Get in touch
Gabs
Blog

How do you see ChatGPT and Gemini visits in your analytics?

ChatGPT clicks carry a utm tag, yet 96% to 99% lack a referrer, so GA4's AI channel misses them. Check the tag, referrer and user agent.

Gabriel EspinheiraSenior Full-Stack Engineer
  • Published
  • 8 minReading time
  • MarketingCategory

Listen to this post· AI-narrated

0:00 / 8:36

Someone asks ChatGPT which tool to use, your product is in the answer, and they click. Where do ChatGPT and Gemini visits like that show up in your analytics? Since May, Google Analytics has had an AI Assistant channel built for exactly this, and some people have opened it and found almost nothing. One commenter on r/GoogleAnalytics (opens in a new tab) said theirs showed "only 2 sessions", "but we're getting a lot of traffic from chatgpt and gemini, so the numbers aren't adding up." The numbers don't add up because each assistant sends a different signal, and the AI Assistant channel reads only one of them. To see ChatGPT and Gemini visits in your analytics, you have to read all three: the utm tag, the referrer and the user agent. One of them only shows up on your server.

TL;DR: GA4's AI Assistant channel only counts visits that arrive with an AI referrer. ChatGPT clicks carry a utm tag but almost never a referrer, and the Gemini iOS app sends neither, only a user agent. Group AI sources by tag and referrer in a custom channel, check the user agent on your server, and treat the total as a floor.

Where do ChatGPT and Gemini visits land in GA4?

A click from an AI answer can end up in AI Assistant, Referral, Unassigned or Direct, depending on what it carries. Google added the AI Assistant channel to the Default Channel Group on 13 May 2026. Its rule is narrow: GA4 sets the medium to ai-assistant only "if the referrer matches a list of AI Assistants", naming sources like ChatGPT, Gemini, Deepseek, Copilot and Grok (Google Analytics Help (opens in a new tab)). Clicks from Google's own AI Overviews and AI Mode are excluded and count as Organic Search.

The referrer is the weak link. Natzir Turrado, a search consultant who publishes server-log data on AI traffic, finds that since GPT-6, 96% to 99% of visits carrying ChatGPT's utm_source=chatgpt.com tag arrive with no referrer at all (Turrado, updated 27/10/2026 (opens in a new tab)). A visit like that reaches GA4 as chatgpt.com / (not set). No default rule matches a medium of (not set), so the session goes to Unassigned, not to AI Assistant or Referral (BuildMVPFast (opens in a new tab)). Clicks with neither tag nor referrer go to Direct.

Read the AI Assistant row as the share of your AI traffic that still sends a referrer. For ChatGPT's tagged clicks, by those numbers, that's one to four in a hundred.

What does each AI assistant send when someone clicks?

The same assistant sends different signals from its website and its app, and Gemini changed its own in September. This is the picture from Turrado's table, updated 27/10/2026, unless a line cites another source:

  • ChatGPT on the web, citation links: the tag utm_source=chatgpt.com, on every plan since June 2025. The referrer almost never comes through.
  • ChatGPT on the web, inline links on the Free plan: no tag and no referrer, so they land in Direct.
  • Gemini on the web: a gemini.google.com referrer. For about three weeks in September it also added utm_source=gemini to some links, and the tag has been gone since around 29 September (Search Engine Roundtable, 30/10/2026 (opens in a new tab)).
  • Gemini iOS app: links open in the app's own WebView with no referrer, so GA4 files them under Direct. The only trace is a user agent containing GeminiiOS and GoogleWv/1.0 (WKWebView), which you only see in server logs (PPC Land, 01/11/2026 (opens in a new tab)).
  • Gemini Android app: no documented user agent of its own, and almost all of it lands in Direct.
  • Perplexity and Copilot on the web: a normal referrer.
  • Claude on the web: a referrer whose path ends in the date, claude.ai/referral/YYYY-MM-DD, so match the host and ignore the path.
  • The ChatGPT, Claude and Perplexity mobile apps: mostly no referrer, and most clicks carry no tag.

How do you build an AI channel that catches the tagged visits?

Match on source instead of referrer. GA4 takes the source from the utm tag when there is one, so chatgpt.com / (not set) still has chatgpt.com as its source, and a channel that reads the source catches it. In GA4, go to Admin, Data display, Channel groups, copy the default group and add a channel called AI with the condition Source matches regex:

