



Published 29/07/2026. Last updated 30/08/2026. Windows setup, about an hour start to finish.
In short: Claude talks to Google Analytics 4 through an MCP server, a small program that runs on your own computer and passes read-only questions to the GA4 API. You need Python, a Google Cloud service account with Viewer access to your property, and one entry in Claude Desktop’s config file. Allow an hour.
In this post, learn how to connect to Claude AI and free up time for more added value tasks. You will be able to stop spending time checking if a GA4 property has been correctly configured and can check multiple properties using an automated approach. Connecting AI to GA4 opens up lots of opportunities to get easier access to data. Imagine, if you could open a chat window and type “Which of my traffic sources bring in lots of visitors but almost no engagement?” A minute later you have a real answer, pulled straight from your Google Analytics 4 data. No export to build, dashboard to check and no waiting on someone else to run the numbers.
That’s what happens once you connect Claude, Anthropic’s AI assistant, to your GA4 property. If you spend much of your week in GA4 or you have multiple GA4 properties to monitor, this changes how you work with it day to day.
On this page
If you’d rather watch someone do this than read about it, our founder, Neal Cole, who created the CXL.com GA4 Audit course, has recorded a full walkthrough. Both routes end up in the same place, so pick whichever suits how you learn.
By the end of this article you should understand:

How Claude, the MCP server and GA4 fit together

Example response using Conversion Uplift’s own GA4 data
Before you start, you’ll need:

Setup roadmap for connecting Claude to GA4

Windows PowerShell Window
The MCP connector is a small program written in Python, so Python needs to be on your machine first. You don’t need to have any coding experience to use Python because Claude will do all the coding for you, you just need to give AI the prompts, and it will do the rest.

Python Standalone Installer
C:\Python (create the folder if it doesn’t already exist). The path must contain no spaces, which is why we’re not using the default location.

C:\Python path – create this folder if it doesn’t exist
python --version
You should see something like Python 3.14.6 printed back.

Turning off Python.exe toggles
If PowerShell says: “the term ‘python’ is not recognised” , Python is installed, but Windows doesn’t know where to look for it. You need to add two folders to your PATH:

Selecting Environment Variables
C:\Python, then New again and add C:\Python\Scripts. Click OK on every window.python --version again.

Adding the Python folders to the PATH environment variable
Type these entries carefully, a single wrong character (like C:\pythonzscripts instead of C:\Python\Scripts) means Windows fails to find your programs, with no error to warn you. PATH changes only apply to new PowerShell windows, so always close and reopen after editing as otherwise PowerShell won’t have updated and it will give you the wrong feedback.
setx PIPX_HOME "C:\pipx-new"
setx PIPX_BIN_DIR "C:\pipx-new\bin"python -m pip install --upgrade pip
python -m pip install pipx
python -m pipx ensurepathYou are making good progress, next we need to confirm a few things.
C:\Python. In a new PowerShell window, run:python -c "import sys; print(sys.executable)"C:\Python\python.exe. Copy this. You’ll use it in the install command below in place of C:\Python\python.exe if yours is different.

Install GA4 MCP server
The one line that might look alarming, “WARNING: Skipping setuptools as it is not installed”, is harmless and so it is safe to ignore it. It’s a routine pipx notice and doesn’t affect the install. If this prints a path inside \WindowsApps\, or Python still isn’t recognised here, stop and finish the PATH and App execution alias fixes from Step 1 first. If the installer points at the Microsoft Store stub instead of your real Python install, this step will fail without any warning. In this case, follow the next steps:
pipx install analytics-mcp --python "C:\Python\python.exe" --forceWe now need to verify the install and find out exactly where the program landed. Paste this into PowerShell
pipx list
where.exe analytics-mcp
Verify the GA4 MCP server install location
C:\pipx-new\bin\analytics-mcp.exe or C:\Users\YOURNAME\.local\bin\analytics-mcp.exe.where.exe says it “could not find files”, don’t worry, the program is still installed. Find it by running dir C:\Users\YOURNAME\.local\bin\analytics-mcp.exe (swap in your own username) or dir C:\pipx-new\bin\analytics-mcp.exe. Whichever command lists a file is your path.The Google Cloud project is just a container that holds your permissions. You will only need to do this once. If you don’t already have a Google Cloud account, you will need to create a new one or check if your organisation already has GCP set up.
mcp-analytics-connection). It’s usually your project name in lowercase with hyphens. You’ll need it in Step 9.

Google Cloud Project

Google Analytics Admin API

API Library
The Library has several similarly named APIs, make sure you enable exactly these two, not the older “Google Analytics API” or “Analytics Hub API”.

Creating the service account in Google Cloud
[email protected]. You’ll need it in Step 8 to give Claude access to your GA4 properties.Here we will need to store the JSON key and you only get one opportunity to do this, and so take your time. However, if you don’t manage to get it the first time, it is easy to create a new key.

