Skip to content

Grokem · https://www.grokem.com/data/data-analytics/marketing-measurement/campaign-tracking/utm-parameters/utm-naming-conventions

UTM ParametersBest practices

UTM parameters: naming conventions that survive a year of campaigns

Five tracking parameters, one rulebook and a small script that enforces it, so 'Email', 'email' and 'e-mail' stop appearing as three different channels.

Grokem Editorial

Editorial desk

Published
  • 4 min read

UTM parameters are small additions to a link that tell your analytics where a visit came from:

text
https://example.com/pricing?utm_source=newsletter&utm_medium=email&utm_campaign=spring-sale-2025&utm_content=header-button

They are a great idea until six people use them for a year without agreeing on spelling. Then the channel report lists email, Email, e-mail and newsletter as four different mediums and nobody can say how e-mail performed.

The five parameters

Parameter Answers Example
utm_source Where the visit came from newsletter, linkedin, google
utm_medium What kind of channel email, cpc, social
utm_campaign Which initiative spring-sale-2025
utm_content Which link or creative, when there are several header-button, banner-b
utm_term The paid keyword (search campaigns) running-shoes

The first three are the ones to require. The other two earn their place when you need to compare links in the same message or ads in the same campaign.

The rules, and why each exists

The checklist above is the rulebook. The reasons are practical:

  • One spelling. Analytics tools match values as exact text, so every variant is a separate row. Lower case and hyphens remove most variants.
  • A closed list for medium. Default channel groupings in analytics tools are built from the medium. A medium nobody expected ends up in "Unassigned" or "Other".
  • No tags on internal links. A tagged link on your own site tells the analytics tool that a new visit has started, from a source that is your own website. It destroys the real origin of the session.
  • No personal data in URLs. Links are copied into e-mails, chats and server logs. Anything in the URL should be assumed public.

Enforce it with code

A rule that depends on memory fails. This script builds tagged links, normalises the values and refuses a medium that is not on the list.

python
import re
from urllib.parse import parse_qsl, urlencode, urlparse, urlunparse

ALLOWED_MEDIUMS = {"email", "cpc", "social", "referral", "affiliate", "display"}


def clean(value: str) -> str:
    """lower case, words joined by hyphens, nothing but letters, digits and hyphens"""
    value = re.sub(r"[^a-z0-9]+", "-", value.strip().lower())
    return value.strip("-")


def tag_url(url: str, source: str, medium: str, campaign: str, content: str = "", term: str = "") -> str:
    medium = clean(medium)
    if medium not in ALLOWED_MEDIUMS:
        raise ValueError(f"medium {medium!r} is not one of {sorted(ALLOWED_MEDIUMS)}")
    parts = urlparse(url)
    query = dict(parse_qsl(parts.query))          # keep any parameters the link already has
    query.update({"utm_source": clean(source), "utm_medium": medium, "utm_campaign": clean(campaign)})
    if content:
        query["utm_content"] = clean(content)
    if term:
        query["utm_term"] = clean(term)
    return urlunparse(parts._replace(query=urlencode(query)))


print(tag_url("https://example.com/pricing", "Newsletter", "Email", "Spring Sale 2025", content="Header Button"))
print(tag_url("https://example.com/landing?ref=partner", "LinkedIn", "social", "Launch / Webinar!"))
try:
    tag_url("https://example.com", "x", "e-mail", "y")
except ValueError as error:
    print(error)
text
https://example.com/pricing?utm_source=newsletter&utm_medium=email&utm_campaign=spring-sale-2025&utm_content=header-button
https://example.com/landing?ref=partner&utm_source=linkedin&utm_medium=social&utm_campaign=launch-webinar
medium 'e-mail' is not one of ['affiliate', 'cpc', 'display', 'email', 'referral', 'social']

Three things to notice. Messy input (Spring Sale 2025, Launch / Webinar!) becomes clean values. A link that already carries a parameter (ref=partner) keeps it. And e-mail is rejected rather than guessed at, so the person building the link has to pick email and the reports stay clean.

Keep a registry

A shared sheet with one row per campaign (name, owner, dates, the exact UTM values, the landing page) turns tagging from guesswork into a record. It also answers the question that otherwise arrives six months later: "what was summer-promo-b?"

Check before you celebrate

After launching a campaign, click a tagged link yourself in a private window. Within a few minutes, the visit should appear in the real-time report under the source and medium you intended. A broken link found in the first hour is a typo; found a month later it is a month of missing data.

Checklist

  • Use all of utm_source, utm_medium and utm_campaign on every campaign link. Add utm_content to tell apart links in the same message, and utm_term for paid keywords.
  • Write everything in lower case. Reports treat 'Email' and 'email' as different values, and nobody remembers which one they used last time.
  • Use hyphens instead of spaces, and avoid other punctuation. Spaces become %20 and make links ugly and error-prone.
  • Choose utm_medium from a short, fixed list (for example email, cpc, social, referral, affiliate, display) and let nothing else in. Mediums drive your channel reports.
  • Make utm_source the specific origin (newsletter, linkedin, google) and utm_campaign the initiative (spring-sale-2025). Put the date or year in campaign names so they stay unique.
  • Never add UTM parameters to links inside your own site. They start a new session and replace the real source of the visit. Track internal clicks with events.
  • Never put personal data (an e-mail address, a name, a customer id) in a link. URLs are logged, shared and cached everywhere.
  • Keep a shared registry of every source, medium and campaign in use, and one owner who approves new values.
  • Generate links with a tool or script, not by hand, so the rules are enforced and not merely written down.
  • Check campaigns after launch: click a tagged link yourself and confirm the visit appears under the intended source and medium.

Frequently asked questions

Do UTM parameters work for every analytics tool?

They are a convention, not a standard. Google Analytics reads them by default, and most other web analytics tools also understand utm_source, utm_medium and utm_campaign, but check yours.

What about links that are shared or copied?

A shared link keeps its parameters, so a tagged link posted by a reader attributes their friends' visits to your campaign. Use a short link for the public, and tagged links for the channels you control.

References

From Grokem: https://www.grokem.com/data/data-analytics/marketing-measurement/campaign-tracking/utm-parameters/utm-naming-conventions

How did this strike you?

Be the first to react – it is anonymous.

Community

Questions about this?

Ask in Questions and help and get help from other readers.

Ask a questionBrowse Questions and help

Comments

No comments yet. Share what worked for you, or ask a question.

Choose what we may use. You can change this at any time with “Privacy choices” at the foot of every page. Details are in the Cookie policy and the Privacy policy.

Strictly necessary

Remembers your theme, the lessons you marked as done and this choice. It stays on your device, tracks nothing and cannot be switched off.

Always on
What exactly is collected, and why

Grokem’s own counts

Collects
The pages you open and how long you stay, how far you scroll, where you came from, your device type, browser, screen size, language and time zone. Your IP address is turned into a code that changes every day; it is never stored as it is.
Why
To see how long lessons are read and where readers leave. Not shared with anyone.
Stored
A random visitor ID, a visit ID and the time of your last page view in your browser’s storage (gr_vid, gr_sid, gr_last). No name or email is attached.