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.