Article · Mar 7, 2026 · 5 min read

URL encoding for UTM tracking links

UTM parameters are the standard for tracking marketing campaigns in Google Analytics and most other analytics platforms. They’re just regular URL query parameters with a specific naming convention — but they often contain text that needs URL encoding, and getting that encoding wrong silently corrupts your analytics data.

This article covers the UTM parameter spec, the encoding rules, and how to build URLs that survive every channel.

The five standard UTM parameters

Parameter Required? Purpose
utm_sourceRequiredWhere the traffic came from (e.g., google, newsletter)
utm_mediumRequiredChannel type (e.g., cpc, email, social)
utm_campaignRequiredCampaign name (e.g., spring_sale_2026)
utm_termOptionalPaid keyword for search campaigns
utm_contentOptionalDifferentiates ad variants (A/B testing)

When UTM values need encoding

UTM values are query parameter values, so they follow standard URL encoding rules. They need encoding if they contain:

A canonical example

// Campaign details
source:    "newsletter"
medium:    "email"
campaign:  "Spring Sale 2026"
content:   "CTA Button"

// Build the URL
const params = new URLSearchParams({
  utm_source: 'newsletter',
  utm_medium: 'email',
  utm_campaign: 'Spring Sale 2026',
  utm_content: 'CTA Button',
});
const url = `https://example.com/products?${params}`;

// Result:
// https://example.com/products?utm_source=newsletter&utm_medium=email
//   &utm_campaign=Spring+Sale+2026&utm_content=CTA+Button

Note: URLSearchParams uses + for spaces (form-encoded variant). Google Analytics and most platforms accept both + and %20.

The classic UTM URL bugs

1. Spaces left unencoded

// Wrong — manually built URL with raw space
const url = "https://example.com?utm_campaign=Spring Sale 2026";
// Browser may auto-fix this when typed, but copy-paste through emails/SMS breaks it

// Right
const url = `https://example.com?${new URLSearchParams({
  utm_campaign: 'Spring Sale 2026',
}).toString()}`;

2. Embedded ampersands in values

// Wrong — & in campaign name breaks the URL
?utm_campaign=Smith & Sons Spring Sale&utm_source=newsletter
// Server reads: utm_campaign="Smith ", " Sons Spring Sale", utm_source="newsletter"
// Three parameters where you wanted two.

// Right — encode the ampersand as %26
?utm_campaign=Smith%20%26%20Sons%20Spring%20Sale&utm_source=newsletter

3. Mixed case inconsistency

UTM values are case-sensitive in Google Analytics. utm_source=Newsletter and utm_source=newsletter show as separate sources in reports.

Best practice: always lowercase, use underscores instead of spaces:

utm_source=newsletter
utm_medium=email
utm_campaign=spring_sale_2026
utm_content=cta_button

This avoids both the encoding question and the case-sensitivity problem.

4. Hash fragment confusion

// User wants to link to a specific anchor on the page
// Wrong — UTM after the hash isn’t tracked
https://example.com/page#section?utm_source=newsletter

// Right — UTM before the hash
https://example.com/page?utm_source=newsletter#section

Analytics platforms read UTM parameters from the query string (before #), not the fragment.

Channel-specific gotchas

Email clients

Some email clients pre-process URLs (link preview, click-through tracking, URL shortening). The pre-processed URL might re-encode or double-encode your UTM parameters. Test in the actual email client before launching a campaign.

QR codes

Generators handle encoding correctly when given a clean URL. But if you paste a URL with already-encoded values, some generators double-encode. Provide raw URLs to QR generators.

SMS and instant messaging

Some platforms (especially older SMS gateways) strip URL parameters or break long URLs. Test by sending to yourself. Consider a URL shortener if the destination URL is over ~80 characters.

Social media auto-shorteners

Twitter, LinkedIn, and Facebook auto-shorten URLs, replacing the original with their own tracker. The UTM parameters survive the shortening (passed through to the destination), but the visible URL no longer shows them.

Print campaigns

URLs in print ads typically use a redirect (example.com/spring → real URL with UTM). Direct copy of a long UTM URL is hard for readers to type.

Building UTM URLs programmatically

JavaScript helper

function buildUtmUrl(baseUrl, utm) {
  const url = new URL(baseUrl);
  for (const [k, v] of Object.entries(utm)) {
    if (v) url.searchParams.set(`utm_${k}`, v);
  }
  return url.toString();
}

buildUtmUrl('https://example.com/products', {
  source: 'newsletter',
  medium: 'email',
  campaign: 'spring_sale_2026',
});
// "https://example.com/products?utm_source=newsletter&utm_medium=email&utm_campaign=spring_sale_2026"

Python helper

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

def add_utm(url, **utm):
    parts = urlparse(url)
    query = dict(parse_qsl(parts.query))
    for k, v in utm.items():
        query[f'utm_{k}'] = v
    new_query = urlencode(query)
    return urlunparse(parts._replace(query=new_query))

add_utm('https://example.com/products',
        source='newsletter',
        medium='email',
        campaign='spring_sale_2026')

Naming conventions that work

For values, stick to:

Verifying your UTM URLs

Before launching a campaign:

  1. Click the URL yourself — does it load the right page?
  2. Check Google Analytics Real-Time → Traffic Sources for the test click
  3. Verify all 3+ required parameters appear correctly
  4. Check the Acquisition → Campaigns report tomorrow for the recorded data

If values look mangled (extra % signs, truncation), trace back through your tooling — most often the bug is in the marketing platform that emits the link, not the destination.

Tools

Google’s Campaign URL Builder generates valid UTM URLs with proper encoding. Most CRMs and email platforms have built-in builders. For one-off URLs, paste the components into our URL builder and copy the encoded result.


Found this useful? Try the URL decoder, the URL encoder, or browse all tools.

More reading

From the blog.