Create Key Dialog Box
ga4-mcp.json (no spaces).C:\keys. Move the file into this new folder and so the full path should be C:\keys\ga4-mcp.json.Test-Path C:\keys\ga4-mcp.jsonIf it says True, the key is in the right location, and you’re set to go. If False, search for it using this script. Google names downloaded keys after the project, so search for JSON files starting with the project ID (probably something like analytics-connection-…). Check your Downloads and user folder:
Get-ChildItem $HOME\Downloads, $HOME\Desktop, $HOME\Documents, C:\keys -Filter *.json -Recurse -ErrorAction SilentlyContinue | Select-Object FullName, LastWriteTimeWell done, you are now very close to completing the process of connecting Claude to GA4. Next, we have to invite the service account to join GA4, exactly as you would a human colleague. Repeat this step for every property you want Claude to be able to query. Only give it Viewer access as we don’t want AI making any changes in GA4.

Giving the service account Viewer access in GA4
You will need to have Administrator access on the GA4 property to add users. If the Add button is greyed out, ask whoever manages the property to either upgrade your access or if they can add the service account email on your behalf.
Finally, you will need to modify the Claude Config file to connect your desktop Claude app to be able to communicate with your GA4 properties.
Claude Desktop keeps its settings in a file called claude_desktop_config.json. You need to add a section that tells it where the GA4 server lives and which credentials it uses. The server you installed in Step 3 will not appear in Claude until this file is saved and the app restarted.
claude_desktop_config.json. The button opens the folder, not the file.claude_desktop_config.json and open it in Notepad. If you have VS Code or Notepad++, use one of those instead: they’ll flag a missing comma before Claude has to.To add the server:
What you paste depends on what’s already in the file. If the file is empty, or contains only {}, replace everything with this:
{
"mcpServers": {
"analytics-mcp": {
"command": "C:\\pipx-new\\bin\\analytics-mcp.exe",
"args": [],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "C:\\keys\\ga4-mcp.json",
"GOOGLE_PROJECT_ID": "your-project-id"
}
}
}
}If the file already has an "mcpServers" section, don’t paste a second one. A JSON file can’t hold two keys with the same name, and one of them gets dropped without any error. Add your server inside the section that’s already there, separated by a comma.
{
"mcpServers": {
"a-server-you-already-had": {
"command": "..."
},
"analytics-mcp": {
"command": "C:\\pipx-new\\bin\\analytics-mcp.exe",
"args": [],
"env": {
"GOOGLE_APPLICATION_CREDENTIALS": "C:\\keys\\ga4-mcp.json",
"GOOGLE_PROJECT_ID": "your-project-id"
}
}
}
}Everything else in the file stays where it is. You can run as many MCP servers as you want: mcpServers is a list of named entries, and adding one doesn’t remove the others.
Windows paths need double backslashes inside JSON. C:\keys\ga4-mcp.json becomes C:\\keys\\ga4-mcp.json. A single backslash breaks the file.
Watch out for this: Notepad often adds a hidden .txt to the file name, saving it as claude_desktop_config.json.txt, which Claude will never see. In the Save dialog, set “Save as type” to “All Files” and “Encoding” to UTF-8, and check the name ends in .json with nothing after it. If you’ve already saved it, turn on file name extensions in File Explorer (View menu) to check, and rename it back if needed.

analytics-mcp listed in Claude Developer settings
Congratulations, you can now test using your new MCP connection in a new Claude chat, type:
“Can you list all the Google Analytics 4 accounts you have access to using the Google Analytics tool?”
Claude should now reply with the full list of GA4 accounts and properties you granted access to in Step 8. If it does, you’re connected, from here on, just ask questions in plain English.

