pixellint

CAPI · engineers

Your API host is not a landing page

The field is named like a referrer. It is not. It is the page. On a SPA, that is the route at conversion time, including query if the query is part of the page identity, excluding tokens if the query is a session secret.

Required when the source is the web

Meta requires event_source_url when action_source is website. vendor.meta-conversions-api.body.website_requires_source_url. Snap requires it when action_source is WEB (vendor.snapchat.body.web_requires_source_url). The field is a URL, not a path, not a host, not the Graph API edge you posted to.

TikTok's Events API carries page context separately from Meta's name, but the job is the same: the page the user was on, not the collector. If your backend never saw the browser URL, you cannot invent a useful one at send time.

Pass it in with the order

Your worker does not know the URL unless the browser told it, or you stored it at landing. Put it on the order, or accept it on the CAPI proxy from the page. Hosted checkouts are the usual hole: the thank-you host is Shopify or Adyen, and your API host is api.example.com. Send the thank-you URL the customer actually loaded, or the last first-party route you owned before the hop.

A SPA should send the route at conversion time, including query if the query is the page identity (product id, order id), excluding tokens if the query is a session secret. location.href copied blindly from a logged-in account page will leak.

HTTPS and verified host

Vendors compare the host to your verified domain. http://localhost:3000 in production events is how test traffic poisons the graph. Staging should use test_event_code (Meta) or a separate pixel, not a prod token with a localhost URL.

http versus https, www versus apex, locale prefixes: pick the canonical host you verified. A mix of www.example.com and example.com in event_source_url looks like two sites. It is one site with two strings.

PII in the URL

If the thank-you URL contains the email, do not forward it. You will leak PII into a field that is logged widely (your APM, the vendor, every proxy). Canonicalize to path plus order id. Hashing user_data.em does not erase the raw address sitting in event_source_url.

Referrer-policy on the pixel request is a different leak (the next hop sees document.referrer). event_source_url is a field you chose to send. Treat it as a log line you published on purpose.

The API path is the usual helper bug

A shared CAPI client that defaults event_source_url to the incoming request URL will send https://api.example.com/webhooks/stripe on every Purchase. Domain quality drops. Catalog and landing reports attach to a host that never ran fbq.

Default to empty and fail closed (Meta will error on website without the field) rather than defaulting to the server URL and shipping quietly bad data.

Page, not collector

Wrong is the webhook URL. Right is the page the shopper saw.

// Wrong
{
  "action_source": "website",
  "event_source_url": "https://api.example.com/capi/meta"
}

// Right
{
  "action_source": "website",
  "event_source_url": "https://shop.example/thanks?order=1842"
}

pixellint validate json @payload.json --rulepack vendor/meta-conversions-api
# vendor.meta-conversions-api.body.website_requires_source_url
# when action_source is website and event_source_url is missing

Check the artifact

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