To track ChatGPT traffic, match the HTTP referrer against a list of known assistant hostnames on the first pageview of a visit, check the URL query string for the utm_source values the assistants add themselves, and store whichever signal fires as a person-level property that survives the rest of the journey. You need both signals, because the assistants strip referrers on some surfaces and tag links on others. You need person-level storage, because the person who arrives from ChatGPT on Tuesday usually converts on Friday, by which point a session-scoped source has already been overwritten.
GA4 will not do this for you reliably. That is not a configuration mistake on your part, it is a structural property of how AI assistants send traffic. This guide covers what actually reaches your server, how to capture it, and what portion of the channel is genuinely unrecoverable no matter what you do.
Where our own AI-referred visitors came from
LLM Acquisition viewWhy AI Traffic Is Invisible in GA4
There are four separate mechanisms pushing AI referrals into the wrong bucket. They compound, which is why the undercount is usually severe rather than marginal.
Native Apps Send No Referrer
When someone clicks a link inside the ChatGPT desktop app, the Claude macOS app, or either of their mobile apps, the operating system hands the URL to the default browser as a fresh navigation. There is no Referer header because there is no originating web page. Your server sees a cold request with no provenance at all. GA4 classifies it as Direct. This is not a bug in anyone’s implementation, it is how the OS-level URL handoff works, and it applies identically to links opened from Slack desktop, from a PDF, or from a native email client.
The share of assistant usage happening in native apps rather than in a browser tab is substantial and growing, which means the fraction of AI traffic that is invisible by default is also growing.
Referrer Policy Strips What Is Left
Even on the web surfaces, the referrer you receive depends on the sending page’s Referrer-Policy header. Under strict-origin-when-cross-origin, which is the modern browser default, you get the origin (https://chatgpt.com/) but not the path, so you can identify the assistant but never the specific conversation or answer. Under no-referrer or origin-when-downgrade edge cases, you may get nothing. Any redirect hop on your side, including a plain non-www to www 301, can downgrade or drop the header entirely.
Sessions Expire Before the Conversion Does
GA4 attributes on a session model with a default 30-minute inactivity timeout and a channel that gets reassigned on the next campaign touch. Someone who reads a ChatGPT recommendation, visits your comparison page, closes the tab, and signs up three days later after a Google search gets attributed to organic search. The AI touch is recorded, then buried. Our guide on multi-touch attribution covers why last-touch models systematically undervalue discovery channels, and AI assistants sit almost entirely on the discovery side.
The (not set) and Direct Sink
The practical result is a growing pile of unattributed traffic. If you are already investigating a swelling (not set) source / medium bucket in GA4, some meaningful share of it is now AI referrals. The tell is entrance pages: direct traffic to your homepage is normal, direct traffic to a deep comparison page or a specific docs URL that nobody would ever type from memory is not.
The Referrer Domains That Do Show Up
When a referrer does survive, it comes from a short and fairly stable list of hostnames. These are the ones worth matching:
- OpenAI:
chatgpt.comand the olderchat.openai.com. Both still appear. - Anthropic:
claude.ai. - Perplexity:
perplexity.aiandwww.perplexity.ai. - Google:
gemini.google.com, plus the legacybard.google.com. - Microsoft:
copilot.microsoft.com, andbing.comchat surfaces where the referrer is not rewritten to plain Bing search. - Others worth including:
you.com,poe.com,chat.mistral.ai,grok.com,duckduckgo.com/aichat.
Match on hostname suffix rather than exact string, so www.perplexity.ai and perplexity.ai both resolve to the same assistant. Do not match on substring against the full URL, because that produces false positives on your own pages that happen to contain those words in a query parameter.
The Tagged-Link Signal
Separately from the referrer, several assistants append a campaign parameter to outbound links on some surfaces. The most common form is ?utm_source=chatgpt.com. Perplexity and Copilot have used similar tagging. This is the signal that survives when the referrer does not, which is why detection has to check both and treat either as sufficient.
There is a trap here. If your analytics obeys UTM parameters as the highest-priority source and something in your own stack strips or rewrites query strings, you lose the only surviving signal. Check whether your CDN, your consent management platform, or your canonical-URL redirect is dropping unknown query parameters before you conclude the tagging is not there.
Building UTM-Independent Detection
The goal is a detection layer that fires on either signal, resolves to a normalised assistant name, and persists that name against the person rather than the visit.
Detection order of operations
Read the referrer server-side if you can
The Referer header at your edge or origin is more reliable than document.referrer, which is lost across client-side redirects and blanked by some privacy extensions.
Normalise the hostname
Parse to a hostname, strip the www prefix, and match against your assistant list by suffix. Resolve chat.openai.com and chatgpt.com to the same label.
Fall back to the query string
If no referrer matched, check utm_source and any vendor-specific parameters against the same list. Either signal counts as an AI arrival.
Write a person property, not just an event property
Set first_ai_source on the person the first time it fires and never overwrite it. Set last_ai_source every time. Also send an event so you keep the timestamp and landing page.
Suppress it on internal navigation
Only evaluate on the first pageview of a visit. Otherwise every internal click re-evaluates against your own hostname and you get noise.
A Minimal Client-Side Implementation
If you are instrumenting from the browser, the whole thing is about twenty lines. The important details are the suffix match, the query fallback, and writing to a person-scoped store.
const ASSISTANTS = {
'chatgpt.com': 'ChatGPT',
'chat.openai.com': 'ChatGPT',
'claude.ai': 'Claude',
'perplexity.ai': 'Perplexity',
'gemini.google.com': 'Gemini',
'bard.google.com': 'Gemini',
'copilot.microsoft.com': 'Copilot',
'you.com': 'You.com',
'poe.com': 'Poe',
};
function detectAssistant() {
// 1. referrer hostname, matched by suffix
try {
const host = new URL(document.referrer).hostname.replace(/^www\./, '');
for (const domain in ASSISTANTS) {
if (host === domain || host.endsWith('.' + domain)) return ASSISTANTS[domain];
}
} catch (e) { /* no referrer at all */ }
// 2. tagged link fallback
const src = new URLSearchParams(location.search).get('utm_source');
if (src) {
const clean = src.toLowerCase().replace(/^www\./, '');
for (const domain in ASSISTANTS) {
if (clean === domain || clean === domain.split('.')[0]) return ASSISTANTS[domain];
}
}
return null;
}Then record it once per visit, against the person:
const assistant = detectAssistant();
if (assistant && !sessionStorage.getItem('ai_src_recorded')) {
sessionStorage.setItem('ai_src_recorded', '1');
_kmq.push(['set', { 'Last AI Source': assistant }]);
_kmq.push(['record', 'AI Assistant Arrival', {
'AI Source': assistant,
'Landing Page': location.pathname,
}]);
}Keep the Landing Page
The single most actionable field is the landing page, not the assistant name. The page an AI-referred visitor arrives on is, almost by definition, the page the model cited. That is a direct content signal: it tells you which of your pages the models find quotable, which is the only reliable input to writing more of them. Record it on the arrival event and keep it.
What You Cannot Recover, and How to Bound It
Be honest about the ceiling. There is a category of AI arrival that carries neither a referrer nor a tag: a native app link on a surface that does not tag, or a person who reads a model’s recommendation and then types your domain in manually. No detection scheme recovers those, and any vendor claiming complete coverage of AI traffic is either counting crawler hits or guessing.
What you can do is bound it. Track the ratio of detected AI arrivals to total direct entrances on non-homepage, non-campaign pages, and watch that ratio over time. If detected AI arrivals grow and the unattributed deep-page direct bucket grows in step, the dark portion is scaling with the measured portion and your measured number is a usable index even if it is not a complete count. Report it that way. A number with a stated floor beats a number with an invented ceiling.
Two things you should explicitly exclude from this count. First, crawler traffic, which is covered in detail in AI crawlers vs AI referrals. GPTBot fetching your page is not a visitor. Second, agents acting on a person’s behalf, which are a genuinely distinct population with their own measurement needs, covered in analytics for AI agents. Mixing any of the three together produces a number that means nothing.
How the LLM Acquisition Report Handles It
The LLM Acquisition report is the built-in version of everything above. It runs both detection signals, referrers plus AI-tagged links, because either one alone undercounts. Then it does the part that is harder than detection: following those people forward.
- People versus touches. One person can arrive from ChatGPT six times. The report separates distinct people from raw arrivals, so you are not reading a repeat visitor as six prospects.
- An honest denominator. Share of traffic is computed against every distinct person who visited the site, not against AI traffic alone. Sizing a channel against itself always makes it look bigger than it is.
- Landing page drill-down. Expand any assistant to the exact pages its visitors land on. That is the citation list.
- Return rate. The share of an assistant’s visitors who came back on a second distinct day, counting all their visits rather than only the AI-referred ones. This is the metric that separates a real channel from a curiosity click.
- Low-sample discipline. Under five visitors in both comparison periods, the trend reads as low sample instead of inventing a direction. AI volumes are still small for most sites and percentage swings on tiny numbers are noise.
What Our Own Numbers Look Like
For calibration, here is one real dataset rather than an industry estimate. Over a single quarter, the Kissmetrics marketing site received roughly 594 visitors referred by AI assistants:
AI-assistant referred visitors to kissmetrics.io, one quarter
Metrics viewThis is our own traffic, not a benchmark, and your split will differ with your audience and your category. Two things are worth noting anyway. ChatGPT is roughly half of the total, which matches its usage share, and Gemini outranking Claude here is a reminder that the assistant that sends you people is not necessarily the one your team uses. If you are only detecting chatgpt.com, you are missing about half the channel.
Note the absolute size too. Several hundred visitors in a quarter is a real channel worth measuring and a poor channel to bet a quarter of headcount on. The value of measuring it now is that you will know the shape of the curve before the decision matters.
How Do I See ChatGPT Traffic in Google Analytics?
You can see part of it. Create an exploration filtered to session source containing chatgpt.com, chat.openai.com, claude.ai, perplexity.ai, gemini.google.com or copilot.microsoft.com, and build a custom channel group for those hostnames so they stop landing in Referral or Unassigned. That captures the browser-based arrivals. It will not capture arrivals from the native desktop and mobile apps, which send no referrer and are recorded as Direct, and GA4’s session-scoped attribution will still reassign the source if the person converts on a later visit through a different channel. For a complete count you need person-level detection that combines the referrer with the tagged-link fallback and persists across visits.
Key Takeaways
The teams that will be able to argue for AI content budget in twelve months are the ones instrumenting the channel now, while the numbers are small enough that nobody is asking about them yet.
One analytics idea a week
Short, specific, written by the team building the product. No digest, no roundup.
Continue Reading
AI Crawlers vs AI Referrals: GPTBot, ClaudeBot and What to Actually Block
Blocking training crawlers is cheap. Blocking retrieval crawlers costs you the citations that send real humans. Most robots.txt files do not tell the two apart.
Read articleLLM Visibility vs LLM Acquisition: Which AI Search Metric Actually Matters
Being mentioned by ChatGPT is a proxy. Someone arriving from ChatGPT and signing up is the outcome. Both are worth measuring, but only one goes in the board deck.
Read articleAnalytics for AI Agents: Measuring Traffic That Acts on Behalf of a Human
An agent has no scroll depth, no dwell time and no session. Everything session-based analytics measures is meaningless for it. Here is what to measure instead.
Read article