^(chatgpt\.com|gemini|gemini\.google\.com|perplexity\.ai|claude\.ai|copilot\.microsoft\.com)$

The bare gemini covers the sessions Gemini tagged in September. Anchor the pattern: loose versions like .*gpt.* match unrelated sites, and every false match inflates the number you're trying to trust. Then drag the AI channel to the top, above AI Assistant and Referral, because GA4 puts each session in the first channel it matches (Analytics Mania (opens in a new tab)). The AI channel then holds the referred sessions and the tagged ones in one row, and ChatGPT's tagged sessions move out of Unassigned. A standard property gets only two custom channel groups, so this spends one of them, and for ChatGPT it's the difference between one to four tagged clicks in a hundred and all of them.

How do you count the visits analytics never sees?

Count them on your server, where every request still carries its URL, its referrer and its user agent, whether or not an analytics script ran. Your server sees the Gemini iOS app's user agent on every request; GA4's standard reports never show it. A function that checks the three signals in order is short:

type AiSource = "chatgpt" | "gemini" | "perplexity" | "claude" | "copilot"
const TAGS: Record<string, AiSource> = {
  "chatgpt.com": "chatgpt",
  gemini: "gemini",
}
const REFERRERS: Record<string, AiSource> = {
  "chatgpt.com": "chatgpt",
  "gemini.google.com": "gemini",
  "perplexity.ai": "perplexity",
  "claude.ai": "claude",
  "copilot.microsoft.com": "copilot",
}
export function getAiSource(url: URL, referrer: string, userAgent: string): AiSource | null {
  const tag = url.searchParams.get("utm_source")
  if (tag && tag in TAGS) return TAGS[tag]
  if (URL.canParse(referrer)) {
    const host = new URL(referrer).hostname.replace(/^www\./, "")
    if (host in REFERRERS) return REFERRERS[host]
  }
  if (userAgent.includes("GeminiiOS")) return "gemini"
  return null
}

Call it from your middleware or log pipeline on landing requests only, the page requests whose referrer isn't your own site, and collapse repeats from the same IP and user agent within 30 minutes, the window analytics tools use for a session. Store the result next to the request. The tag goes first because it's the signal ChatGPT still sends. The gemini tag can stay in the list, since Google may turn it back on. I wrote seven tests for it before using it: one per trace above, a typed URL and a broken referrer header.

Two kinds of request look like AI visits and aren't. ChatGPT-User and the other assistants' fetchers read your page to answer a question, and in Turrado's logs ChatGPT-User fetches 2 to 7 times more pages than the visits ChatGPT sends. And on one of the sites he measures, up to 35% of visits tagged utm_source=chatgpt.com came from automated clients on 85 data-centre IPs with outdated browser user agents, the pattern of prompt trackers opening links in ChatGPT's answers. Filter both before you count. The fetchers name themselves in the user agent. For the data-centre traffic, use your CDN or host's bot flag if it has one, and expect your server count to run above GA4's anyway, because the server also sees visitors who block the script or decline consent.

How much AI traffic are you still missing?

Report the total as a floor, and say which signals it rests on. Every click that arrives with no tag, no referrer and no telling user agent can't be attributed, and nothing can recover its source. The floor can also drop overnight when an assistant changes its links: from 7 to 16 October a bug stripped ChatGPT's tag. In Turrado's server logs the ChatGPT channel lost 68% to 74% of its visits, GA4 showed drops of 20%, 46% and 60% depending on the site, and the missing visits couldn't be picked out of Direct, whose day-to-day swings were as large as what ChatGPT had lost. OpenAI confirmed it as a bug to Adobe's Cedric Huesler on 14 October and a fix rolled out from the 15th (BuildMVPFast (opens in a new tab)).

For the clicks no signal catches, ask people. A "How did you hear about us?" field on your signup or contact form, with ChatGPT and Gemini as options, keeps working whatever the assistants change next.

What to do this week

Open Traffic acquisition, set the dimension to Session source / medium and look for chatgpt.com / (not set). If it's there, your AI Assistant channel has been undercounting. Add the anchored AI channel at the top of a copied channel group, put the three-signal check on your server, filter the bots, and add the question to your form. Then check the rows again the next time ChatGPT or Gemini ships a new answer format, because that's when the tags break.

More posts on building and shipping software are on the gabs.app blog. I'm a full-stack engineer and my work is on gabs.app; if you're hiring, the contact form comes straight to me.