UTM Parameters Explained for Technical Teams

UTM parameters are five query string values — utm_source, utm_medium, utm_campaign, utm_term, and utm_content — appended to URLs that tell analytics platforms how a visitor arrived. Three are required; two are optional. GA4 reads them on page load and stores them as session dimensions. The devil is in the formatting: these parameters are case-sensitive, whitespace-sensitive, and need to be percent-encoded when they contain special characters. This reference covers the complete technical specification, how each major analytics platform parses the values, the common pitfalls that break tracking, and how to validate parameters programmatically before any link goes live.

Five UTM parameter cards — utm_source, utm_medium, utm_campaign (required), utm_term and utm_content (optional, dashed border) — assembled into a full URL at the bottom

What UTM parameters are and where they came from

UTM stands for Urchin Tracking Module. Urchin Software developed the tracking system in the early 2000s; Google acquired Urchin in 2005 and incorporated the mechanism into Google Analytics. The five-parameter convention has remained stable since then — one of the more durable pieces of web analytics infrastructure.

Technically, UTM parameters are ordinary query string key-value pairs. There’s nothing special about the protocol: they’re just ?key=value&key2=value2 appended to any URL. The “magic” is that Google Analytics and most other analytics platforms recognize the specific key names and store their values as session attributes. A URL like https://example.com/page?utm_source=linkedin&utm_medium=social&utm_campaign=spring-launch tells GA4 exactly where that session originated.

That’s also the limitation: UTM parameters only work if the analytics platform is configured to read them, and the values only mean what your taxonomy says they mean. There’s no central registry. If half your team uses utm_medium=social and the other half uses utm_medium=social-paid, those are different mediums in your reports, even if they describe the same channel. See the UTM tracking for developers guide for the full discussion of why naming consistency is a developer problem.

All 5 UTM parameters, with technical examples

utm_source — required

Identifies the traffic source: the platform, publisher, or partner sending the visitor. Think of it as the answer to “who sent this traffic?”

Examples: linkedin, google, newsletter, partner-acme, facebook, twitter, reddit

GA4 dimension: Session source. Visible in Acquisition → Traffic acquisition → Session source.

Critical rule: Lowercase only. LinkedIn, linkedin, and Linkedin are three distinct values in GA4 reports. Use hyphens for multi-word sources: google-display, not google display or google_display.

utm_medium — required

Identifies the marketing medium: the channel type. Think of it as “how was this traffic sent?”

Examples: social, cpc, email, display, affiliate, referral, organic

GA4 dimension: Session medium. Also used by GA4’s Default Channel Grouping to classify sessions as “Paid Search”, “Paid Social”, “Organic Social”, etc. GA4 looks for specific utm_medium strings to make these assignments. Use cpc for paid search (not paid-search or ppc) to get correct channel grouping.

GA4 channel grouping rules (partial): cpc or ppc → Paid Search; social or social-media → Organic Social; email → Email; display → Display. See GA4 documentation for the full regex-based matching rules.

utm_campaign — required

Names the specific campaign. This is the grouping dimension you’ll use most in reporting.

Examples: spring-launch-2026, q2-retargeting, brand-awareness-apac, product-demo-series

GA4 dimension: Session campaign.

Best practices: Use descriptive, consistent names. Include the quarter or year if campaigns are time-boxed. Avoid generic names like test or campaign1 that won’t be interpretable in six months. See the UTM naming convention guide for a full taxonomy reference.

utm_term — optional

Originally designed for paid search keywords. Identifies the search term that triggered the ad, or more broadly, any targeting parameter you want to track.

Examples (paid search): utm_term=campaign+link+validator, utm_term=utm+builder+tool

Examples (non-search): utm_term=saas-decision-makers, utm_term=retargeting-cart-abandon

GA4 dimension: Session manual term.

Encoding note: Spaces in utm_term values should be encoded as + or %20. Most analytics platforms handle both, but percent-encoding is technically correct per RFC 3986.

utm_content — optional

Differentiates multiple links within the same campaign or ad. Used for A/B testing, CTA variants, or multiple links in a single email.

Examples: header-cta, sidebar-banner, footer-link, image-ad, text-ad, variant-a

GA4 dimension: Session manual ad content.

Common use case: If you have three links in a single email newsletter all pointing to the same landing page with the same utm_campaign, use utm_content to tell them apart: utm_content=top-cta, utm_content=inline-link, utm_content=bottom-button.

How GA4, Mixpanel, and Amplitude parse UTM parameters

Google Analytics 4 (GA4)
GA4 reads UTM parameters from the page URL at session start. It stores them as session-scoped dimensions (Session source, Session medium, Session campaign) accessible in Acquisition reports and via the GA4 Data API. GA4 is case-sensitive: linkedin and LinkedIn are distinct values. GA4 also uses utm_medium for Default Channel Grouping — the regex-based classification that assigns sessions to channels like “Paid Search” or “Email”. Incorrect medium values result in sessions classified as “Unassigned”.
Mixpanel
Mixpanel’s JavaScript SDK reads UTM parameters and stores them as user properties ($initial_referring_domain, etc.) and as event properties on the first event of the session. Like GA4, Mixpanel is case-sensitive. Mixpanel also stores UTM values on the user’s profile at first touch, enabling first-touch attribution queries. Multi-touch analysis requires the UTM data to be consistently present on every session, which means validating that parameters survive redirect chains on every link.
Amplitude
Amplitude’s SDKs capture UTM parameters as event properties by default (utm_source, utm_medium, etc.) and can be configured to store them as user properties for attribution analysis. Amplitude’s Marketing Analytics add-on uses UTM data for channel attribution. Same case-sensitivity rules apply. Amplitude does some normalization (lowercasing) in certain SDK versions — but don’t rely on this; enforce lowercase at the source.
Segment
Segment’s Analytics.js library reads UTM parameters from the page URL and includes them in context.campaign on every track and page call. Segment passes this data downstream to all connected destinations. Because Segment normalizes the property names (source, medium, name instead of the raw UTM key names), verify how your specific destinations receive the values.

