pixellint

Own the number before you own the tag

The expensive mistakes are product mistakes: Purchase on the landing page, no owner for GTM, staging ids in production. The validator catches syntax. You catch intent. These pages are the ones to send the room before kickoff.

Validate a pixel or CAPI All docs

Pixels and tags

How does a tracking pixel differ from a cookie? PixelsmarketersengineersPMs A tracking pixel sends an event to a collector. A cookie stores a value that may be sent with a later request. See what survives when cookies are blocked and how to inspect both in DevTools. How do Meta Pixel and Google Ads conversion tags compare? PixelsmarketersengineersPMs Meta Pixel and Google Ads tags can report the same purchase to different ad systems. Compare their event names, conversion IDs, click identifiers, deduplication, and QA steps. What is a tracking pixel PixelsPMsmarketersengineers A tracking pixel is an HTTP request that records an ad impression, click, page view, or conversion. The transport may be a 1x1 image GET, navigator.sendBeacon, or fetch. Email open pixels and VAST Impression beacons are the same job on different surfaces. Impression pixels vs click trackers PixelsmarketersPMsengineers An impression pixel fires when the creative loads and should return 200 with a 1x1 or 204. A click tracker fires on click as a 302 chain. Never 302 an impression to a landing page. View-through is a report setting, not a third pixel. Conversion pixels vs S2S postbacks PixelsPMsmarketersengineers A conversion pixel fires in the browser on the thank-you page. An MMP postback is a server-to-server GET or POST with macros expanded at conversion time. CAPI is a JSON POST to the vendor. They fail in different ways. Unexpanded macros on a fired postback are a trafficking bug. First-party vs third-party cookies on pixels PixelsengineersPMs Third-party cookies on facebook.com or google-analytics.com are blocked or partitioned in Safari, Firefox, and Chrome. First-party pixels set _fbp and _ga on your domain. CHIPS partitions third-party cookies by top-level site. ITP expires tracker-like storage. Matching moved to click ids and server events. SPA pageviews PixelsengineersPMs Single-page apps do not reload the document. If you only fire PageView on first load, checkout and thank-you routes are invisible. Hook history. React 18 Strict Mode double-mounts and will double Purchase. Meta CAPI event_source_url must be the current route, not the first URL of the session. UTM parameters vs click ids PixelsmarketersPMsengineers utm_source, utm_medium, utm_campaign, utm_content, and utm_term are for your analytics property. Google Ads, Meta, and TikTok attribute paid clicks with gclid, fbclid, and ttclid. UTM is not a click id. Casing splits sessions. Do not put gclid in utm_content and expect Ads to see it. Landing page vs thank-you page pixels PixelsmarketersPMsengineers PageView belongs on the landing page, where click ids are stored. Purchase belongs on the thank-you page, once. Hosted checkout (Shopify, Stripe Checkout) often means the thank-you page is another host, so cookies and click ids must travel or the conversion fires as a new user. Firing Purchase on every landing inflates ROAS until the platform discounts you. Bots, prefetch, and invalid traffic on pixels PixelsengineersPMsmarketers Prefetch, Slack unfurls, Gmail image proxies, and link scanners fire pixels without a user. Platforms filter invalid traffic in the UI. Your BigQuery export of raw hits will not match. Gate conversion tags on a real order id, not on DOM Ready of a public URL. Ad blockers and tracking pixels PixelsengineersmarketersPMs Ad blockers drop known pixel hosts from EasyList and similar lists. GTM preview can say the tag fired while facebook.com/tr never leaves the machine. Noscript does not bypass a host block. Recovery is CAPI or sGTM on a first-party collector you operate, not a second request to the same listed host. PII in pixel query strings PixelsengineersPMs Raw emails, phones, and names in a pixel URL land in vendor logs, CDN logs, and Referer headers. Meta flags unhashed emails on facebook.com/tr as vendor.meta.pii.unhashed_email. Hash SHA-256 of a normalized email in a body field, or use CAPI. Image pixels cannot hash in the browser. First-party collectors and CNAME cloaking PixelsengineersPMs Serving a vendor collector from metrics.example.com via DNS CNAME can dodge some blocklists. Safari classified CNAME-cloaked trackers. Certificate automation and subdomain takeovers become your incident. Server-side GTM on infrastructure you own is a different design: you send the event, you do not pretend facebook.com is you.

