pixellint

CAPI still needs a lawful basis

Short answer

Server-side is better at surviving blockers. It is worse at inheriting a CMP that only gated JavaScript. If the user refused ads storage, your webhook still knows the email.

Validate this snippet Open the rulepack

Pass the choice

Store consent with the session or the order, including the TC String and GPP if you have them. Skip CAPI, or send a redacted event, when the basis is missing. Silent always-on CAPI is how you rebuild the tag the user turned off. Consent Mode updates gtag. It does not update your shop backend.

A retry three days later with a new yes you never received is a new processing. If the user refused ads, do not send the CAPI Purchase with fbp, fbc, and em and call it a measurement-only event unless counsel said that sentence. Dropping click ids but keeping email is still a match attempt.

Processors

The ads platform is a recipient. Your CAPI proxy and sGTM host are processors or controllers depending on how you run them. Name them in the policy you already claim is accurate. Many CAPI endpoints do not have gdpr_consent query fields. Then the record of consent lives in your log and in the CMP, and the payload should not include fields you were not allowed to process.

event_source_url, client_ip_address, and hashed PII are the usual over-collection. Do not copy the full user table into user_data because Event Match Quality went up in a dashboard. Gate the whole event, or send a genuinely non-ads pipeline that is not Meta's graph.

Region and action_source

action_source=website, email, app, phone_call, chat, physical_store, system_generated, business_messaging, and other are Meta's nine documented values. They describe where the event happened. They do not describe the lawful basis. A physical_store purchase in the EEA is still in GDPR. An app event after ATT deny can still be a CAPI event with hashed email if you have a basis. It cannot invent an IDFA the OS withheld.

Google Analytics Measurement Protocol is the same split. non_personalized_ads is deprecated in favor of the consent object. Pixellint flags that deprecation on the GA4 pack as vendor.google-analytics.body.non_personalized_ads.deprecated. Wiring the consent object is still your job. The 16-digit timestamp_micros check is a clock check, not a GDPR check.

Check the artifact

Paste the pixel URL or JSON body into the playground. Same engine as pixellint validate. Artifacts you test may be stored; see privacy.