Every meaningful attribution conversation eventually hits the same wall: the data you need to answer a question was never collected. Safari's Intelligent Tracking Prevention limits cookie lifetimes to seven days for cookies set via JavaScript. iOS ATT's global opt-in rate has sat around 25% since Apple introduced the framework. Third-party signals are shrinking. First-party data is the answer, but only if you start collecting it before you discover you need it.

What first-party attribution data actually is

First-party data for attribution is not the same as first-party data for personalisation or CRM enrichment. For attribution purposes, the specific data you need is narrow: how did this user first arrive at your site, what source and campaign brought them, what is the persistent identifier that ties their sessions together across visits, and how does that identifier connect to the CRM contact record created when they converted. This is the causal chain from the first session to the conversion event. Without it, you know that someone became a lead. You do not know what caused them to become a lead, which is the only question that determines where next month's acquisition budget should go.

Three data points to capture on every session

Before any user converts, you have one window to collect attribution data: the session itself. Three specific data points create the foundation. First: the GA4 client_id from the _ga cookie — the persistent identifier GA4 uses to stitch sessions together over time. Read it via JavaScript and store it as a data layer variable. Second: the first-touch UTM parameters. On the user's first session (before your attribution cookie exists), read utm_source, utm_medium, and utm_campaign from the URL and write them to a first-party cookie with a 90-day expiry. Critically: never overwrite this cookie on return visits. The first touch is what you want to preserve. Third: the full landing page URL with all query parameters intact, captured at session start. These three data points cost nothing beyond an afternoon of GTM configuration.

The cookie architecture that survives Safari ITP

Safari ITP limits cookies written via document.cookie (JavaScript-set cookies) to seven days. Cookies set via HTTP response headers by your own server are not subject to the same restriction. The practical implication: if your attribution cookie is set by a JavaScript snippet in GTM, it expires in seven days for Safari users, which represent a substantial share of mobile traffic. The correct architecture is server-set cookies. When a user arrives with UTM parameters, your server reads the query string from the incoming request and sets the attribution cookie in the HTTP Set-Cookie response header. GTM server-side containers can do this: configure a server-side tag to read incoming event parameters and emit a Set-Cookie header in the response. The attribution cookie then behaves identically across browsers and survives ITP.

Connecting session data to your CRM contact record

All of the session-level attribution data above is wasted if it never reaches the CRM. The connection point is the form submission. Every form on your site — demo request, contact, newsletter, any form — should include hidden fields that are populated by JavaScript immediately before the form submits. Those hidden fields carry the GA4 client_id, the first-touch cookie values, and the current page URL. When the form submits, these fields travel through the webhook or CRM native integration and populate dedicated custom fields on the contact record. Two implementation rules matter here: the fields should be write-once, meaning a second form submission from the same contact should not overwrite the original first-touch attribution, and the fields should be required in the form handler, so submissions that fail to capture these values trigger an error you can investigate.