Conversion APIs

One conversion API JSON cannot serve every vendor CAPIengineersPMs Meta Conversions API event_time is seconds. Reddit CAPI event_at is milliseconds. LinkedIn conversionHappenedAt is milliseconds and still needs user.userIds. TikTok timestamp is ISO 8601. A shared conversion API event named event_time will be wrong on at least one hop. How do GA4 key events and Google Ads conversions compare? ConversionsmarketersPMsengineers A GA4 key event marks an important site action. A Google Ads conversion action can be created from that Analytics event or measured with an Ads tag. Learn why counts diverge and what to check before bidding. How does conversion tracking differ from attribution? ConversionsmarketersPMsengineers Conversion tracking records an action. Attribution assigns credit to earlier marketing touchpoints. Diagnose a missing event, missing click ID, and differing dashboard totals in the right order. What is a conversion API CAPIPMsmarketersengineers A conversion API is a server POST that sends conversion API events. Meta names it the Conversions API (CAPI). Facebook CAPI and Meta CAPI are the same Graph events edge. TikTok names it Events API. Google names it Measurement Protocol. Same job, incompatible JSON. Pixel plus conversion API events CAPIengineersmarketersPMs CAPI implementation is browser pixel plus conversion API events, deduplicated on event_id. Drop either side without a plan and you undercount or double-count. Meta CAPI and Facebook CAPI document this hybrid. Event deduplication CAPIengineersPMs Meta, TikTok, and others drop a duplicate conversion when the same event_id arrives on the pixel and the conversion API. Generate it once, persist it, send it on both pipes. Event match quality CAPImarketersengineersPMs Match quality is how confidently the platform attaches your event to a user. Click ids score high. Hashed email and phone help. IP plus user-agent are weak but real. Empty user data is a dark event. Server-side tagging CAPIengineersPMs Server-side Google Tag Manager is a first-party collector that forwards to vendors. Direct CAPI from your backend skips the tag manager. Both are server events. They are not the same architecture. HTTP 200 is not conversion validation CAPIengineersPMs PostHog capture, Segment track, and several ads CAPIs return 200 for payloads they will not ingest. Validate the body before you ship. Do not use status code as the contract. Offline conversions CAPIPMsmarketersengineers Offline conversions upload events that never happened in the browser: phone sales, in-store POS, Salesforce stages. Matching is PII-heavy. Timestamps are usually delayed. Dedup against any pixel you already fired. Standard vs custom events CAPImarketersengineersPMs Pinterest standard events are lowercase (pagevisit, checkout, addtocart). Meta is PascalCase (Purchase, Lead, AddToCart). Snap is UPPER_CASE. A typo becomes a custom event and still 200s. Funnel events CAPImarketersPMsengineers Funnel events exist so the platform can optimize toward the next step. Firing all of them on the thank-you page teaches the model that every user is a buyer. Firing none of them except Purchase starves upper-funnel learning. Refund and cancel events CAPIPMsmarketersengineers If you send Purchase and never send Refund, the ads platform keeps spending toward orders that came back. Meta, GA4, and several CAPIs have refund events. Use the original transaction id. Conversion API validator CAPIengineersmarketersPMs A conversion API validator checks CAPI JSON against the vendor contract: Meta CAPI and Facebook CAPI event_time in seconds, hashed em, action_source, event_source_url, Purchase value and currency. Paste the body. HTTP 200 is not that check.

Identity and matching

Click ids IdentitymarketersengineersPMs Paid platforms join conversions on click ids: gclid, fbclid, ttclid, msclkid, li_fat_id, twclid. UTMs do not replace them. Capture on the landing URL and send them again on the conversion. client_id vs external_id vs Firebase app instance IdentityengineersPMs GA4 client_id is the analytics browser id. Meta external_id is your customer key, hashed. Firebase app_instance_id is the app stream id. They are not aliases. Do not paste one into the other field. distinct_id IdentityengineersPMs PostHog requires distinct_id on every capture, including each batch row. Mixpanel joins on properties.distinct_id. Segment uses userId or anonymousId, which destinations often map to distinct_id. Identity graphs vs your CDP IdentityPMsengineersmarketers Meta, Google, and the CDPs each keep a graph you do not own. You send hashed PII, click ids, and cookies. You do not download their device graph. Matching is a payload problem, not a warehouse join you can copy. Intelligent Tracking Prevention IdentityengineersPMs Safari Intelligent Tracking Prevention blocks third-party cookies and caps first-party cookies that look like trackers. _fbp and _ga will expire sooner than your tag's max-age. Design for click ids and server events. CNAME cloaking is classified. Cross-domain tracking IdentityengineersmarketersPMs Checkout on another host drops first-party cookies and often the click id. Shop.example.com does not see _fbp from www.example.com unless Domain=.example.com. Forward gclid, fbclid, and the cookies you need, or fire CAPI from the order. GA4 linker uses _gl.

