Skip to content
Can Elmas

Attribution · 8 min read

UTM Naming Conventions: A Template Your Whole Team Will Follow

TL;DR

Fix UTMs by locking a short list of lowercase source and medium values that match GA4's default channel rules, building campaign names from one fixed pattern, and creating every link in a validated builder sheet with a named owner. Then reclassify historical values with a custom channel group or mapping table instead of trying to rewrite old data.

· Published · Updated

Traffic lands in Unassigned when GA4 receives a source and medium pair its channel rules don’t recognize, and it piles into (other) when campaign values are so varied that reports hit their row limits. The fix is a short, fixed vocabulary for source and medium, one pattern for campaign names, and a builder sheet everyone has to use.

Why messy UTMs break reporting

UTM parameters are free text, and everyone who hand-types a link invents a slightly different value. Each variation does specific damage:

  • Unassigned traffic. A pair like newsletter / blast or partner-x / influencer matches no default channel rule, so it lands in Unassigned.
  • Misclassified traffic. facebook / social-paid isn’t recognized as paid, but the source is on GA4’s social list, so paid spend shows up as Organic Social.
  • Split rows. GA4 treats Facebook, facebook and fb as three different sources, spreading paid social across rows nobody adds up.
  • (other) rows. When campaign or content values include timestamps, per-send IDs or one-off names, unique values multiply and reports roll the long tail into (other).

When I audit GA4 properties, the cause is rarely one big mistake; it’s years of small inconsistencies. Messy UTMs also make GA4 harder to reconcile with ad platforms (see why GA4 and ad platforms don’t match).

How GA4 reads UTM parameters

GA4 maps each parameter to a session-scoped dimension:

ParameterGA4 dimensionUse it for
utm_sourceSession sourceWhere the click came from: facebook, bing, klaviyo
utm_mediumSession mediumThe type of traffic: cpc, paid_social, email
utm_campaignSession campaignThe specific campaign or initiative
utm_contentSession manual ad contentWhich ad, creative or link
utm_termSession manual termKeyword or audience
utm_idSession campaign IDCampaign ID, a key for cost data imports

The channel is not a parameter. GA4 derives it from source and medium, and sometimes campaign name, using its default channel group rules (the full list is in Google’s GA4 help center). The ones that matter most:

  • Paid channels need a medium matching ^(.*cp.*|ppc|retargeting|paid.*)$, so cpc, ppc and anything starting with paid qualify. The source then picks the channel: a recognized social source gives Paid Social, a search engine Paid Search, a video site Paid Video, anything else Paid Other.
  • Organic Social triggers on a recognized social source or a medium such as social.
  • Email, SMS, Affiliates, Audio, Referral and Mobile Push Notifications trigger on specific mediums: email, sms, affiliate, audio, referral, and anything ending in push.
  • Campaign names count too. A name containing “cross-network” goes to Cross-network. “Shop” or “shopping” in a campaign name can pull traffic into Paid Shopping or Organic Shopping, and the pattern also catches words like shopify and shop-now.

Rules for source and medium

Source and medium decide the channel, so four rules apply:

  1. Lowercase only. GA4 reports are case-sensitive.
  2. Letters, numbers, hyphens and underscores only. No spaces, ampersands or accents.
  3. Source is the platform or publisher, spelled out in full (facebook, not fb or meta-ads) so it matches GA4’s source lists. Never the campaign, audience or ad name.
  4. Medium is the traffic type and comes from a closed list. Nobody adds one without the owner’s approval.

The approved vocabulary:

Trafficutm_sourceutm_mediumGA4 channel
Meta (incl. Instagram), LinkedIn or TikTok adsfacebook, linkedin, tiktokpaid_socialPaid Social
Microsoft AdsbingcpcPaid Search
Programmatic displaynetwork namedisplayDisplay
Organic social postslinkedin, x, facebooksocialOrganic Social
Email to your own listklaviyo or hubspotemailEmail
SMSsending platformsmsSMS
Affiliatesnetwork or partner nameaffiliateAffiliates
Partner and PR linkspartner domainreferralReferral
Podcast sponsorshipsshow nameaudioAudio