Example response using Conversion Uplift’s own GA4 data
One habit worth keeping: always sanity check totals by asking Claude to run a separate report with no breakdowns for the same date range, rather than trusting a sum of rows from a breakdown table.
Windows is intercepting the command. Go to Settings, then Apps, then Advanced app settings, then App execution aliases, and turn OFF python.exe and python3.exe. Then open a new PowerShell window.
C:\Python isn’t on your PATH. Follow the PATH steps in Step 1. The entries need to go inside the existing Path variable, not as separate new variables. Then open a new PowerShell window.
The Scripts folder is missing from PATH, or there’s a typo in it. Check the Path entries character by character (C:\Python\Scripts). As a workaround, you can replace pipx with python -m pipx in any command.
where.exe analytics-mcp returns nothing.The pipx app folder isn’t on PATH, which is fine, since the config file uses the full path anyway. Confirm the file exists with dir C:\Users\YOURNAME\.local\bin\analytics-mcp.exe or dir C:\pipx-new\bin\analytics-mcp.exe.
Usually one of two things: Claude wasn’t properly restarted (close it with File, then Exit, not the X button), or there’s a JSON error in the config file, often a missing comma or bracket. Paste the config into a checker like jsonlint.com if it still won’t show.
Start a new chat and ask explicitly: “Use the analytics-mcp tools to…”. Also check the connector is switched on for that chat in the tools menu near the message box.
Nothing wrong with your setup. Anthropic’s servers are temporarily busy. Click Try again, or check status.claude.com.
Once it’s running, here’s what it actually changes:
Connecting Claude to GA4 won’t replace solid analytics knowledge, but it can cut down a lot of the friction between asking a question and getting an answer. If you or your team spend real time in GA4 but don’t want to live in the interface, this is a practical way to speed things up. To help your team, get AI to document all your events and parameters so that people know what to ask for, as otherwise, if you ask the wrong question, you will get the wrong answer or no answer at all.
This setup takes about an hour, done properly. After that, your analytics data is just a conversation away. It is also a great way of conducting regular audits to check for settings that may not be optimal for you, but remember to give it some context, such as the nature of your website and business goals, so that it can focus on what is most relevant to your website.
Claude will answer whatever your GA4 property tells it. If the property is mis-configured, you still get a confident answer, just built on the wrong numbers.
That is the part we handle. Neal wrote the official GA4 and GTM audit course for CXL, and we check GA4 properties, tag manager containers and server-side tracking setups so the numbers behind the answers hold up.
Prefer to talk it through first? Get in touch or email [email protected].
Related reading: the Google Analytics audit checklist, the Google Tag Manager audit checklist, and how to connect GA4 to BigQuery for analysis heavier than a chat window handles well.
So, the number of conversions and revenue are a lot lower in GA4 and Google Ads than what your back-end data shows you. Well, conversion tracking should tell you which marketing campaigns generate leads and sales. Too often, it does not. These are common problems we come across every day and we see the same causes across different sectors and website platforms.
Quick plugins and native integrations make conversion tracking easy to install, but easy does not always mean accurate. Here are five common weaknesses, and how web and server-side Google Tag Manager can create a more reliable measurement setup.
Conversions may be missing, duplicated or attributed to the wrong channel. The numbers reported in Google Analytics 4 (GA4), Google Ads, Meta and an ecommerce platform may all disagree. Worse still, inaccurate conversion data can influence automated bidding, causing advertising platforms to optimise campaigns using unreliable signals.
The problem often begins with a tracking setup chosen because it was quick to install rather than because it was designed around the business’s measurement requirements.
In the accompanying video, I explain five common weaknesses in conversion tracking and how to build a more robust setup using Google Tag Manager (GTM) and server-side GTM.
WordPress plugins such as Site Kit and ecommerce integrations available through app marketplaces can make GA4 quick to install. That is useful for a basic setup, especially when a business has limited technical resources.
However, convenience comes with trade-offs. You may have limited control over:
Most plugins rely on third-party cookies, and even those that do incorporate server-side tracking, set limitaions on which events and parameters which are sent server-side. Bowser-based implementations depend heavily on client-side scripts and requests. These can be restricted by browser privacy controls, content blockers, consent choices, network failures and implementation conflicts.
This creates gaps between what actually happened on the website and what appears in your analytics and advertising platforms.
A well-managed web GTM container gives you much more control. You can create a documented data layer, use consistent event names, apply validation rules and decide exactly which platforms receive each event.
GTM is not automatically accurate simply because it has been installed. It still needs a proper measurement plan, consent configuration, testing and ongoing governance. But it provides a far more flexible foundation than a collection of disconnected plugins.
After implementing GTM, check whether another plugin, theme, app or hard-coded script is also loading GA4 or the Google tag.
For example, a YouTube or GA4 app may continue to load its own tracking code after a new GTM implementation goes live. Two loaders can cause:
This does not mean every website with two Google-related scripts will definitely duplicate every event. The outcome depends on how each implementation is configured. Nevertheless, multiple uncontrolled loaders are a major warning sign. It is generally best practice to limit to a single loader.
Choose one governed implementation and remove or disable redundant tracking. Then test it in GTM Preview, GA4 DebugView and the browser’s network requests before publishing.
Web GTM is a major improvement over a fragmented plugin-based setup, but it still runs primarily in the visitor’s browser. Some measurement requests will be lost because of privacy controls, blockers, poor connectivity, page closures and technical errors.
Server-side Google Tag Manager adds a controlled tagging server between the website and analytics or advertising platforms.
Instead of the browser sending every request directly to several vendors, data can be routed through the business’s tagging endpoint. The server container can then validate, enrich, redact and distribute approved data to its destinations.
Google identifies improved performance, security and data control as key benefits of server-side tagging. A first-party context can also improve cookie durability and reduce the website’s direct communication with third-party domains.
You can host server-side GTM through Google Cloud or another suitable platform. Stape offers managed hosting that can reduce the technical work and cost of deployment, particularly for small and medium-sized organisations.
Its custom-loader options can serve tagging resources from a first-party route and alter recognisable loading patterns. This may improve resilience in some environments, but it should not be described as invisible tracking or as a guaranteed way to defeat blockers. Tracking must still respect consent choices, privacy law and the user’s browser settings.
Server-side tagging is also not a magic fix. A badly designed data layer will send bad data more efficiently. The underlying event logic must be correct before it is routed through a server container.
Creating a server container is only part of the job. If it continues to use the cloud provider’s default domain, you will not receive all the benefits associated with first-party serving.
Configure the tagging server on a domain connected to your website—for example, data.example.co.uk—or use a same-origin path where the infrastructure supports it.
Google describes same-origin serving as best practice because it provides the security and durability benefits of server-set cookies. A first-party subdomain is also a common and practical option.
After configuring the domain, verify:
A custom domain that exists but is not used by the live tags achieves very little. Test the actual network traffic rather than relying on configuration screens.
GA4 conversions—now called key events in the GA4 interface—can be imported into Google Ads. This is convenient and can be useful for reporting or as a secondary comparison.
However, for the conversion actions used for bidding, I generally recommend implementing dedicated Google Ads conversion tags through web and server-side GTM. This gives you greater control over the data sent to Google Ads and avoids making the GA4 import the only source used for campaign optimisation.
The dedicated setup should include, where relevant:
In Google Ads, mark the trusted conversion action as Primary so it is included in the Conversions column and can be used for bidding. Keep the GA4-imported action as Secondary if you want it for observation and comparison without double-counting it in bidding goals.
Do not make this switch blindly. Run both sources in parallel, compare volumes and values, investigate discrepancies and confirm the direct Google Ads action is stable first.
A robust setup normally follows this route:
This architecture will not produce a perfect one-to-one record of every conversion. No modern web analytics system can promise that. It does, however, give you more control, better governance and a stronger opportunity to recover valid measurement signals than a collection of unmanaged plugins.
Look for these warning signs:
These symptoms do not all have the same cause. A proper audit should examine the website, data layer, GTM containers, consent platform, browser requests, server logs, platform settings and backend totals.
Fast tracking installations are attractive, but a tracking tag appearing on a website is not proof that conversions are measured correctly.
Start by replacing fragmented plugins with a governed web GTM implementation. Remove duplicate loaders. Where the value and volume of conversions justify it, add server-side GTM, use a genuine first-party endpoint and send dedicated conversion data to advertising platforms.
Most importantly, test the complete journey—from the user’s action to the final platform report. Reliable conversion tracking is an engineered system, not a box to tick.
Call to action: If your analytics and advertising platforms disagree—or you are unsure whether your conversion data is trustworthy—Conversion Uplift can audit your GA4, Google Tag Manager, consent and server-side tracking setup. [Contact us to discuss a conversion-tracking audit.]
Common causes include incorrect triggers, duplicate tags, missing consent configuration, browser restrictions, cross-domain problems, broken data-layer values and platform settings that count the wrong actions as conversions.
Not automatically. GTM provides greater control, debugging and flexibility, which makes a robust implementation easier. Its accuracy still depends on the quality of the event logic, consent setup and testing.
No. It can improve measurement resilience and control, but it cannot recover every blocked or uncollected interaction. It must also continue to respect valid consent choices and applicable privacy law.
GA4 imports can be useful for reporting and comparison. For bidding-critical actions, a dedicated Google Ads conversion implementation often gives greater control. Avoid treating both versions of the same conversion as Primary unless intentional deduplication is in place.
You can technically send data to a provider’s default server URL, but a correctly configured first-party domain—or preferably a same-origin path where practical—is needed to gain the main cookie durability and first-party serving benefits.