Time and attribution

Consent and privacy

TCF v2 consent strings on pixels ConsentengineersPMsmarketers gdpr must be 0 or 1. gdpr=1 needs a TC String in gdpr_consent. Pixellint decodes the string. gdpr_consent=1 and gdpr_consent=true are valid base64 and still not a TC String. Core reads query string and Floodlight-style path parameters. Global Privacy Platform strings ConsentengineersPMs A GPP string has header type 3. A TC String pasted into gpp decodes as type 2. gpp needs gpp_sid so the callee knows which section is in force. The spec does not require sid to match sections inside the string. Pixellint does not invent that check. IAB US Privacy string ConsentengineersPMsmarketers The IAB US Privacy string is a version digit plus three Y, N, or hyphen characters. Only version 1 was published. IAB Tech Lab deprecated it on 31 January 2024 in favor of GPP. Pixellint still checks the shape and always warns that the parameter is deprecated. Google Consent Mode v2 ConsentengineersmarketersPMs Google Consent Mode is a gtag or GTM signal for ad_storage, analytics_storage, ad_user_data, and ad_personalization. It is not a CMP and not a TC String. Default denied, then update on choice. EEA traffic without the v2 keys is a policy problem, not a pixel syntax problem Pixellint invented. Cookie banners vs actually blocking tags ConsentPMsengineersmarketers A banner that does not wrap tags still fires pixels on first paint. Blocking means the tag does not queue until granted, or Consent Mode defaults to denied. UX copy is not a technical control. Network tab on a fresh profile is the audit, not a screenshot of the modal. GDPR and server-side conversion APIs ConsentPMsengineers Moving the pixel to CAPI does not move you out of GDPR. You still need a lawful basis, a processor story, and a way to respect refusal. Hashing an email is not anonymization. The vendor 200 is not a legal opinion. Consent Mode does not update your shop backend. Meta Limited Data Use ConsentengineersPMs Meta Limited Data Use is dpo=LDU plus a country and usually a state. dpoco=1 is the US. Country without state lets Meta geolocate. Pixellint flags that as vendor.meta.ldu.country_without_state. On CAPI, data_processing_options_country is required when LDU is sent. App Tracking Transparency ConsentengineersPMs ATT is the iOS prompt. IDFA is the advertising identifier you may read after authorize. Denied ATT does not forbid first-party CAPI with hashed email you collected in-app. It does forbid IDFA. All zeros means denied. Do not hash IDFA like email unless the MMP field is documented as hashed. COPPA and restricted data in measurement ConsentPMsengineers Child-directed apps and mixed-audience properties cannot treat ads pixels as default. Flag child-directed traffic in the vendor's restricted data processing settings. Hashing an email you should not have does not help. Pixellint does not invent a COPPA rulepack. The vendor 200 is not permission. Data retention for pixels and CAPI logs ConsentengineersPMs Pixel query strings, CAPI bodies, HARs, Segment archives, and sGTM logs are identifier stores. Keep them as short as the debug job requires. A six-month access log of hashed emails is still a dossier. Pixellint flags a raw email on a live artifact. It will not scrub the file you already uploaded. Privacy Sandbox ConsentPMsengineers Third-party cookies are already gone in Safari and Firefox. Chrome moved to user choice and Privacy Sandbox APIs. Topics and Attribution Reporting are not a pixel with a different host. Keep CAPI while you learn them. Privacy Sandbox does not waive GDPR or a CMP. Pixellint does not validate Topics values. Attribution Reporting API vs conversion pixels ConsentengineersPMs The Attribution Reporting API sends delayed, noisy aggregate reports (and limited event-level reports) from the browser. It is not a conversion pixel you can paste into a HAR validator. Keep enhanced conversions and gclid. Pixellint does not validate Attribution-Reporting-Register-Source headers. Consent revocation on the wire ConsentengineersPMsmarketers Granting consent is a request the vendor can see. Revoking it often is not. A banner that shows a new choice while Floodlight, Meta, and CAPI keep the old string is a withdraw that never left the page. Lint the hop after refuse, not only after accept.

