Somebody on your team builds a UTM link by hand, in a hurry, right before a campaign goes live. It works. The link opens the page, the ad runs, the newsletter sends. Three weeks later you're staring at a GA4 report where a chunk of paid social traffic sits under Unassigned and a newsletter send shows up as Direct, and nobody can say why. The link worked. The tracking didn't. Those are two different things, and GA4 will not tell you which one failed — it just quietly stops counting.
The three parameters GA4 actually requires
Google's URL builder documentation is specific about this: when you add campaign parameters to a URL, use utm_source, utm_medium, and utm_campaign. utm_term and utm_content are optional add-ons — term is meant to hold a paid search keyword, content to distinguish two links pointing at the same page in the same campaign, like an A/B test on a CTA button.
Skip one of the three and GA4 doesn't reject the hit. It logs the session with (not set) in that dimension instead, per Google's guidance on traffic-source dimensions, which recommends setting all relevant parameters together rather than partially. A campaign missing utm_medium still gets counted — it just can't be grouped with anything else, because the field that tells GA4 what kind of traffic this is never arrived.
| Parameter | Required | Purpose | Missing it means |
|---|---|---|---|
utm_source | Yes | Where the traffic came from — newsletter, facebook, google | Session logged with source (not set) |
utm_medium | Yes | What kind of traffic — email, cpc, paid_social | Channel grouping can't classify the session |
utm_campaign | Yes | Which campaign drove the click | Traffic can't be tied to a specific push |
utm_term | No | Paid search keyword | No paid-keyword breakdown, otherwise harmless |
utm_content | No | Distinguishes near-identical links in one campaign | Can't tell which link or variant got the click |
A missing required field is the easiest mistake to catch automatically — the first thing a UTM Checker flags in a batch of pasted links, well before (not set) piles up in a report.
How casing quietly fragments one channel into three
UTM values are case sensitive — Google states this plainly: utm_source=google and utm_source=Google are different values to Analytics, not the same source spelled two ways. Tag one newsletter send utm_source=Newsletter and the next utm_source=newsletter, and GA4 reports two sources, each carrying half the sessions of what you'd otherwise call one channel.
This is where a team of three fractures its own data without anyone doing anything wrong. One person builds links by hand in a spreadsheet, one uses a browser extension, one copies last quarter's link and swaps the campaign name. Three habits, three casings, one channel split three ways — an org chart nobody asked GA4 to draw. Google recommends lowercase as the default for exactly this reason. Not because uppercase breaks anything technically. Because consistency is the only thing standing between one tidy row in your channel report and three fragments nobody thinks to add back together.
The self-referral trap
There's one UTM mistake that does more damage than a casing typo: setting utm_source to your own domain. It happens when a link gets copied from one part of the site to promote content elsewhere on it, or when a shortened link redirects through your own domain before landing on the destination page.
GA4 uses last-non-direct-click attribution by default: the most recent UTM-tagged link a visitor clicked gets credit for the session, including a link that happens to point back to your own site. Google built a whole referral-exclusion feature specifically because traffic from your own domain isn't supposed to count as a new source at all.
Your own domain is not a traffic source
If utm_source matches the hostname of the page it points to, that link is misattributing every session it drives. GA4's unwanted-referrals documentation exists because this exact scenario — a site referring traffic to itself — corrupts the last-non-direct-click chain that decides which source gets credit. It's an easy one to introduce by accident: copy a working UTM link from an old campaign, change the destination path, forget the source was never meant to point back here.
Why "fb" and "facebook" never land in the same bucket
Shortform habits cause a quieter version of the same problem. utm_source=fb and utm_source=facebook aren't a casing mismatch — GA4 doesn't try to reconcile them, because nothing in its Default Channel Group logic maps source abbreviations to full platform names. The channel grouping runs almost entirely on utm_medium, matching exact values and patterns:
| Channel | Matches when medium is... | Breaks when... |
|---|---|---|
| Paid Search / Paid Social | Contains "cp" (e.g. cpc), or is exactly ppc, retargeting, or starts with paid | Medium is ppc-ads (no exact match) or social-paid instead of paid_social |
| Organic Social | social, social-network, social-media, sm, "social network", "social media" | Medium is organic-social or social_media with an underscore — not on the list |
Source or medium is email, e-mail, e_mail, "e mail" | Medium is newsletter instead of email | |
| Affiliates | Medium is affiliate | Medium is affiliate-program or partner |
None of these are typos GA4 flags. They're valid strings that simply don't match the pattern list, so the session falls through to Unassigned instead — the bucket Google documents for traffic that arrived with parameters, just not ones the rules recognize.
Duplicate parameters and other errors that don't look like errors
A few more failure modes are worth checking for, because none of them throw a visible error either.
Two utm_source values in the same URL — usually from pasting a tracking link into a template that already had one — and whatever reads the query string first picks one and drops the other. Malformed percent-encoding, like a stray % that isn't a valid escape sequence, breaks decoding for that parameter and everything after it. And utm_term without utm_medium=cpc isn't wrong exactly — Google documents utm_term for paid keyword tracking, so setting it on an email or social link just leaves a field nobody will look up.
Space is a real constraint here, if an unusual one. GA4 caps the page_location parameter — the full URL, UTM string included — at 1,000 characters, and that limit counts the encoded length. A duplicated parameter or two unencoded spaces in the campaign name eats into that budget faster than the raw text suggests. Google documents the cap but not what happens to a hit that crosses it — clean truncation or a dropped hit is genuinely unclear from the public documentation, reason enough to treat 1,000 characters as a hard ceiling.
Checking a batch of links before they go live
Catching all of this by eye means opening every link, checking required fields, matching casing against the last campaign, and cross-referencing GA4's channel rules from memory. None of it throws a browser warning. The link works, the click happens, the data lands somewhere you didn't intend — and nobody notices until a report looks wrong weeks later.
Our free UTM Checker runs a batch of URLs through these checks at once: missing required parameters, duplicate or malformed parameters, casing and shortform inconsistencies across the batch, and a flag when utm_source matches your own domain. A Facebook in one row and a facebook in the next gets caught before either ships. Paste the links, get the corrected versions, nothing leaves your browser — no exotic errors, just the predictable result of building links by hand, a habit worth retiring in 2026. For links you're still building, the UTM Campaign Builder applies the same normalization rules on the way in, so there's less to catch on the way out.