GA4 attribution is often inaccurate because most websites misuse UTM parameters. Inconsistent UTM naming conventions, incorrect medium values, mixed casing, and poorly structured campaign tags all lead to broken attribution in Google Analytics 4. When UTMs are not implemented correctly, GA4 cannot reliably assign traffic to the right source, medium, or channel group, resulting in inflated Direct traffic, high Unassigned sessions, and misleading performance data. Correct use of UTM parameters is essential for accurate GA4 attribution, reliable channel reporting, and informed marketing decisions — without it, campaign analysis and ROI measurement are fundamentally unreliable.
You can either watch my video here or read the blog below — both cover the same process.
If you deal with messy GA4 attribution, inconsistent UTMs, or bloated channel groups, this will save you hours.
In a typical GA4 audit, you’ll head to Traffic acquisition report, and then start breaking things down by adding an extra dimension such as:
Session source / medium
Campaign name
Campaign ID (if used)
That’s where the fun stops.
What starts as ~20 rows quickly becomes hundreds once you factor in:
Google Ads
Meta / Facebook
TikTok
Email campaigns
Affiliates
Display
Random “one-off” campaigns
Go to the Explore section and create a custom report if you need to add multiple dimensions to your report. However, manually reviewing that is slow, boring, and error-prone.
Across most accounts we audit, we see the same issues:
Uppercase vs lowercase UTMs
Non-standard medium names (paid, social_paid, email_campaign, etc.)
Campaign names that mean nothing
Different teams using different “rules”
Marketers copying broken UTMs because “that’s how it’s always been done”
GA4 doesn’t forgive this. Attribution breaks. Channel groups inflate. “Unassigned” grows.
Here’s the exact process shown in the video.
Use Traffic acquisition or an Explore report
Include:
Session Source / Medium
Campaign (and campaign ID if relevant)
Then use the ‘Share this report’ option in the GA4 UI, and choose your preferred Download option. We use the CSV option.
Before uploading to AI:
Remove columns that add no value (company name, notes, etc.)
Keep it focused on attribution fields
This helps AI process the data properly and avoids it generating garbage.
Once uploaded, use a clear, structured prompt. Ours asks AI to:
Evaluate GA4 traffic acquisition data
Identify inconsistent or sub-optimal UTM usage
Flag:
Case sensitivity issues
Non-standard mediums
Broken or ignored naming conventions
Recommend:
Correct UTM structures
Cleaner channel grouping
How to split generic default channels into custom GA4 channel groups
The output is blunt — and that’s exactly what you want.
Here is the full prompt:
“Evaluate this traffic acquisition data from Google Analytics 4 and list inconsistent or sub-optimal use of UTM parameters, such as upper case and not using standard naming conventions that Google does not recognise. identify how changes in the use of UTM parameters could be deployed to provide more consistent channel groups to help marketing people set up UTM parameters for campaigns using best practice naming conventions. Also suggest how to break up generic default channel groups into custom channel groups in the GA4 console.”
AI excels at spotting patterns across hundreds of rows, including:
Paid instead of cpc
social_paid instead of paid_social
email_campaign instead of email
display_ads instead of display
Overloaded or meaningless campaign names
Bad examples vs good examples
Clear UTM naming frameworks
Practical guidance marketers can actually follow
Channel grouping recommendations that work with GA4 logic.
If your UTMs are wrong:
GA4 attribution is wrong
Channel performance is wrong
Budget decisions are wrong
AI doesn’t fix bad data automatically — but it exposes problems fast. That’s the real win.
Once AI has reviewed the data, you can:
Ask follow-up questions.
Simplify the language.
Generate a PDF audit summary to share with your client.
Share clear UTM rules with marketing teams.
This turns a messy export into something clients actually understand.
AI won’t replace proper GA4 implementation, but for attribution audits and UTM reviews, it’s a serious time-saver.
If you’re still eyeballing hundreds of GA4 rows manually, you’re doing it the hard way.
👉 Watch the video above if you want to see it live
👉 Read this blog if you want the repeatable process
Either way, clean UTMs = better attribution = better decisions.
AI assistants and AI search engines (ChatGPT, Gemini, Perplexity, Copilot, etc.) increasingly surface and share your content. This guide shows how to track AI referrals in GA4 using Google Tag Manager (GTM) and GA4 with a clean dataLayer push, so multiple tags (GA4/Ads/Meta) can consume the same signal.
Measure AI visibility: See how often AI platforms send you traffic and which platforms matter most.
Content strategy: Identify pages most cited by AI tools and double down on those topics for SEO purposes.
Channel comparison: Compare AI-sourced sessions with Organic/Social/Direct for engagement and conversion.
Campaign targeting: Build audiences (e.g., “Came from ChatGPT”) for remarketing or personalisation.
AI snippet tracking (e.g., text-fragment #:~:text= / PAA/Featured Snippets) measures clicks from enhanced Google SERP features.
This method measures referrals from external AI platforms (ChatGPT/Gemini/Perplexity/Copilot/You.com/etc.), outside traditional search.
Use both to see the full picture: inside-Google AI features and off-Google AI platforms.
A CustomJavaScriptVariable detects AI platforms via document.referrer and UTM hints.
A Custom HTML tag runs on DOM Ready and, if a match exists, pushes an ai_referral_detected custom event with parameters into the dataLayer.
You create Data Layer Variables (DLVs) that read those parameters.
A GA4 Event tag fires on the Custom Event (ai_referral_detected) and sends parameters to GA4.
Make sure you register custom dimensions in GA4 and analyse. To minimise the number of new event scoped custom dimensions that you need to register, try and re-use some generic custom dimensions that you may use elsewhere, such as type and sub_type.
GTM → Variables → New → Custom JavaScript
Name: CJ AI Source Detector
function () {
try {
// — Helpers as function expressions (ES5-safe in blocks) —
var trim = function(s){ return (s || ”).replace(/^\s+|\s+$/g,”); };
var lc = function(s){ return (s || ”).toLowerCase(); };
var getQueryParams = function(href){
var params = {};
var q = href.split(‘?’)[1] || ”;
if (!q) return params;
var hashSplit = q.split(‘#’)[0] || q; // strip fragment
var parts = hashSplit.split(‘&’);
for (var i=0; i<parts.length; i++){
var kv = parts[i].split(‘=’);
if (!kv[0]) continue;
var key = lc(decodeURIComponent(kv[0]));
var val = ”;
try { val = lc(decodeURIComponent(kv.slice(1).join(‘=’))); } catch(e) { val = lc(kv.slice(1).join(‘=’)); }
params[key] = val;
}
return params;
};
var build = function(platform, method, pattern){
return {
platform: platform.name,
category: platform.category,
detection_method: method, // ‘referrer’ | ‘utm’
match_pattern: String(pattern),
referrer: String(document.referrer || ”),
utm_source: qp.utm_source || ”,
utm_medium: qp.utm_medium || ”,
utm_campaign: qp.utm_campaign || ”
};
};// — Inputs —
var href = String(window.location && window.location.href || ”);
var ref = lc(String(document.referrer || ”));
var qp = getQueryParams(href);
var utmConcat = trim([qp.utm_source, qp.utm_medium, qp.utm_campaign].join(‘ ‘));// — Catalog of AI platforms (extend anytime) —
var catalog = [
{ name:’ChatGPT’, category:’AI Chat’,
domains:[/chat\.openai\.com/], utm:[/chatgpt/,/openai/] },
{ name:’Claude’, category:’AI Chat’,
domains:[/claude\.ai/], utm:[/claude/] },
{ name:’Poe’, category:’AI Chat’,
domains:[/poe\.com/], utm:[/poe/] },{ name:’Perplexity’, category:’AI Search’,
domains:[/perplexity\.ai/], utm:[/perplexity/] },
{ name:’Google Gemini’, category:’AI Search’,
domains:[/gemini\.google\.com/,/bard\.google\.com/], utm:[/gemini|bard/] },
{ name:’Microsoft Copilot’, category:’AI Search’,
domains:[/copilot\.microsoft\.com/,/bing\.com\/chat/], utm:[/copilot|bingchat/] },
{ name:’You.com’, category:’AI Search’,
domains:[/you\.com/], utm:[/youai|you\.com/] },
{ name:’Phind’, category:’AI Search’,
domains:[/phind\.com/], utm:[/phind/] },
{ name:’Kagi’, category:’AI Search’,
domains:[/kagi\.com/], utm:[/kagi/] },
{ name:’Brave (AI Summary)’, category:’AI Search’,
domains:[/search\.brave\.com/], utm:[/brave/] },
{ name:’DuckDuckGo (DuckAssist)’, category:’AI Search’,
domains:[/duckduckgo\.com/], utm:[/duckassist|ddg-ai/] },{ name:’Meta AI’, category:’Assistant’,
domains:[/meta\.ai/], utm:[/metaai/] },
{ name:’Arc Search’, category:’Assistant’,
domains:[/arc\.net/], utm:[/arc/] }
];// — 1) Referrer match —
for (var i=0; i<catalog.length; i++){
var p = catalog[i];
for (var d=0; d<p.domains.length; d++){
if (ref && p.domains[d].test(ref)) {
return build(p, ‘referrer’, p.domains[d]);
}
}
}// — 2) UTM match —
if (utmConcat) {
for (var j=0; j<catalog.length; j++){
var q = catalog[j];
for (var r=0; r<q.utm.length; r++){
if (q.utm[r].test(utmConcat)) {
return build(q, ‘utm’, q.utm[r]);
}
}
}
}// No detection
return null;
} catch (e) {
return null;
}
}
Create a new custom HTML tag in GA4 to push the parameters to the data layer. Use the DOM Ready trigger.
GTM → Tags → New → Custom HTML
Name: AI Referral – dataLayer push
Trigger: DOM Ready (once per page)
<script>
(function () {
try {
// prevent double-push on the same page
if (window.__aiReferralPushed) return;var det = {{CJ AI Source Detector}}; // returns object or null
if (!det || !det.platform) return;window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: ‘ai_referral_detected’,
ai_source_platform: det.platform,
ai_source_category: det.category,
ai_detection_method: det.detection_method,
ai_match_pattern: det.match_pattern,
page_referrer: det.referrer || document.referrer || ”,
ai_utm_source: det.utm_source || ”,
ai_utm_medium: det.utm_medium || ”,
ai_utm_campaign: det.utm_campaign || ”
});window.__aiReferralPushed = true;
} catch (e) {}
})();
</script>
If you enforce Consent Mode, add a consent check or fire this after consent is set.
Create the following Data Layer Variables (DLV) by going to the User Defined Variables and use enter the following keys to capture the values:
ai_source_platform
ai_source_category
ai_detection_method
ai_match_pattern
page_referrer
ai_utm_source
ai_utm_medium
ai_utm_campaign
Here we create a new GA4 Event tag for ai_referral_detected and use this send new parameters to GA4.
Tag type: GA4 Event
Event name: ai_referral_detected
Trigger: Custom Event → Event name = ai_referral_detected
Event parameters:
| Parameter | Value |
|---|---|
| type | {{ai_source_platform}} |
| sub_type | {{ai_source_category}} |
| method | {{ai_detection_method}} |
| pattern | {{ai_match_pattern}} |
| page_referrer | {{page_referrer}} |
| source | {{ai_utm_source}} |
| medium | {{ai_utm_medium}} |
| campaign | {{ai_utm_campaign}} |
GA4 → Admin → Custom definitions → Create custom dimension (Scope: Event):
To help prevent GA4 running out of event scoped custom dimensions, we suggest you use some generic labels, such type, and subtype to minimise the need for registering new custom dimensions. If you are automatically exporting your GA4 data to BigQuery, you don’t need to register the parameter names if you don’t plan to analyse them in the GA4 console.
ai_source_platform → use the generic name of “type”
ai_source_category → use the generic name of “sub_type”
AI Detection Method → use method
AI Match Pattern → use pattern
(UTMs don’t need registering unless you want them in standard reports.)
Test your set up in GTM Preview Mode and GA4DebugView before you publish.
GTM Preview: Load your site from an AI platform (or use a UTM test URL likehttps://yourdomain.com/?utm_source=chatgpt&utm_medium=aiassistant) and confirm the ai_referral_detected event appears with parameters.
GA4 DebugView: Check the event and parameters arrive.
Duplicates: The window.__aiReferralPushed guard helps avoid double pushes.
Use the Explore reports section of GA4 to create custom reports. First add all the necessary custom dimensions to the Free Form report. This will allow you to add them to the report. Create segments based upon the source of traffic, including the event ai_referral_detected.
Explorations (Free Form):
Dimensions: AI Source Platform (type), Landing page + query string
Metrics: Sessions, Engagement rate, Conversions
Compare AI vs Organic/Direct segments.
Funnel/Pathing:
Entry by AI Source Platform (type) → subsequent pages → conversion.
Audiences:
Build an audience where event_name = ai_referral_detected to compare lifetime value or remarket.
Looker Studio (recommended visuals):
Time series by AI Source Platform (type) with a filter set for event name equals ai_referral_detected.
Top landing pages for AI referrals
Conversion rate by platform and landing page
Multi-destination ready: The same event can feed GA4, Google Ads, Meta, or custom endpoints.
Debuggable: Easy to see in GTM’s Data Layer panel for QA.
Separation of concerns: Detection logic is isolated (variable), distribution is centralised (event).
Future-proofing: As new AI platforms emerge, update the catalog once; all tags keep working.
SPAs: On single-page apps, also fire on “History Change” if navigation happens without reload.
Strict CSP: If inline scripts are blocked, convert the push into a template or use a GA4 tag with DLV mapping.
Consent Mode: Align firing with your consent policy.
Evolving ecosystem: Keep the platform catalog up-to-date.
Tracking visits and backlinks from AI tools is becoming an essential part of understanding how your content is discovered and shared in an AI-driven web. By setting up this GTM and GA4 framework, you’ll gain visibility into how platforms like ChatGPT, Gemini and Perplexity surface your site — giving you insights traditional analytics can’t.
If you’d like support implementing this or improving your GA4 and GTM setup, get in touch with the team at Conversion Uplift by email [email protected]. We help businesses enhance data quality, streamline analytics, and uncover opportunities that drive measurable growth.

When it comes to SEO, alignment between your title tags, meta descriptions, and on-page headings plays a huge role in click-through rates and content performance. Our Google Tag Manager SEO audit allows you to compare what users see on your site with what search engines display in the SERPs — especially on dynamic or JavaScript-rendered pages?
That’s where a SERP Snippet Match Audit comes in. You can download a copy of the GTM receipe at the bottom of this post.
Many websites unknowingly have mismatched or duplicate metadata. For example:
The <title> tag doesn’t match the on-page H1
The meta description is missing or generic
The first paragraph doesn’t reflect the page intent
These inconsistencies can harm your click-through rates, confuse users, and weaken your content’s SEO relevance.
Traditional SEO crawlers show what’s in the static HTML — but modern websites often inject metadata dynamically through JavaScript frameworks like React, Next.js or Elementor. That’s why we can use Google Tag Manager (GTM) to collect these values directly from the rendered page and send them into Google Analytics 4 (GA4) for analysis.
You can use this simple Custom HTML tag in GTM to capture your metadata and push it into the data layer.
<script>
(function() {
try {
var titleTag = document.title || ”;var metaEl = document.querySelector(‘meta[name=”description”]’);
var metaDesc = metaEl ? (metaEl.getAttribute(‘content’) || ”) : ”;var h1El = document.querySelector(‘h1’);
var h1Text = h1El ? ((h1El.innerText || h1El.textContent || ”)).trim() : ”;var pEl = document.querySelector(‘p’);
var firstPara = pEl ? ((pEl.innerText || pEl.textContent || ”)).replace(/\s+/g,’ ‘).trim() : ”;
firstPara = firstPara.substring(0, 200); // keep it shortwindow.dataLayer = window.dataLayer || [];
window.dataLayer.push({
event: ‘serp_snippet_audit’,
serp_title: titleTag,
serp_meta_description: metaDesc,
serp_h1: h1Text,
serp_first_paragraph: firstPara
});
} catch (e) {
// Avoid breaking the page
}
})();
</script>
Trigger: DOM Ready
Event name: serp_snippet_audit
Once the data is pushed into the data layer, you can create a GA4 event tag with the same parameters (title_tag, meta_description, h1_text, first_paragraph) to store and analyse in GA4 or BigQuery.
GA4 won’t automatically recognise these new parameters. You must register them as Custom Dimensions before they can appear in your reports.
Follow these steps:
Go to your GA4 Property → Admin
Under Data display, select Custom definitions
Click Create custom dimension
Add each of the following with Scope: Event
Title Tag — Event parameter: title_tag — Description: The page’s HTML title
Meta Description — Event parameter: meta_description — Description: The page’s meta description
H1 Text — Event parameter: h1_text — Description: The first H1 text visible to users
First Paragraph — Event parameter: first_paragraph — Description: The first paragraph of on-page text
Save each one.
Wait up to 24 hours for data to appear in GA4 Explorations.
In GA4 Explorations, you can:
Compare Title Tag and H1 Text to find inconsistencies
Identify missing or duplicate Meta Descriptions
Review which pages have weak or empty first paragraphs
If your property exports data to BigQuery, you can go further — calculate text similarity scores or flag mismatched metadata programmatically.
For example, identify pages where the title and H1 don’t share any common words, or where the meta description repeats across multiple URLs.
It’s worth noting that Google often rewrites title tags and meta descriptions in the search results — usually to better match the user’s query or to shorten long titles. This behaviour can’t be tracked directly in GA4 or GTM, as it changes dynamically per search.
However, the SERP Snippet Audit is still valuable because it captures the on-page data you control — the title, meta description, and H1 that Google uses as inputs when deciding whether to rewrite. By analysing these elements together, you can identify pages with poor alignment or overly long titles that are more likely to be rewritten.
The goal isn’t to track Google’s edits, but to strengthen your own metadata so that when rewrites happen, they’re based on accurate, well-optimised content.
Works with JavaScript-rendered content (React, Next.js, Elementor, etc.)
Captures the rendered content seen by users and search engines
Automatically updates when content changes
Integrates seamlessly with GA4 and Looker Studio dashboards
For analytics and SEO teams, it bridges the gap between technical SEO and real-world user experience.
If you’re already using GTM for analytics or server-side tagging, adding a SERP Snippet Match Audit is a quick, low-overhead upgrade.
It reveals how well your metadata aligns with what’s visible on-page — helping you optimise for both CTR and relevance. Rather than creating your own tags, triggers and variables, you can download the receipe here.
Does your content say what your search results promise?
Now you can measure it.

Most GA4 and GTM audits focus on technical accuracy — checking tags, validating triggers, and fixing broken event tracking. While that’s important, it’s not enough.
If your audit doesn’t inspire action, build trust, and connect analytics to business outcomes, it’s just another report that gets ignored.
At MeasureCamp London 2025, I shared a session on how to make GA4 and GTM audits genuinely valuable — not just technically correct, but strategically useful. Here’s a summary of the key takeaways from my presentation.
Too often, audits are viewed as compliance tasks. A great GA4/GTM audit reframes that.
It shows how accurate data supports decisions that improve marketing performance, customer experience, and business growth.
Audits should empower teams, not just highlight problems.
Be transparent about what an audit can and can’t achieve. GA4 isn’t an accounting system — it’s designed for insight, not perfect accuracy.
Don’t over-promise. Some tracking fixes will need input from developers or backend teams. The goal is to build trust, not false expectations.
The best insights come from curiosity. Understand the client’s business model, key user journeys, and what success looks like for them.
An audit without context is just a list of fixes.
Avoid jargon. Talk about conversions, revenue, and customer experience — not tags, triggers, and data layers.
When stakeholders understand what you’re saying, they act on your recommendations.
Here are some practical ways to go beyond the basics:
Measurement Plan – Align business objectives with user goals and KPIs.
Regular Updates – Provide transparent weekly progress summaries: what was done, what’s next, key risks, and hours used.
Core Web Vitals – Use Google’s performance metrics to link analytics with site speed and user experience.
Automatic Alerts – Set triggers for sudden drops in conversions or traffic.
AI UTM Analysis – Use AI tools to identify poor UTM structures and suggest consistent naming conventions.
Event Values – Assign a value to key GA4 events based on conversion rate and lifetime value.
Device Mining Dashboard – Analyse conversion performance by device type, OS, and browser. Credit to Craig Sullivan and Charles Meaden for this concept. Get the dashboard here.
Session Replay – Tools like Microsoft Clarity add qualitative context to GA4 metrics.
BigQuery Export – Unlock unsampled GA4 data for advanced analysis and cost control.
Knowledge Transfer – Train teams via Microsoft Teams or Google Meet to interpret their own data. Empowerment is a form of added value.
A truly valuable GA4/GTM audit builds stronger partnerships. It delivers insights that clients can act on, transparency that drives trust, and measurable improvements that reinforce your credibility.
Adding value isn’t about doing more work — it’s about changing how your work is perceived.
You can access our comprehensive GA4 and GTM Audit checklist here.
Comments
Neal Cole
Founder of Conversion Uplift
Neal is the founder of Conversion Uplift and the author of the official GA4/GTM audit course for CXL. It's the course much of the industry trains on. He's spent over 20 years in digital analytics, including senior roles in online gaming and financial services, working out where businesses' numbers go wrong and what it costs them. His work now focuses on server-side tracking, GA4 and BigQuery: getting the data right, and being the person who's accountable for it when a decision depends on it.