pixellint

Pixels · engineers · PMs

The vendor host cannot see your cookie jar

A pixel loaded from facebook.com or google-analytics.com is third-party storage. Safari already treated that as hostile. Everyone else is catching up. Matching moved to first-party cookies (_fbp, _ga), click ids in the URL, and server events that send those values back.

Third-party: the cookie on their host

The collector sets a cookie on its own domain. facebook.com sets identifiers the Meta pixel historically read on later hits to facebook.com/tr. google-analytics.com did the same for older analytics cookies. That model is useful when the same id should follow the user across publishers. It is also the model ITP, ETP, and Chrome partitioning exist to break.

If your only identifier is a third-party cookie, expect match rates to look like a 2017 case study in the ads manager and like a 2026 outage in the warehouse join. The request still returns 200. The cookie is missing, partitioned, or expired. You cannot see that in GTM preview. You see it in the request's Cookie header, or in the absence of one.

_fbp, _ga, and friends on your host

_fbp is Meta's first-party browser id, set on your domain by the pixel as fb.1.timestamp.random. _fbc is the click id cookie, fb.1.timestamp.fbclid_value, written when fbclid is on the landing URL. _ga is GA4's client id cookie; the collect hit also sends cid explicitly. _gcl_aw holds the Google Ads click id after auto-tagging. First-party ttclid-style cookies are the TikTok analogue.

The JS tag writes them. Your CAPI call should send them back (fbp and fbc in user_data, client_id on Measurement Protocol). Losing them on a subdomain, a consent wipe, or a cookie domain that does not cover checkout is a silent matching failure. HttpOnly cookies your tag cannot read will never make it into a CAPI payload unless the server sends them. If checkout is shop.example.com and the pixel ran on www.example.com with cookie domain www only, _fbp never arrives at Purchase.

CHIPS partitions third-party cookies

Cookies Having Independent Partitioned State (CHIPS) lets a third-party set a cookie with Partitioned, keyed by the top-level site. The facebook.com cookie set on publisher-a.com is not the one set on publisher-b.com. Cross-site retargeting that assumed one jar is done. Your own first-party _fbp is not a CHIPS cookie; it is your host. Do not expect CHIPS to restore 2017 cross-site ids. It is a way for embedded third parties to keep per-site state, not a global id.

If a vendor still sets an unpartitioned third-party cookie, Chrome may reject or partition it depending on the phase of the privacy sandbox rollout you are in. QA in one Chrome profile is not QA. Check Safari, Firefox, and a Chrome profile with third-party cookies blocked. The pixel URL can be valid in all three while the cookie story is not.

ITP is not a pixel syntax bug

Safari Intelligent Tracking Prevention caps and expires cookies it classifies as trackers. Third-party cookies were first. Then seven-day caps on first-party cookies set by a tracker-classified script. Then CNAME-cloaked first-party hosts. Bounce tracking mitigations expire storage that looks like a bounce tracker. None of these change whether facebook.com/tr has a numeric id and an ev. They change whether _fbp from last month is still there.

Design for click ids on the landing URL (fbclid, gclid, ttclid) written into first-party storage you control, and for server events that reuse those values. A pixel that is syntactically perfect and a match rate that fell off a cliff after an iOS release is ITP, not a missing cd[currency]. Do not CNAME-cloak collect.example.com to a vendor to dodge ITP; Safari classified that. sGTM on infrastructure you own is a different design.

What to send when the cookie is gone

Click ids in the URL, stored on first hit, sent on conversion. Hashed email and phone that the user typed, not scraped from a URL. IP and user-agent unhashed, because vendors match those in the clear. event_id so a browser hit and a CAPI hit collapse. That bundle survives third-party cookie death. A hope that facebook.com will still have a cookie from a display impression on another site does not.

When you debug a low EMQ, look at whether fbp and fbc are present on the CAPI payload, whether cid is on /g/collect, and whether the Cookie header on the browser pixel includes _fbp. A valid URL with no identifiers is a valid miss. Pixellint will not invent a cookie for you; it will tell you if em looks like an unhashed email.

Check the artifact

Paste the pixel URL or JSON body into the playground. Same engine as pixellint validate. Nothing leaves the tab.