flowsk.com
How-to

The UTM taxonomy that survives a marketing team

Every team has a UTM convention document. Almost none have clean UTM data. The gap is enforcement — here is a taxonomy small enough to follow and a way to check it.

Jul 20, 2026· 3 min read ·How-to
Quick answer

lowercase · hyphens · closed list for medium · never empty · validate before launch

Analytics groups on the exact string, so Facebook and facebook are two channels. The fix is not a longer document — it is a shorter vocabulary plus a check that runs before a campaign goes live.

Keep utm_medium to six or seven values, forever. That is the parameter you group by when someone asks how much revenue comes from paid.

Your UTM convention document is not the problem. Every team has one, and almost every team has dirty UTM data anyway.

The problem is that a convention checked by memory, at 6pm, by someone launching a campaign in a hurry, is not a convention.

What drift costs

Three people launch in the same week:

?utm_source=facebook&utm_medium=cpc&utm_campaign=spring-sale
?utm_source=Facebook&utm_medium=paid-social&utm_campaign=Spring Sale
?utm_source=fb&utm_medium=ppc&utm_campaign=spring-sale

One campaign. Three rows. Each with a third of the conversions and a CPA that looks three times worse than reality.

Nobody gets an error. The report just becomes wrong in a way that looks like underperformance — so the reasonable reaction is to cut spend on something that was working.

The taxonomy

Short enough that people can actually hold it.

Parameter Rule Good Bad
utm_source The platform. One canonical value each. facebook FB, Facebook, facebook.com
utm_medium Closed list. How it was delivered. cpc paid-social, PPC, paid_search
utm_campaign The initiative. Lowercase, hyphenated, dated. spring-sale-2026 Spring Sale, spring sale
utm_content Creative or placement variant. video-a Video A (final v2)
utm_term Keyword — search only. running-shoes Running Shoes
utm_id Stable platform campaign id, where available. 23851234567 (empty)

The closed list for medium

This is the rule that matters most, and it is the one always broken first.

cpc          paid search and paid social clicks
display      banner and programmatic
social       organic social
email        every email, including transactional
affiliate    partners and affiliates
referral     genuine referrals

Six values. It should never grow. Source can be long-tailed — you will always add platforms — but medium is the axis you aggregate on when someone asks “how much of our revenue is paid?” The moment there are eleven mediums, three of which mean paid social, that question stops having an answer.

Campaign naming

Pick a pattern and use it everywhere:

{initiative}-{audience}-{yyyymm}

spring-sale-prospecting-202604
retarget-cart-abandon-202604
launch-lamp-broad-202605

Three benefits: it sorts chronologically, it is greppable, and the audience is visible in the report without opening the ad platform.

Rules that make it enforceable

1. Lowercase everything. No exceptions, no judgement calls.

2. Hyphens, never spaces or underscores. A space becomes %20 or + depending on who encoded it, which is two more variants of the same value.

3. Never leave a required parameter empty. utm_campaign= is worse than omitting it — some tools record an empty string as a distinct value.

4. One vocabulary, one place. Not a Notion page nobody opens. Somewhere the link builder reads from.

5. Build links, do not type them. The only reliable way to keep vocabulary consistent is to remove the step where a human types.

6. Validate before launch. Ten seconds against a checker beats a fortnight of a confusing report.

Fixing what you already have

You cannot rewrite history, and you do not need to. Normalise on read: map the variants to the canonical value at report time, and keep the original strings on the events.

facebook ← Facebook, FB, fb, facebook.com, meta
cpc      ← CPC, ppc, PPC, paid, paid-social, paidsocial, paid_search

Nothing is lost, the grouping is fixed, and past traffic regroups the moment you declare the canonical value.

Where to start

Paste your last month of campaign URLs into the UTM validator. It shows every casing difference, every synonym, every missing parameter, and prints the vocabulary those URLs should have used.

Most teams find between three and eight distinct problems in the first pass, and every one of them is currently splitting a row in their report.

Frequently asked questions

What is the difference between source and medium?

Source is where the traffic came from (facebook, google, newsletter). Medium is how it got there (cpc, email, social, referral). The most common mistake is putting the platform in both, which makes medium useless for grouping.

How many mediums should I have?

Six or seven, and the list should never grow. Source can be long-tailed because you will always add platforms; medium is the axis you aggregate on, so it has to stay closed.

Should I use underscores or hyphens?

Hyphens. Underscores are harder to read in a report and some tools treat them inconsistently. Pick one and never mix — mixing is worse than either choice.

What about ad platform macros?

Use them for utm_content and utm_id where the platform substitutes a stable value. Keep source, medium and campaign hand-controlled, because macros are exactly where uncontrolled vocabulary enters.

Can I fix historical data?

You can normalise on read — map variants to a canonical value at report time. The underlying events keep their original strings, which means nothing is lost and the grouping is fixed.

Check the campaigns you already launched

Paste your last month of campaign URLs and see every casing difference, synonym and missing parameter splitting your reports right now.

Validate my UTMs

Stop guessing which ad made the sale.

Flowsk Signals stitches the anonymous click to the email to the purchase — first-party, server-side, de-duplicated. One snippet, $29/mo, and every conversion comes with a receipt you can inspect.

Keep reading