Once you've connected GA4, you'll see GA4 metrics under the metrics selector
If you've connected GA4 and metrics don't show any value, the data is almost always arriving fine. The issue is that we can't tie a GA4 session back to a specific ad.
This article explains how the matching works, why it breaks, and how to fix it.
How we match GA4 data to your ads
We read the UTM parameters on the landing page URL and try two rules, in order.
Rule 1: ad ID.
If we find the ad ID anywhere in the standard UTM params, we match on that and stop. This is the most reliable one, since ad IDs don't change.
These are the parameters we read:
utm_contentutm_termutm_campaignutm_sourceutm_medium
The ad ID doesn't even need its own parameter. If it's mixed in with other values inside one of those five, we'll still find it. What won't work is a custom parameter like creative=123456, because we don't read parameters outside that list.
Rule 2: names.
If there's no ad ID, we fall back to matching the ad name, the ad set (or ad group) name and the campaign name against what we hold in your ad account. All three have to match. Two out of three gets no credit.
Why name matching many times fails
The campaign was renamed after the ads went live
This is a common one. UTM parameters are baked into the ad when it's published, so renaming a campaign in your ad platform doesn't update them. GA4 keeps sending the old name while your ad account holds the new one. Rule 2 needs all three names, so the events get dropped.
You'll often see the same ad split across both states: the traffic from before the rename fails to match, and anything published after it matches fine.
The UTMs were typed in by hand and differ from names in ad platform
If campaign and ad set names are written manually into the URL rather than pulled from the platform's dynamic variables, small differences almost certainately creep in.
A space instead of an underscore, a pipe instead of a hyphen, a truncated name.
Rule 2 needs exact matches, so near misses don't count.
You're not using ad name, ad set name AND campaign name
In many cases some users pass some names, but not all, as part of any of the standard utm params.
The quickest fix: pass the ad ID
Every major platform has a dynamic variable that resolves to the ad ID at click time. Add it to your tracking setup and the matching stops depending on names entirely, which means renames no longer break anything.
Platform | Variable for ad ID |
Meta |
|
Google Ads |
|
TikTok |
|
|
You can pass it on any standard UTM param.
Drop it into utm_content if that parameter is free. For example:
utm_content={{ad.id}}
Where to set dynamic variables on ad platforms
Ad platforms update their UI very frequently, so this may change, but currently:
Meta. The URL parameters field at ad level, under URL parameters
below the website URL, on the tracking section
Google Ads. Google gives you multiple options. You can find the tracking template under Admin, then Account settings, then Tracking. Setting it at account level applies it everywhere. Note that {creative} is a ValueTrack parameter, so it belongs in the tracking template or final URL suffix rather than typed into the final URL.
TikTok. The URL parameter field on the ad. TikTok has no parameter inheritance, so every ad needs its own configuration unless you use URL auto-attach at account level.
LinkedIn. Tracking parameters at campaign or ad account level, not per ad.
Also worth doing: use dynamic variables for names
Even with the ad ID in place, using dynamic variables for your campaign and ad names keeps everything else consistent with your ad account. Here's the pattern we use on Meta:
utm_source=facebook&utm_medium=cpc&utm_campaign={{campaign.name}}_{{adset.name}}&utm_content={{ad.name}}
If you need utm_content for the ad name, you could put the ad ID in utm_term instead.
Platform quirks to know about
TikTok macro names are misleading. __CID__ is the ad ID and __AID__ is the ad set ID, which is the opposite of what the letters suggest. Macros use two underscores on each side. A single underscore fails silently and passes the raw text into your URL.
Google Ads changes take time. Tracking template updates take roughly 24 to 48 hours to appear in serving ads.
Performance Max has no ad ID. {creative} won't resolve for PMax campaigns. The closest equivalent is {assetgroupid}, which sits at asset group level rather than ad level.
LinkedIn renamed its hierarchy. As of October 2025, Campaign Group became Campaign and Campaign became Ad Set. Depending on your account, the macro picker may show {{CREATIVE_ID}} or {{AD_ID}}. Check what's actually offered in the picker before you build the string. LinkedIn dynamic parameters also don't work on Conversation Ads or Message Ads.
After you make the change
New traffic will start matching once the updated URLs are live and the platform has picked them up.
Historical data won't backfill. Those clicks already happened with the old UTM values attached, and there's no way to rewrite them after the fact.
Checking it worked
Preview or click one of your ads.
Look at the landing page URL in your browser. The variables should have resolved into real values, not raw text like
{creative}or__CID__.Confirm the ad ID is sitting in one of the five parameters we read.
Give it a day, then check the GA4 columns in your report.
If it's still empty after that, send us the resolved URL from step 2 and we'll take a look.

