On this page+
The most common version of this conversation: a marketer opens GA4 on Monday, the campaign that should have driven 5,000 sessions shows 1,200, and the ad platform claims 4,800. Either the campaign actually failed and somebody is fudging the platform numbers, or the tracking is broken. This piece is about the second case.
Six causes of UTM data drift, in order of frequency.
1. Mixed casing and inconsistent values
The most common. utm_medium=Email and utm_medium=email are two different rows in GA4. The same campaign tagged inconsistently across an email send, a paid social ad, and a partner blast splits into three rows. The data is still there, it is just split across rows that should have merged.
Symptoms:
- Multiple rows in Source/Medium for what should be one campaign
- "Email" and "email" both appearing in your weekly review
- A campaign showing fewer sessions than expected because half landed in a row you did not look at
Fix: one naming convention, applied at the link-builder level. The piece on utm naming conventions has the rules.
2. Channel name in utm_medium
The second most common. utm_medium=facebook instead of utm_medium=social. This puts your Facebook traffic into the "Other" channel grouping in GA4 because GA4's Default Channel Grouping is a string match on a specific list of values that does not include "facebook."
Symptoms:
- Big "Other" or "Unassigned" channel in your weekly review
- Total Paid Social sessions much lower than expected
- Drilldown shows the source values are correct (facebook, instagram, linkedin) but the medium is the platform name
Fix: change every active campaign's tagging convention to use utm_medium=social or utm_medium=paid_social for social channels. The piece on utm_source vs utm_medium has the channel-by-channel table.
3. Cross-domain redirect that strips UTMs
If your campaign sends a visitor from marketing.com to app.com and the cross-domain measurement is not configured, GA4 sees the second domain as a fresh visit attributed to the first as a referrer. The original UTM source is overwritten.
Symptoms:
- Your
app.comGA4 property shows traffic frommarketing.comas a referral source - Original
utm_source(linkedin, mailchimp, etc.) does not appear on the second domain - Total sessions per campaign are correct, but the channel attribution is wrong
Fix: GA4 Admin → Data Streams → Configure tag settings → Configure your domains. Add both domains. The piece on utm tracking in GA4 covers the full setup.
4. Server-side redirect that strips query parameters
A redirect from acme.com/landing to acme.com/landing-v2 that does not preserve the query string. The visitor lands on the new URL with no UTMs at all and shows up as direct traffic.
This is more common than teams realize. Common causes:
- A WordPress plugin that redirects 404s to the homepage and drops the query string
- A CDN-level redirect rule that does not include
*for query parameters - An A/B testing tool that rewrites URLs and strips parameters
- A SEO redirect cleanup that removed query parameters as a "best practice"
Symptoms:
- Campaigns show big "direct" traffic on days they should not
- The redirected URL works but lands without UTMs when tested
- Curl-ing the original URL with -L follows the redirect chain and shows where the strip happens
Fix: every redirect on the destination path must preserve query strings. The fix is platform-specific (Cloudflare Page Rules, Nginx config, WordPress 301 plugin settings).
5. In-app browsers and ad-blocker erosion
Instagram, Facebook, TikTok, and most other social apps open links in their own in-app browser. These browsers do not pass HTTP Referer headers to the destination. UTMs in the URL still survive (they ride in the URL itself rather than the referrer header), so GA4 still attributes correctly. But many ad-blockers and privacy-focused browsers (Brave, Firefox with Enhanced Tracking) block the GA4 script entirely, so the session is not recorded at all.
Symptoms:
- Ad platform reports 1,000 clicks, GA4 reports 700 sessions, gap of 30 percent
- Higher gaps on social campaigns than on email
- Lower gaps in Q4 than in Q1 (ad-blocker rates are seasonally lower in retail-heavy quarters)
Fix: nothing on the GA4 side. This is structural. Plan for a 10 to 25 percent gap between ad-platform clicks and GA4 sessions. If the gap is bigger, look elsewhere first.
6. Cookie-consent rejection
Many GA4 properties have a cookie-consent banner that blocks the GA4 script until the visitor accepts. If the visitor never interacts with the banner, no GA4 session is recorded.
This is GDPR-compliant and the right legal posture. It also means a substantial fraction of EU traffic and a smaller fraction of global traffic never makes it into GA4.
Symptoms:
- EU traffic is meaningfully lower in GA4 than other measurement
- Bounce rates appear artificially low because non-consenting users are not counted
- Direct traffic looks higher than it should because consenting users on the second pageview are counted while their initial UTM-tagged pageview was not
Fix: structural. Plan for a 10 to 30 percent gap on EU-heavy campaigns. Consider GA4 Consent Mode v2, which logs anonymized "ping" events from non-consenting users so totals are at least directionally right.
A diagnostic flowchart
When the numbers are off, work through this in order:
- 01
Are the UTMs actually in the URL?
Open the campaign link, follow it through any redirects, check that the final URL on landing has the expected utm_source, utm_medium, and utm_campaign. If they are missing, the issue is upstream (server-side redirect, link-builder error, copy-paste damage). - 02
Does GA4 Realtime see them?
Click the link in incognito, open GA4 Realtime → User snapshot. Confirm the snapshot shows the correct source and medium. If not, the issue is on the GA4 side (script not loading, consent banner blocking). - 03
Is the medium one of GA4's recognized channel-grouping strings?
If utm_medium=facebook, traffic falls into Other. Check the medium against the GA4 list in the utm_source vs utm_medium piece. - 04
Compare to the ad platform.
Pull the platform's click count for the same date range. A 10 to 25 percent gap is normal. A 50 percent gap usually points at a tracking config issue rather than at the campaign itself. - 05
Look for splits in the data.
Same campaign showing in multiple Source/Medium rows usually means casing inconsistency. Same medium in multiple rows usually means typo variants.
What to live with and what to fix
Some drift is structural and you cannot fix it:
- Ad-blocker erosion (10 to 20 percent)
- Cookie-consent rejection (10 to 30 percent in EU-heavy markets)
- Cross-platform deduplication differences (a unique visitor on Meta might be two sessions in GA4)
Some drift is fixable:
- Mixed casing in your team's UTM tags
- Channel names in
utm_mediuminstead of medium categories - Cross-domain measurement not configured
- Server-side redirects stripping query parameters
For the upstream end of this list, the free Trakl UTM builder handles the casing and channel-grouping pieces at the moment the URL is built, before any of the downstream drift can take hold.
For the long-term, a single shared link builder with an opinionated taxonomy fixes the team-side problems. The platform-side problems require triage and accepting some structural noise.
For the working setup, the UTM tracking in GA4 piece covers the GA4 settings. For the team-side discipline, utm naming conventions is the playbook.
Frequently filed
Common questions.
Q.01Why don't GA4 numbers match my ad platform's numbers?+
They almost never match exactly. Common reasons include ad-blocker erosion (10 to 20 percent of users), cookie-consent rejection, server-side redirects that strip query strings, in-app browsers that strip referrers, and timing differences (ad platform counts impressions and clicks, GA4 counts landed sessions). A 10 to 25 percent gap is normal. Larger gaps usually mean a tracking config issue.
Q.02My traffic is showing up as direct. What happened?+
The link did not carry UTMs through to the landing page. Common causes are a server-side redirect that strips query parameters, a 404 redirect to the homepage, an in-app browser that does strip the referrer (and the URL had no UTMs), or the link was typed manually and the UTMs were dropped along the way.
Q.03Why does the same campaign show up as multiple rows in GA4?+
Mixed casing or inconsistent values in the UTM parameters. utm_medium=Email and utm_medium=email are two rows. utm_campaign=Q2-Launch and utm_campaign=q2_launch are two rows. The fix is a single naming convention applied at the link-builder level so values are not retyped.
By the byline
Trakl TeamEditorial team
We build Trakl, a link shortener and UTM tracker for marketing teams. We write here from the cleanup work, support tickets, and campaign reviews that fill the rest of our week. Specifics over slogans, and we cite the source.
Photo: William Warby on Unsplash


