• October 22, 2026
GA4GEOTag ManagerFor SEO pros

By Jourdan Rombough, Optimization Theory · Updated · Field-tested on a three-site network

GA4 can tell you that ChatGPT sent a visit. It cannot tell you whether that visitor read anything, came back, converted, or was a bot. That gap is the difference between a GEO report and a GEO guess.

I just rebuilt the analytics on my own network (optimizationtheory.com, vuss.io and infographi.ac) to answer the questions SEOs are now getting from clients: which AI assistants cite us, what those visitors do next, which content actually gets read, and how much of the "traffic" is real. This is every setting I changed, the code I used, and the reports I built on top. If you already know where the GA4 admin menu is, this is for you.

<1%of all site visits come from AI platforms (0.2% to 1.08% across four studies)
95.1%of AI referrals came from ChatGPT in August 2026
8%click rate on results under an AI summary, vs 15% without
+101%ChatGPT referral growth, January to August 2026

Sources: AI share range across Contentsquare, Ahrefs, SE Ranking and Conductor studies compiled by Mission Growth. ChatGPT share and growth from BrightEdge. Click rates from Pew Research Center.

Default GA4 vs the GEO power user setup
Question Default GA4 After this setup
Which AI sent the visit? AI Assistant channel for some sources since May 2026, the rest in Referral Custom channel plus an ai_source dimension on every event
Do AI visitors come back? No way to tell first_ai_source user property
Did they read it? "Engaged session" after 10 seconds engaged_read: 75% scroll and 60 active seconds
AI Overviews traffic? Blended into google / organic Search Console AI report plus text-fragment landings
Is the traffic real? Ghost and bot hits mixed in hit_source and traffic_quality labels
Year-over-year explorations? 2 months of event data 14 months
Multiple sites? Each site sees the others as referrals Network roll-up property with cross-domain linking
Infographic comparing default GA4 with the GEO power user setup across seven questions: which AI sent the visit, return visits, real reads, AI Overviews traffic, traffic quality, year-over-year analysis and multiple sites
Seven questions your analytics should answer, and what changes after this setup.

What my own audit turned up. All three properties were still on 2-month event retention. On one site, the WordPress pages had no GA4 tag at all, and only a set of static HTML pages were reporting. Another site had a static page outside WordPress carrying its own hardcoded tag. Cloudflare was caching full pages for 31 days, so tag changes would not have shown up for a month. Local development visits were landing as referrals. If that can happen on an SEO's own sites, it is happening on your clients' sites.

What GA4's native AI Assistant channel misses

Google added an AI Assistant channel to the default channel group in May 2026. Recognized assistants get the medium ai-assistant and the campaign (ai-assistant). It is a good start, and it is not enough for GEO work:

  • ✕No history. It is not retroactive. Everything before the rollout stays in Referral.
  • ✕Unpublished source list. Google has not published which assistants it recognizes, and reports disagree on whether Claude and Perplexity are included. Check your own Traffic acquisition report for claude.ai and perplexity.ai with a medium of "referral."
  • ✕App clicks. Clicks from mobile and desktop assistant apps often arrive with no referrer and land in Direct.
  • ✕Google's own AI. AI Overviews and AI Mode clicks still report as google / organic.
  • ✕No behavior layer. It labels the session. It does not tell you which assistant a returning customer first came from.
Infographic of 5 gaps in GA4's AI Assistant channel: no history, unpublished source list, app clicks lose referrers, Google's own AI blended into organic, and no first-touch behavior layer
The native channel labels the session. Everything else takes custom setup.

Sources: Semrush and Zeevron on the rollout and its gaps. The rest of this guide closes each one.

Keep 14 months of event data, not 2

The default event data retention is 2 months. Any exploration, funnel or path report older than that comes back empty. GEO is a trend story, and you cannot show a client that AI referrals doubled year over year with 60 days of data.

Admin›Data collection and modification›Data retention›Event data: 14 months
GA4 › Data retention

GA4 data retention settings with event data retention set to 14 months

Set event data to 14 months and leave "Reset on new user activity" on.