QR codes, events and print have no default channel. Give them one consistent medium (qr, event) and a custom channel group rather than forcing them into the wrong channel.

Campaign, content and term conventions

utm_campaign

Build it from fixed parts in a fixed order, joined with underscores:

[yyyy-mm]_[objective]_[audience]_[offer]_[geo]

Example: 2025-11_prospecting_saas-founders_growth-audit_us

  • Objective comes from a short list: prospecting, retargeting, retention, launch, brand.
  • Audience and offer join words with hyphens, never underscores.
  • Geo is optional, goes last and uses country codes.
  • Never skip a middle part. Use all when a campaign targets everyone, so every name splits into the same columns by position.

The date prefix sorts campaigns and makes a quarter easy to filter; always-on campaigns use evergreen in its place. Keep “shop” out of every part unless it really is a shopping campaign.

utm_content

Identify the creative or link, not the campaign: [format]_[concept]_[variant], for example video_founder-story_v2 or static_pricing-table_v1. In email, use the link’s position: hero-cta, footer-link.

utm_term and utm_id

Paid search keywords come through auto-tagging, so use utm_term for social targeting: lookalike-purchasers, job-title-cmo. Pass the platform’s campaign ID in utm_id wherever a dynamic value exists; it’s part of the join key for GA4 cost data imports and for merging spend in a dashboard.

Never put personal data in UTMs. No email addresses, names or phone numbers; Google Analytics policies prohibit sending personally identifiable information. Skip per-subscriber IDs too; they only feed the (other) row.

Platform-by-platform examples

Google Ads. Leave auto-tagging on and link the account to GA4; the click ID carries source, medium and campaign.

Microsoft Ads. Turn on UTM auto-tagging in account settings; it applies bing / cpc plus campaign values.

Meta. Add URL parameters at the ad level with dynamic values:

utm_source=facebook&utm_medium=paid_social&utm_campaign={{campaign.name}}&utm_term={{adset.name}}&utm_content={{ad.name}}&utm_id={{campaign.id}}

Dynamic values are only as clean as your Ads Manager names, and renaming a live campaign splits its rows in GA4.

LinkedIn. Add URL parameters in Campaign Manager’s campaign settings with utm_source=linkedin&utm_medium=paid_social and your campaign name.

TikTok. Add parameters at the ad level; its name macros are safe only if campaign, ad group and ad names follow the convention.

Email (Klaviyo, HubSpot). Both can append UTMs automatically; if their defaults put a campaign or flow name in utm_source, email scatters across hundreds of sources. Use the platform as source, email as medium and the send or flow name as campaign; map any default you can’t change.

Organic social and bio links. utm_source=linkedin&utm_medium=social&utm_campaign=evergreen_brand_all_founder-posts.

QR codes and print. utm_source=packaging&utm_medium=qr&utm_campaign=2025-11_retention_customers_insert-card. Point the code at a redirect you control, so you can fix parameters without reprinting.

Governance: builder sheet and ownership

Conventions hold when the easiest way to create a link also enforces the rules.

The builder sheet

One Google Sheet with two tabs:

  • Dictionary. Approved channels, their source options and the one medium each uses. Values are defined only here.
  • Builder. One row per link, with date, owner and destination so bad values can be traced. Channel, source, objective and audience are dropdowns fed by the dictionary, set to reject other input; medium fills in from the channel.

Useful formulas, assuming the destination URL in column A, channel in B, source in C, medium in D, the five campaign parts in E to I, campaign in J and content in K:

  • Campaign: =LOWER(TEXTJOIN("_",TRUE,E2:I2))
  • Final URL: =A2&IF(ISNUMBER(FIND("?",A2)),"&","?")&"utm_source="&C2&"&utm_medium="&D2&"&utm_campaign="&J2&IF(K2="","","&utm_content="&K2)
  • Check: =IF(REGEXMATCH(C2&D2&J2&K2,"^[a-z0-9_-]+$"),"OK","FIX")

