pixellint

Pixels · engineers

no-referrer means the collector guesses

Referrer-Policy: no-referrer is good privacy on outbound links. It is also why a CAPI event has a blank event_source_url if you copied document.referrer instead of location.href. The referrer is the previous page. The source URL is the page you are on.

Send the page you are on

event_source_url (Meta CAPI) and page_location / dl (GA4) should be the current document URL, location.href, not the referrer. The referrer is the previous page. Mixing them makes Meta think the purchase happened on google.com or on an empty string. Pixellint flags a website action_source with no event_source_url. It cannot know you sent the search engine instead of /thank-you.

In the browser pixel, Meta infers page from the document unless you override. In CAPI you must send it. A Node job that sets event_source_url to process.env.SITE_URL always, ignoring the actual checkout path, collapses every event onto the homepage. Store the request URL of the page that produced the event, or the canonical thank-you URL including HTTPS and host.

What each policy strips

no-referrer: nothing is sent. origin: scheme plus host, no path, no query. origin-when-cross-origin: full URL same-origin, origin only cross-origin. strict-origin-when-cross-origin is the common browser default: full URL same-origin, origin on HTTPS to HTTPS cross-origin, nothing on HTTPS to HTTP. no-referrer-when-downgrade is the old default. same-origin and strict-origin are stricter still.

A third-party pixel is a cross-origin request. Under strict-origin-when-cross-origin, document.referrer inside a callback is origin-only or empty depending on how you read it, and the Referer header the collector sees is origin-only. Click ids in the previous URL are gone. Path is gone. If your matching scraped gclid from the referrer, it is dead. Read click ids from the landing URL on first party, store them, send them as gclid or fbc.

Click ids in the referrer

Some old setups scrape gclid from document.referrer after a Google Ads click, because the landing page redirected and they thought the referrer would keep the query. A policy of origin-when-cross-origin or stricter deletes it. So does an intermediate redirect that does not forward the query. So does a referrer that is google.com/aclk without the id depending on Google's own policy.

Do not restore this by loosening Referrer-Policy to unsafe-url on the whole site. You will leak paths and PII in query strings to every third-party script. Store gclid on arrival. First-party cookie, first-party server, then CAPI. The referrer is not a warehouse.

PII rides Referer

If your own URLs contain emails (?email=buyer@example.com), a full referrer leaks them to every third-party pixel that receives Referer. That is a reason to tighten policy and a reason to stop putting PII in query strings. A Meta pixel with em=buyer@example.com is also a finding on the URL itself (vendor.meta.pii.unhashed_email). The Referer leak is the copy that hits every other vendor on the page.

Fragments never reach the server (core.url.fragment_ignored). They also do not ride Referer the way query strings do. Do not hide PII in the fragment and then read it from referrer; it was never a safe channel. Hash in the browser or on the server, POST a body, keep emails out of the address bar.

Outbound links versus pixels

You can set Referrer-Policy per request (Referrer-Policy header, meta, rel=noreferrer on an <a>). A strict policy on outbound affiliate links is good. A strict policy that also blanks event_source_url because your CAPI mapper used document.referrer is a self-own. Split the concerns: noreferrer on <a target=_blank>, location.href on measurement.

Iframes add another referrer: the parent. A pixel in a Stripe frame with a full referrer policy may send stripe.com, or your checkout URL, depending on who set what. Do not guess. Log the event_source_url you actually POST. Compare it to the merchant thank-you URL. If they differ, fix the mapper, not the ads manager attribution window.

Check the artifact

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