Common pitfalls that break UTM tracking

Case inconsistency
The most common cause of fragmented UTM data. LinkedIn, linkedin, Linkedin, and linkedIn are four distinct utm_source values in GA4. Enforce lowercase everywhere, without exception. Programmatic generation is the only reliable way to do this at scale — humans filling out forms introduce variation.
Spaces in parameter values
Spaces in UTM values (“spring launch”) should be encoded as %20 or +. Some tools percent-encode automatically; some don’t. A URL with unencoded spaces is technically malformed and may be parsed inconsistently across platforms. Use hyphens instead of spaces: spring-launch, not spring launch.
Special characters requiring encoding
Characters like &, =, #, ?, and non-ASCII characters in UTM values must be percent-encoded. An & in a campaign name (q1&q2-combined) will be parsed as a parameter delimiter, splitting your value incorrectly. Stick to alphanumeric characters, hyphens, and underscores in UTM values. Validate encoding programmatically.
Redirect chains stripping parameters
Some redirect configurations — particularly server-side 301 redirects and certain CDN configurations — drop query parameters from the destination URL. If your campaign link redirects through a marketing landing page system or a URL shortener, the UTM parameters may be stripped before the analytics platform reads them. The only way to detect this is to follow the redirect chain programmatically and verify the parameters are present on the final URL.
Double-encoding
When UTM links are generated by a tool that percent-encodes values, and then that encoded URL is passed through another system that encodes it again, you end up with double-encoded values: %2520 instead of %20. These show up as literal strings in your analytics reports. Validate the final URL to confirm encoding is correct.
Conflicting UTM parameters on the destination
If your destination URL already has UTM parameters (e.g., https://example.com/page?utm_source=organic) and you add more, the behavior depends on which set the analytics platform reads first. Most platforms read left-to-right and use the first occurrence. Test this with your specific analytics stack and avoid linking to URLs that already have UTM parameters.

How to validate UTM parameters programmatically

The mlz build command generates UTM-tagged links with enforced naming. Add --validate to verify the destination resolves before generating the link. This catches encoding issues, missing parameters, and destination problems at generation time:

mlz build --url "https://acme.com/lp" --campaign "spring-launch-2026" --source "linkedin" --medium "social" --validate --format json

The JSON output includes the tracked URL and all parameter values, ready for automated processing:

mlz build --format json
{
  "tracked_url": "https://acme.com/lp?utm_source=linkedin&utm_medium=social&utm_campaign=spring-launch-2026",
  "params": {
    "utm_source": "linkedin",
    "utm_medium": "social",
    "utm_campaign": "spring-launch-2026"
  },
  "destination_url": "https://acme.com/lp",
  "created_at": "2026-04-10T09:30:00.000Z",
  "link_id": "lnk_9wlvd9qi",
  "stored": true
}

For the full pre-publish validation including redirect chain verification and OG tag inspection, use mlz preflight. The validate UTM links before publishing guide has the complete walkthrough.

Frequently asked questions

Are UTM parameters case-sensitive?
The parameter names (utm_source, utm_medium, etc.) are case-insensitive at the HTTP level but should always be lowercase. The parameter values (linkedin, social) are case-sensitive in GA4 and most other analytics platforms — LinkedIn and linkedin appear as different sources in your reports. Always use lowercase values.
Do UTM parameters affect SEO?
UTM parameters don’t directly affect search rankings. However, duplicate content issues can arise if search engines index the same page with different UTM parameter combinations. Mitigate this by adding UTM-parameterized URLs to your robots.txt disallow list or by setting the canonical URL to the parameter-free version. Google’s crawlers typically don’t store UTM parameters — they strip them before indexing.
What order should UTM parameters be in?
The order doesn’t affect how analytics platforms parse the parameters — all five are read from the query string regardless of order. Convention is utm_source, utm_medium, utm_campaign, then utm_term and utm_content if used. Consistent ordering makes URLs more readable and easier to audit.
Should I use utm_term for non-search campaigns?
utm_term was designed for paid search keywords but can be used for any targeting parameter you want to track per-link. Some teams use it for audience segment identifiers (utm_term=enterprise-decision-makers) or geographic targeting tags. It shows up as “Session manual term” in GA4. Use it when you need a fifth dimension of differentiation that utm_content doesn’t cover.
What happens if I use utm_campaign but not utm_source?
GA4 attributes the session using whatever parameters are present. If utm_source is missing, the source dimension shows as “(direct)” or “(not set)” even though a campaign name is present. All three required parameters must be included for complete attribution. Validate every link before publishing to catch missing required parameters.

Generate validated UTM links from the terminal

MissingLinkz builds UTM-tagged links with enforced naming conventions and validates the destination before generating. No forms, no dashboards — just a CLI command.

npm install -g missinglinkz
mlz build --url "https://yoursite.com" --campaign "your-campaign" --source "linkedin" --medium "social" --validate

Free for up to 50 links/month. No credit card required.