The FIND test handles destinations that already have a query string. Parameters must sit before any # anchor, so strip anchors from the destination column. Format the month column as plain text, or Sheets turns 2025-11 into a date.

One named owner

Name one person who owns the dictionary, usually whoever runs analytics or marketing ops. They approve new values before use, review GA4 monthly for values outside the dictionary, and walk every new hire, agency and freelancer through the sheet.

The rules they enforce:

  • Every external link comes from the builder, including agency and partner links
  • No UTMs on internal links or site banners
  • Short links are created from the tagged URL, not tagged afterward
  • Redirects preserve query strings (test one per domain)
  • Ad platform names follow the convention wherever dynamic values are used

Setting this up is one of the first things I do in a marketing attribution engagement, because every dashboard downstream depends on it.

Fixing historical UTM mess

GA4 doesn’t let you edit collected data, so old UTMs can’t be rewritten. They can be reclassified.

  1. Export the damage. In the Traffic acquisition report, set 12 months, use Session source / medium with Session campaign as a secondary dimension, and export sessions and key events. Use this standard report, not an exploration, which only reaches back as far as your data retention setting (two months by default).
  2. Build a mapping table. One row per messy pair, with the clean source, medium and channel it should have had.
  3. Create a custom channel group under Admin, Data display, Channel groups. Copy the default group and add rules that catch legacy values, such as social-paid from a social source going to Paid Social. Rules run top to bottom, so place each one above the default channel that would otherwise claim the traffic. Custom channel groups apply to historical data too.
  4. Apply the mapping in your reporting for anything a channel rule can’t express, by joining the table in Looker Studio or BigQuery. In an automated pipeline, it belongs in the normalization step (see automating marketing reporting).
  5. Shut off the sources. Find live links still producing bad values: old ads, email templates, bio links, partner pages, printed QR codes. Replace them, or the cleanup never ends.

An example mapping table:

Messy source / mediumClean source / mediumChannel
Facebook / Social-Paidfacebook / paid_socialPaid Social
newsletter / Emailklaviyo / emailEmail
partner-x / influencerpartner-x / affiliateAffiliates

Some Unassigned traffic has nothing to do with UTMs: server-side or Measurement Protocol events sent without session information land there too. If Unassigned stays high after cleanup, check how your tags pass session data.

Get it built

If more of your traffic sits in Unassigned than in any real channel and you want the convention, builder sheet and cleanup done for you, start with the Growth Audit: $1,500 fixed, credited if we continue. See pricing or get in touch.

FAQ

Frequently Asked Questions

Should UTM parameters be lowercase or uppercase?

Lowercase. GA4 reports treat Facebook and facebook as different values, so mixed case splits one source into several rows. Enforce it in the builder sheet with a LOWER formula and a validation check.

Do I need UTM parameters on Google Ads links?

Usually not. With auto-tagging on and Google Ads linked to GA4, the click ID supplies source, medium and campaign. Add manual UTMs only if another tool needs them, and use google / cpc so the values agree.

Should I put UTM parameters on internal links or site banners?

No. Internal UTMs make your own site look like the traffic source and take conversion credit away from the channel that actually brought the visitor. Track internal promotions with GA4 events instead, such as select_promotion for ecommerce banners.

Do UTM parameters hurt SEO?

Not if every page carries a canonical tag pointing to its clean URL, which tells search engines to consolidate the parameter versions. Keeping UTMs off internal links also stops crawlers from finding parameter URLs on your own site.

Work with me

Let’s find your biggest growth lever

Tell me about your growth challenge. I’ll tell you honestly if I can help — and if I can’t, who can.

  • ✓ No obligation
  • ✓ No sales script
  • ✓ Honest feedback
  • ✓ Clear next steps