Why it matters even with BigQuery. Standard reports use aggregated tables and are not affected, but explorations, funnels and user-level analysis are. The change only applies going forward, so it is the first thing to fix in any audit.

Tune enhanced measurement for content sites

Open your web stream (Admin › Data streams › your stream). Enhanced measurement is the block of automatic events GA4 collects without any code.

GA4 › Web stream details

GA4 web stream details showing enhanced measurement and Google tag settings

The web stream holds both enhanced measurement and the Google tag settings used in the next steps.
  • Page views: on, including browser history changes
  • Scrolls: on. This fires at 90% depth. Tag Manager adds 25, 50 and 75.
  • Outbound clicks: on. You want to know when readers click your citations and sources.
  • Site search: on. Include the query parameters q,s,search,query,keyword. WordPress uses s.
  • Form interactions: off. It fires on every form focus, including search boxes and newsletter bars. Track successful submissions instead.
  • Video engagement and file downloads: on
GA4 › Enhanced measurement

GA4 enhanced measurement panel with form interactions turned off

Form interactions is the only switch turned off.

Stop payment pages from stealing your organic credit

When a visitor who arrived from Google or ChatGPT goes to PayPal or Stripe to pay and comes back, GA4 can start a new session credited to the payment site. The channel that earned the sale loses it. "Sign in with Google" does the same.

Data stream›Configure tag settings›Show more›List unwanted referrals
Google tag › Settings

Google tag settings menu in GA4 showing define internal traffic and list unwanted referrals

Unwanted referrals and internal traffic both live in the Google tag settings.

Add these as "Referral domain contains":

  • paypal.com
  • paypal.me
  • stripe.com
  • accounts.google.com
  • mail.google.com
Google tag › List unwanted referrals

GA4 unwanted referrals list with PayPal, Stripe and Google account domains

Payment and login domains no longer take credit for conversions.

Take yourself out of the data

When you test your own pages in ChatGPT and click through, you become AI referral traffic. On a small site that alone can make GEO look like it is working.

Configure tag settings›Define internal traffic›Create

Name the rule, keep traffic_type as internal, and add your IP.

Google tag › Define internal traffic

GA4 internal traffic rule with traffic_type set to internal and an IP address condition

One rule per location you work from.

Then check Admin › Data filters. GA4 creates the "Internal Traffic" filter in Testing mode, which labels your visits without excluding them. Confirm the label in DebugView, then switch it to Active.

Pro tip: IP rules miss you on your phone, on a VPN and on client Wi-Fi. In my Tag Manager setup, visiting any page with ?ot_internal=1 sets a two-year cookie that marks every hit from that browser as internal, and adds a user_type = internal user property so you can exclude yourself from audiences too.

Running more than one site? Build a Network property

If you own sites that link to each other, each property sees the others as plain referrals. You never see the full journey, like a reader who lands on one site from Perplexity and requests a quote on another.

The fix is a separate Network property that every site also sends to, with cross-domain measurement on. Each site keeps its own clean property, and the Network property is the roll-up.

GA4 › Create property

Creating a new GA4 property named OT Network all sites with New York time zone

Match the time zone and currency of your site properties.

Add one web stream, then open Configure tag settings › Configure your domains and list every domain:

Google tag › Configure your domains

GA4 cross-domain measurement configured for three domains

Cross-domain linking keeps one session as a reader moves between your sites.

Give the Network property the same retention, unwanted referrals, internal traffic rules and custom definitions as the others, and add a site_name parameter to every event so one report can switch between sites.

Move tracking into Tag Manager, with Consent Mode v2

Site Kit and similar plugins are fine for page views. They cannot capture the AI source of a session, real reading behavior, tool use or where on the page a click happened. Tag Manager can.

Tag Manager › Add a new account

Google Tag Manager add a new account screen with a web container

One account, one web container per domain.

I built each container as a JSON file and imported it (Admin › Import Container), which loads every tag, trigger and variable in one pass:

Tag Manager › Import container

Google Tag Manager import container preview showing 65 items added

65 tags, triggers and variables added in a single import.

Each container fires two Google tags, one for the site property and one for the Network property:

Tag Manager › Overview

Google Tag Manager container sending to two GA4 destinations, a network property and a site property

One container, two destinations.

On WordPress, GTM4WP places the container and pushes post type, categories, author, publish date and logged-in state into the data layer.

Do not double count. Turn off Site Kit's "Place Google Analytics code" in the same minute you publish Tag Manager. Then hunt for static pages outside WordPress that carry their own hardcoded gtag, and purge the host and CDN cache, or the old HTML keeps serving.

Consent Mode v2 on a free consent plugin

With Consent Mode, a denied visitor still sends a cookieless ping and Google models the gap. Without it, an opt-out erases the visit, and AI referral numbers that are already small get smaller.

I use Complianz (free) with United States opt-out rules and Global Privacy Control respected. The free version does not pass Consent Mode signals to Tag Manager, so each container has a Custom HTML tag on the Consent Initialization trigger that reads the banner choice and the browser's GPC flag and sets the defaults before any Google tag fires.

Check the gcs parameter on GA4 hits in your browser's network tab
gcs value What it means When you should see it
G111 Analytics and ads storage granted A normal visit with no opt-out
G100 Storage denied, cookieless ping only After opting out in the banner, or with GPC on

Build an AI Assistants channel that beats the default

A custom channel group fixes the history and coverage problems. Unlike the native channel, a custom group re-buckets historical data whenever you select it in a report or exploration.

1

CreateCopy the default channel group

Admin › Data display › Channel groups › Create new channel group. It starts as a copy of the default.

2

DefineAdd an AI Assistants channel

Add new channel, name it AI Assistants, condition Source matches regex:

.*(chatgpt|openai|perplexity|gemini\.google|bard\.google|copilot|edgeservices\.bing|claude\.ai|you\.com|phind|poe\.com|meta\.ai|deepseek|grok|x\.ai|mistral|kagi|duck\.ai|qwen|character\.ai).*

GA4 caps a regex condition at 256 characters, so this pattern uses partial matches. It also catches tagged links, since ChatGPT appends a utm_source value containing "chatgpt" to many of the links it cites.

GA4 › Channel groups › AI Assistants

GA4 custom channel named AI Assistants with a source matches regex condition

One regex covers every major assistant.
3

ReorderMove it to position 1

Channel rules run top to bottom and the first match wins. If AI Assistants sits below Referral, Referral takes the session.

GA4 › Reorder channels

GA4 channel group reorder with AI Assistants moved to the top above Direct

AI Assistants above Direct, Referral and Organic Search.
4

ActivateMake it the primary channel group

Set it as the primary channel group so standard acquisition reports and attribution use it. That switch applies going forward, while the group itself stays available for historical analysis.

Capture the AI source on every hit, not just the session

A channel tells you how a session started. For GEO you also want to know, on every event, which assistant the reader came from, and for every user, which assistant first introduced them. That takes three pieces in Tag Manager:

  • ai_sourceEvent parameter on every hit in the session: chatgpt, perplexity, gemini, copilot, claude and so on. Read from the referrer or utm_source, then held for the rest of the session.
  • first_ai_sourceUser property saved once and kept. Shows which assistant introduced readers who return weeks later through search or direct.
  • ai_landingEvent fired on the first page of an AI-referred session, with the landing page. Your list of pages AI assistants actually send people to.

Here is the Custom JavaScript variable behind ai_source, trimmed for readability. Add more assistants to the map as they appear in your referral report.

