Measurement

AI Traffic Attribution: How to Attribute Conversions From AI Assistants When the Referrer Is Gone

· · 13 min read

AI traffic attribution is the hardest open problem in search measurement, and most of the advice on it is a regex. The regex is necessary. It is also the easy part. It catches the sessions where ChatGPT, Perplexity or Gemini passed a referrer or a campaign parameter, and it says nothing about the sessions where they did not, which for some assistants and some surfaces is most of them. Those visits land in Direct, convert there, and get credited to nothing.

This guide is the method I use to attribute conversions from AI assistants when the referrer is missing. It has four layers: capture everything the assistant does send and stop your analytics discarding it, infer the visits it does not send from landing-page and log evidence, calibrate the inference with a self-reported question, and model the remainder with a control. The output is a range with a floor you can defend and a ceiling you can explain, not a single number. If you want the basic channel-group setup first, it is in how to track AI referral traffic in GA4; this article starts where that one stops.

Key takeaways

  • The referrer is a browser feature, so an assistant’s native app has nothing to send, and even in a browser the default Referrer-Policy sends only the origin on cross-site clicks.
  • ChatGPT’s web app appends utm_source=chatgpt.com to the links it cites, which GA4 reads as a campaign source, so those visits are attributable if you keep the parameter intact.
  • Gemini’s citations carry a text fragment (#:~:text=) that never reaches your server but can be captured by a tag reading the URL hash on landing.
  • Under denied consent, GA4’s cookieless pings still carry the referrer, so source-level counts survive when session-level attribution does not.
  • Report AI conversions as three numbers, observed, probable and self-reported, and let the gap between them be the finding.

Why normal attribution fails for AI assistants

Every attribution model in GA4 starts from the same two inputs: the traffic source of the session, and an identifier that links the session to the conversion. AI assistants damage both.

The source comes from the Referer header or from campaign parameters in the landing URL. The header is set by the browser that made the request, and it is governed by a policy the linking site controls. MDN’s Referrer-Policy reference documents the default as strict-origin-when-cross-origin, which sends the origin, path and query string for same-origin requests and only the origin for cross-origin HTTPS requests. So the best case from a browser-based assistant is a bare origin such as https://chatgpt.com/, with no path that would tell you which conversation or question produced the click. A site that sets no-referrer, or marks a link rel="noreferrer", sends nothing at all.

A native app is worse, because the referrer is a property of a document, and an app is not a document. When a link opens from an assistant’s iOS or Android app into the system browser, there is no page to be the referrer, and the visit arrives with an empty header. Nothing in your analytics configuration can recover a value that was never sent. That is the structural reason AI traffic attribution cannot be solved by configuration alone: the missing sessions are missing at the transport layer.

The identifier is damaged separately. A visitor who arrives from an assistant and declines analytics consent has no cookie, so even a correctly attributed session cannot be joined to a conversion that happens two days later. The same visit is therefore lost twice, once to the referrer and once to consent, and the two losses have to be handled by different layers.

What each assistant actually sends

The honest answer is that it varies by assistant, by surface and by month, and the only durable way to know is to run a referrer census on your own site. Some observations are stable enough to build on.

ChatGPT’s web app appends a campaign parameter to the links it cites. In my own captures of ChatGPT answers this week, every cited URL carried utm_source=chatgpt.com, so a click on one of those links lands with a source GA4 can read directly. That parameter is not a referrer, it is a query string, which changes how you have to handle it. GA4’s campaign documentation says parameter values are case sensitive, that a source without a medium and campaign produces (not set) for the missing fields, and that UTM parameters are omitted from the landing page and page path query-string dimensions and appear only in Page location. Any redirect that drops the query string, any canonicalising middleware that strips unknown parameters, and any report built on the landing page dimension will lose the signal.

Gemini’s citations, in the answers I captured, point at the source page with a text fragment, a #:~:text= suffix that tells the browser which passage to highlight, and in some of the same captures the cited URLs also carried utm_source=gemini, so Gemini is at least partly attributable as a campaign source in the same way as ChatGPT. Fragments are never sent to the server, so neither your access log nor GA4’s default page location sees them. A tag that reads location.hash on the landing page can, which is the same technique the AI Overviews measurement stack uses for Google’s AI features. A text fragment on a landing page is strong evidence that an AI surface was the source even when the referrer is a bare origin or empty.

Perplexity and Copilot pass a referrer from their web surfaces, which the channel-group regex catches. The mobile apps are the gap, for every assistant, and the size of that gap is the number you most want and least have.

The referrer census is how you measure it. For thirty days, log three things for every landing pageview: the raw referrer, the full URL including query string and hash, and the user agent. Do it in a tag, not in GA4, because GA4 has already normalised the values by the time you see them. Then count, per assistant, how many landings carried a usable source and how many carried nothing. The ratio is your site’s own strip rate, and it is the multiplier the later layers depend on.

Layer 1: capture what is sent, and stop GA4 discarding it

The first layer is unglamorous and recovers the most conversions per hour of work. Its job is to make sure that every signal an assistant does send reaches the conversion event.

Start with the landing source. In Google Tag Manager, on the first pageview of a session, read document.referrer, the utm_source parameter and location.hash, and derive a single ai_source value: the assistant’s hostname if the referrer matches one, the campaign source if it is one of the assistant values, or text_fragment if a fragment is present with no other signal. Write that value to a first-party cookie with a thirty-day expiry and send it as a user-scoped custom dimension on every subsequent event, including the conversion. This is the mechanism that survives a Direct session on day one and a conversion on day three: the cookie remembers what GA4’s session attribution forgot.

Keep the parameter intact end to end. Audit your redirects for query-string loss, confirm that your CDN and framework do not strip parameters they do not recognise, and check the Page location dimension in GA4 for the raw value, because the landing page dimension will never show it.

Then handle consent, because it decides what this layer can promise. With consent mode implemented in the advanced pattern, tags load before the banner and, when analytics storage is denied, send cookieless pings instead of setting cookies. GA4’s consent mode documentation lists what those pings can include, and the referrer is on the list, alongside the user agent and a timestamp. That means the count of landings from chatgpt.com or perplexity.ai still reaches Google under denied consent, even though no session or user identifier does. Source-level volume survives; conversion joins do not. Under a basic implementation, where tags are blocked until consent, neither survives, and the documentation is explicit that the property then gets no modelled data. If your banner blocks tags, this layer has a hole exactly the size of your reject rate, and the fix is in the cookie banner guide.

Finally, move the conversion join server-side where you can. A server-side GTM container or a first-party conversion endpoint that records ai_source from the cookie at the moment of conversion does not depend on GA4’s session model at all. It is the setup I build for clients through full-funnel tracking, and for AI traffic attribution it matters more than for any other channel, because it is the only place the thirty-day cookie and the conversion meet without GA4 in between.

Layer 2: infer what is not sent

Layer 1 gives you the observed floor. Layer 2 estimates the visits that arrived with nothing, and it does so from two kinds of evidence you already have.

The first is the shape of Direct traffic. Classic Direct is dominated by the home page, the login page and short brand URLs, because those are what people type or bookmark. An assistant sends people to deep, specific pages: a comparison article, a pricing page, a documentation section that answers one question. Build a segment of Direct sessions that land on URLs which historically received almost no Direct traffic, and watch what happens to it over time against the observed AI channel. It is the closest thing to an AI-probable Direct count that analytics data alone can give you, and it must be reported as probable, never as observed.

The second is your access log. The user-initiated agents that assistants use while composing answers, ChatGPT-User, Claude-User and Perplexity-User, fetch the pages they are about to cite, and those fetches are visible and verifiable in your logs. AI crawler log analysis covers how to verify and count them. A landing page with a high rate of verified user fetches and a rising share of deep Direct landings is a page that assistants are actively sending people to. Weight the probable segment by that fetch rate and you have a per-page estimate that is grounded in server evidence rather than in a guess about user behaviour.

Add the text fragment signal from Layer 1 here as well. A Direct landing with a #:~:text= fragment is not classic Direct, whatever the referrer says, and should be moved into the probable count outright.

Layer 3: self-reported attribution, done properly

The self-reported question, “how did you hear about us”, is the only layer that can see a mobile-app visit, and it is usually thrown away because it is treated as a number rather than as a calibrator.

Ask it at the point of conversion, not on a pop-up, with a short list that names the assistants explicitly. “ChatGPT, Claude, Gemini or another AI assistant” as one option outperforms a vague “AI” line, and the order of options should rotate. Record the answer as an event parameter on the conversion so it sits next to ai_source from Layer 1.

Then use it the right way. Split conversions into those with an observed AI source and those without. Among the observed group, the share who also self-report AI is your under-reporting rate for the question; people forget, skip and misremember, and this tells you by how much. Among the group with no observed source, the self-reported AI share, corrected by that rate, is an independent estimate of the stripped-referrer conversions. When it lands inside the range Layer 2 produced, you have two methods agreeing from different evidence, which is as close to proof as attribution gets. When it does not, one of the two layers is wrong, and finding out which is worth a week of anyone’s time.

Layer 4: modelled attribution with a control

The last layer is for teams who need a defensible incremental number rather than a corrected count. It is also the layer most likely to be done badly, so keep it small.

The question is whether AI-referred visitors convert differently from the visitors you would have had anyway, because if they do, then crediting probable-AI conversions at the classic Direct rate is wrong in a known direction. The comparison is between two groups: sessions with an observed AI source, and Direct sessions on the same landing pages in the same weeks. The landing page match is what makes this a control, because it removes the difference in page intent that otherwise dominates. If the observed AI group converts at a materially different rate from matched Direct, apply that ratio to the probable segment rather than the site average.

Two constraints keep the model honest. Use conversion rates, not counts, because volumes are small and noisy. And run it on a rolling window of at least eight weeks, because the assistants change what they send without notice, and a ratio computed in a month when one of them switched behaviour will mislead the next quarter.

Reporting: three numbers and a range

The deliverable for AI traffic attribution is a small table, refreshed monthly, with three rows per conversion type.

RowSource of evidenceWhat it can claim
ObservedReferrer, utm_source, text fragment, thirty-day cookieFloor. These conversions came from an assistant.
ProbableDeep-Direct segment weighted by verified user fetchesEstimate. Report with the method, not as fact.
Self-reportedCorrected conversion-form answersIndependent check on the probable row.

The number to present is the range between observed and the larger of probable and self-reported. When the range is narrow, the assistants are sending usable signals and you can plan on the midpoint. When it is wide, the gap is itself the finding: it tells you how much of the channel is invisible, and it is the argument for the server-side join and the consent implementation that shrink it.

One thing not to do is fold Google’s AI features into this table. Clicks from AI Overviews and AI Mode are counted inside the Web search type in Search Console, per Google’s documentation, and they arrive as organic search in GA4. They are a Google organic question with their own method, and mixing them into assistant attribution overstates both.

Frequently asked questions

Why does ChatGPT traffic show up as Direct in GA4?

Because the visit arrived without a referrer or campaign parameter. ChatGPT’s web app appends utm_source=chatgpt.com to cited links, and those visits are attributed correctly if the parameter survives your redirects. Visits from the mobile app, and any link where the parameter was stripped, carry nothing GA4 can read, so they fall into Direct. The fix is to capture what is sent on landing, store it in a first-party cookie and infer the rest from landing-page patterns.

Can I attribute a conversion to an AI assistant if the user declined cookies?

Only at the source level, not at the conversion level, unless you join the two yourself. Under advanced consent mode GA4 still receives cookieless pings that include the referrer, so it can count landings from an assistant, but with no identifier it cannot connect that landing to a later conversion. A first-party cookie you set with the user’s consent, or a server-side conversion record, is the only way to keep the join.

What is the difference between AI referral traffic and AI traffic attribution?

AI referral traffic is the set of sessions whose source GA4 can identify as an assistant. AI traffic attribution is the work of crediting conversions to assistants, including the sessions GA4 cannot identify. The first is a reporting configuration. The second needs inference and calibration, because the referrer is often missing.

How accurate is the “how did you hear about us” question for AI?

On its own, not very, because respondents forget and skip. Used as a calibrator it is valuable: the share of conversions with an observed AI source who also self-report AI tells you the under-reporting rate, and applying that rate to conversions with no observed source gives an independent estimate to compare against the landing-page inference.

Should AI Overview clicks be included in AI assistant attribution?

No. Google reports AI Overview and AI Mode clicks inside ordinary web search in Search Console, and they arrive as organic search in analytics. They need their own method, and adding them to assistant attribution inflates both numbers.