Mobile and MMP

MMP server-to-server in-app events MobileengineersPMs Adjust, AppsFlyer, and Branch S2S endpoints are contracts: required tokens, device ids, clocks, and unhashed IP. A 200 from the MMP does not mean the event was recorded. Validate the body before you retry. Pixellint packs encode the documented fields, not SKAN postbacks. SKAdNetwork vs MMP MobilePMsengineersmarketers SKAdNetwork attributes iOS campaigns with a conversion value and a delayed Apple postback. It is not a click id, not an MMP device id, and not a replacement for S2S in-app events. Map values on purpose or the postback is a coin flip. Pixellint does not validate SKAN postbacks. App install vs session vs in-app events MobilePMsmarketersengineers Install, first open, session, and in-app purchase are different MMP events. Firing purchase on first open inflates ROAS. Firing install on every session inflates CPI. Name the event the vendor catalog uses, then S2S it once. Adjust tokens are opaque. AppsFlyer eventName is a string. Branch distinguishes standard and custom endpoints. Web-to-app measurement MobilePMsengineersmarketers A paid click on the web that converts in the app needs a bridge: MMP, Meta app events, or SKAN. The web pixel alone stops at the store page. Store the web click id before the user leaves for the store. action_source=app on CAPI. Do not fire website Purchase when the charge happened in IAP. IDFA vs GAID MobileengineersPMs IDFA vs GAID: IDFA is iOS advertising, gated by ATT. GAID is Android advertising (gps_adid, aaid, advertising_id). IDFV is per-vendor on iOS, not an ads cookie. Sending the wrong one in the wrong MMP field looks populated and matches nobody. Zeros means denied. In-app purchase events MobileengineersPMs Store receipts are the source of truth for IAP. SDK-observed purchases can fire twice, fire on restore, or fire before charge. Validate with Apple or Google, then S2S to the MMP with the real value and ISO currency. Restores are not purchases. A 200 from the MMP does not prove the revenue dashboard moved. Probabilistic mobile attribution after ATT MobilePMsengineers Probabilistic matching (IP, user-agent, time) filled gaps when IDFA was everywhere. After ATT it is noisier. SKAN, consented IDFA, and deterministic MMP clicks are the planned replacements, not a better fingerprint. Do not hash IP. Pixellint flags hashed IP on Adjust and AppsFlyer. It will not tell you the unhashed IP was CGNAT.

Analytics and CDP

GA4 Measurement Protocol AnalyticsengineersPMs GA4 MP needs api_secret and exactly one of measurement_id (G- form) or firebase_app_id. timestamp_micros is 16 digits. Purchase needs currency, value, transaction_id, and items. HTTP 204 is not a schema review. PostHog capture AnalyticsengineersPMs PostHog documents that a capture missing event or distinct_id still returns 200 and is not ingested. Send ISO 8601 for event time. Do not treat status code as a contract test. Segment track AnalyticsengineersPMs Segment's HTTP Tracking API track call needs an event name. The HTTP 200 does not check it. anonymousId or userId still have to exist if you want a person, not a floating event. Mixpanel track AnalyticsengineersPMs Mixpanel joins on distinct_id. Engage/identify must reuse it. Time is epoch seconds in some Mixpanel APIs and not others; read the endpoint you POST to, not a blog from 2016. CDP vs ads pixels vs product analytics AnalyticsPMsengineersmarketers A CDP (Segment and friends) routes events. An ads pixel or CAPI is a bid and attribution pipe. Product analytics is product. One track() call is not automatically all three jobs done well. Event volume, sampling, and pixel QA AnalyticsengineersPMsmarketers GA4 UI sampling and Mixpanel bookkeeping hide rare broken payloads. QA on 20 events will never see the 1% of Purchases missing currency. Sample raw exports or contract-test fixtures. Product analytics vs ads conversion pixels AnalyticsPMsengineersmarketers Product analytics wants funnels and retention. Ads pixels want matchable conversions for bidding. Sharing one Purchase event is fine. Sharing one schema without a map is how both teams think the other is wrong.

Launch and QA

Vendor playbooks