function () {
  try {
    var saved = sessionStorage.getItem('ai_source');
    if (saved) return saved;
  } catch (e) {}
  var map = [
    [/(^|\.)(chatgpt\.com|chat\.openai\.com)$/, 'chatgpt'],
    [/(^|\.)perplexity\.ai$/, 'perplexity'],
    [/(^|\.)gemini\.google\.com$/, 'gemini'],
    [/(^|\.)(copilot\.microsoft\.com|edgeservices\.bing\.com)$/, 'copilot'],
    [/(^|\.)claude\.ai$/, 'claude'],
    [/(^|\.)(grok\.com|x\.ai)$/, 'grok'],
    [/(^|\.)(deepseek\.com|chat\.deepseek\.com)$/, 'deepseek']
  ];
  function match(host) {
    host = (host || '').toLowerCase().replace(/^www\./, '');
    for (var i = 0; i < map.length; i++) if (map[i][0].test(host)) return map[i][1];
    return null;
  }
  var src = null;
  if (document.referrer) {
    var a = document.createElement('a');
    a.href = document.referrer;
    src = match(a.hostname);
  }
  if (!src) {
    var m = location.search.match(/[?&]utm_source=([^&#]*)/i);
    if (m) src = match(decodeURIComponent(m[1]))
      || (/chatgpt/i.test(m[1]) ? 'chatgpt' : null);
  }
  if (src) {
    try {
      sessionStorage.setItem('ai_source', src);
      if (!localStorage.getItem('first_ai_source')) localStorage.setItem('first_ai_source', src);
    } catch (e) {}
  }
  return src || undefined;
}

Send it as an event parameter in your Google tag's shared event settings, and send localStorage.first_ai_source as a user property. Register both as custom dimensions (step 12).

How to track traffic from AI Overviews (and why you mostly cannot)

This is the honest part. Clicks from Google AI Overviews and AI Mode arrive as google / organic, with nothing in the referrer to separate them. Pew's study of real browsing found people clicked a standard result on 8% of searches with an AI summary versus 15% without, and clicked a link inside the summary on just 1%. The traffic is small, and it is hidden inside organic.

What you can do:

  • ✓Search Console's generative AI report. Announced June 2026 and rolling out from the UK, it shows AI Overviews and AI Mode impressions by page, country, device and date. It does not yet show clicks, CTR or queries. Pair its pages with GA4 landing pages to spot pages earning AI visibility.
  • ✓Text-fragment landings (experimental). When Google deep-links to a passage, the URL carries #:~:text=. Browsers hide it from page scripts, but Chrome's navigation timing entry can expose it. I log it as a text_fragment_landing event with the quoted text. It undercounts, but every hit shows the exact sentence Google pulled.
  • ✓Engagement deltas. Compare engaged read rate for organic landings on queries where an AI Overview appears against those where one does not. A drop in clicks with stable or rising read rate is the AI Overview signature.

Sources: Pew Research Center (900 US adults, 68,879 searches, March 2025) and Passionfruit on the Search Console report.

Track real reads, not engaged sessions

GA4's "engaged session" is 10 seconds, two page views or one key event. For content, that tells you almost nothing about whether an AI-referred visitor found the answer they were promised. Here is what I track instead, all through one tracking script in Tag Manager:

Infographic of six GA4 events that track real reads: engaged_read at 75% scroll plus 60 active seconds, scroll_depth, network_click, tool_open, generate_lead and contact_click
Six events that show what visitors actually do after they land.
  • engaged_readFires once at 75% scroll plus 60 seconds of active, visible time. Time only counts while the tab is visible and the reader moved, scrolled or tapped in the last 30 seconds.
  • scroll_depth25, 50 and 75 percent. GA4's own scroll event covers 90.
  • network_clickClicks between your own sites, with destination and page zone: header, nav, content, sidebar or footer.
  • tool_openCalculators, simulators, quote builders and quizzes, counted once per session so multi-page tools do not inflate numbers.
  • generate_leadA successful form submission from the form plugin's own success event, not a button click.
  • contact_clickContact, pricing and quote clicks each get their own event with cta_location, so you know which part of the page drives action.

Mark only the ones that represent business value as key events. On a service site that is leads, quote starts and contact clicks. On a publisher it is engaged reads, newsletter sign-ups and clicks to money pages.

Register custom dimensions for content metadata

Parameters stay invisible in reports until you register them. Go to Admin › Custom definitions › Create custom dimension, choose the scope, and type the parameter name. I registered 29 dimensions and 3 metrics in every property.

GA4 › Custom definitions

GA4 custom dimensions list including ai_source, author, content_age_bucket and cta_location

Registered dimensions show up in standard reports and explorations.
Dimension Scope The GEO or SEO question it answers
ai_source Event Which assistant sent this visit, on every event in the session
first_ai_source User Which assistant first introduced this person
primary_category Event Which topic clusters AI assistants send traffic to
content_age_bucket Event Do assistants favor fresh content, or are old posts still cited
word_count_bucket Event Does long-form get read when an AI sends the visit
author Event Which writer's work gets read to the end
cta_location Event Which part of the page drives the click
hit_source / traffic_quality Event Is this hit real (step 13)

For numbers you sum or average, create custom metrics and set the right unit. Read time should be Seconds:

GA4 › New custom metric

Creating a GA4 custom metric read_time_sec with seconds as the unit of measurement

Time-based metrics need the Seconds unit to format correctly.

Budget your slots. Standard properties allow 50 event-scoped dimensions, 25 user-scoped dimensions and 50 custom metrics. Never register IDs, full URLs with query strings or anything with near-unlimited values, or you will hit the (other) row in every report.

Flag ghost and bot traffic instead of deleting it

AI referral traffic is a fraction of a percent of visits. A handful of bot sessions with a spoofed chatgpt.com referrer can double it. Filtering looks like the fix, but GA4 data filters are permanent: an excluded hit is gone, and so is your evidence. I label every hit instead:

1hit_source = gtm

Added to every event that comes through Tag Manager. Ghost hits sent straight to the Measurement Protocol never touch your site or container, so they arrive without it. One dimension separates real visits from ghost traffic.

2traffic_quality

clean, bot_suspect (headless browsers, automation flags, zero-size screens), spam_referrer (a maintained referrer list) or hostname_mismatch.

With the BigQuery export on, this query shows how much of your data arrived without the Tag Manager label in the last 28 days:

SELECT
  IFNULL(
    (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'hit_source'),
    'ghost (no gtm)'
  ) AS hit_source,
  COUNT(*) AS events,
  COUNT(DISTINCT user_pseudo_id) AS users
FROM `your-project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 28 DAY))
  AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
GROUP BY hit_source
ORDER BY events DESC;

Clean by default, evidence on demand. Every report and dashboard defaults to clean data, and the raw hits stay available. On my own sites, this surfaced a run of direct traffic from Singapore and China that looks nothing like real readers, which would otherwise have inflated every engagement metric.

The GEO reports I actually use

None of the tracking matters until it answers a client question. These are the reports I build on top, in GA4 Explorations and in a Looker Studio dashboard on the Network property.

1AI landing pages

Free-form exploration. Rows: Landing page. Columns: ai_source. Values: Sessions, engaged_read count, Key events. Filter: hit_source exactly matches gtm. This is the list of pages assistants are citing and whether those visitors read.

2AI vs organic quality

Compare the AI Assistants channel to Organic Search on engaged read rate and key event rate. If AI visitors read more and convert better, that is the budget argument for GEO work.

3AI-introduced users

Segment users where first_ai_source is set, then look at their later sessions by channel. It shows how often a ChatGPT first touch comes back through branded search or direct.

4Refresh queue

primary_category by content_age_bucket, colored by engaged read rate. Old posts that still pull AI and organic visits but lose readers are the first to update.

In Looker Studio, two calculated fields do most of the work. The first groups sources into platforms:

CASE
  WHEN REGEXP_MATCH(Session source, ".*(chatgpt|openai).*") THEN "ChatGPT"
  WHEN REGEXP_MATCH(Session source, ".*perplexity.*") THEN "Perplexity"
  WHEN REGEXP_MATCH(Session source, ".*(gemini|bard).*") THEN "Gemini"
  WHEN REGEXP_MATCH(Session source, ".*(copilot|edgeservices\\.bing).*") THEN "Copilot"
  WHEN REGEXP_MATCH(Session source, ".*claude\\.ai.*") THEN "Claude"
  WHEN REGEXP_MATCH(Session source, ".*(grok|deepseek|meta\\.ai|mistral|you\\.com|phind|kagi).*") THEN "Other AI"
  ELSE "Not AI"
END

The second turns the labels from step 13 into a single Data Quality control, defaulted to Clean:

CASE
  WHEN hit_source IS NULL OR hit_source = "(not set)" THEN "Ghost (no GTM)"
  WHEN traffic_quality = "bot_suspect" THEN "Bot suspect"
  WHEN traffic_quality = "spam_referrer" THEN "Spam referrer"
  WHEN traffic_type = "internal" THEN "Internal"
  ELSE "Clean"
END
  • Search Console linkAdmin › Product links. Brings queries and organic landing pages into GA4 next to engagement data.
  • BigQuery linkFree daily export of raw events. Turn on billing in Google Cloud or sandbox tables expire after 60 days.
  • Looker StudioOne report on the Network property with a site switcher: overview, GEO, Search Console, content, funnels, tools, cross-site flow and data quality.

GA4 audit checklist for SEOs

Run this before you trust any number, yours or a client's:

  1. 1Event data retention is 14 months on every property
  2. 2Exactly one GA4 tag per page: no plugin plus hardcoded gtag plus theme option
  3. 3Static pages, microsites and HTML tools outside the CMS are tagged too
  4. 4The live HTML matches what you installed, after host and CDN cache purges
  5. 5Payment and login domains are listed as unwanted referrals
  6. 6Internal traffic is defined, tested, then set to Active
  7. 7Consent Mode sends gcs on every hit, and opt-outs show G100
  8. 8A custom AI Assistants channel sits above Referral and is the primary group
  9. 9ai_source and first_ai_source are populated and registered
  10. 10Key events are limited to actions with business value
  11. 11Ghost and bot hits are labelled, and reports default to clean data
  12. 12Search Console and BigQuery are linked
  • ✕Filters switched to Active on day one. Test first. An active filter that matches the wrong thing deletes real data forever.
  • ✕Key event overload. If every scroll is a key event, nothing is. AI traffic will look like it converts brilliantly.
  • ✕Reporting AI traffic without excluding yourself. Your own ChatGPT tests can be a meaningful share of a small site's AI referrals.
GA4 audit checklist for SEOs infographic with 12 checks grouped into collection, attribution, AI measurement and reporting, plus three mistakes to avoid
Save this one. All 12 checks and the 3 mistakes on a single page.

Frequently asked questions

People also ask

How do I track AI traffic in GA4?

Create a custom channel group with an AI Assistants channel using a "Source matches regex" condition for chatgpt, perplexity, gemini, copilot, claude and similar sources, move it above Referral, and set it as the primary channel group. For deeper analysis, capture the AI source as an event parameter and the first AI source as a user property in Tag Manager.

Does GA4 have an AI Assistant channel?

Yes. Google added an AI Assistant channel to the default channel group in May 2026, using the medium ai-assistant. It is not retroactive, Google has not published the full source list, and app clicks without a referrer still land in Direct, so a custom channel is still worth building.

Can you track traffic from Google AI Overviews in GA4?

Not directly. AI Overviews and AI Mode clicks report as google / organic. Search Console's generative AI report shows impressions by page, and text-fragment landing URLs can reveal passage-level clicks. Together they are the best available proxies.

Why does ChatGPT traffic show as Direct in GA4?

Clicks from the ChatGPT apps and some links arrive without a referrer. ChatGPT adds a utm_source tag to many cited links on the web, which GA4 does pick up, but app traffic and copied links usually fall into Direct.

Should I set GA4 data retention to 14 months?

Yes. The 2-month default limits explorations, funnels and user-level analysis, which are the reports used for year-over-year GEO and SEO trends. 14 months is the maximum on standard properties, and the change only applies going forward.

What should a GA4 audit check for SEO?

Retention, duplicate tags, untagged static pages, stale cached HTML, unwanted referrals, internal traffic, Consent Mode, an AI Assistants channel above Referral, registered custom dimensions, a short key event list, labelled junk traffic, and Search Console and BigQuery links.

Want this on your sites?

This is the analytics overhaul I do for clients.

Retention, Tag Manager, Consent Mode, AI source tracking, ghost traffic labels and a Looker Studio GEO dashboard, set up and verified on your properties.

More Writing & Research by Jourdan Rombough

View all research

SEO MEDITATIONS