Skip to main content
← All Articles · · 10 min read

UTM Parameters Complete Guide for Developers 2025

Master UTM parameters for accurate campaign tracking. Learn all 5 UTM params with real examples, naming conventions, GA4 setup, and best practices for developers.

utm-parametersanalyticsga4marketingtrackinggtm

If you’ve ever asked “which marketing channel is actually driving signups?”, UTM parameters are your answer. They’re a simple but powerful mechanism for passing campaign data through URLs into your analytics platform—and as a developer, understanding them will make you a better collaborator with your marketing team and a better builder of data-driven products.

This guide covers everything you need to know: what UTM parameters are, how all five work, naming conventions that scale, GA4 integration, and implementation patterns for common frameworks.


What Are UTM Parameters?

UTM stands for Urchin Tracking Module—named after Urchin Software, which Google acquired in 2005 and turned into Google Analytics.

UTM parameters are query string key-value pairs appended to URLs. When a user clicks a UTM-tagged link, the values are captured by your analytics tool, allowing you to attribute that visit to a specific campaign, source, and medium.

Example of a UTM-tagged URL:

https://devplaybook.cc/tools/utm-campaign-builder?utm_source=newsletter&utm_medium=email&utm_campaign=march-launch&utm_content=cta-button&utm_term=developer+tools

Without UTM parameters, all email clicks might show up as “direct” traffic in GA4. With them, you get granular attribution.


The 5 UTM Parameters Explained

1. utm_source (Required)

What it is: Identifies where the traffic is coming from—the referrer.

Format: Single word or short identifier, lowercase.

utm_source=google
utm_source=newsletter
utm_source=twitter
utm_source=devto

Real examples:

  • utm_source=google — paid search on Google
  • utm_source=linkedin — LinkedIn post or ad
  • utm_source=partner_devhunt — a specific partner site
  • utm_source=internal — internal email campaigns

2. utm_medium (Required)

What it is: The marketing channel or medium. Think of it as the type of traffic.

Standard medium values (follow these):

  • cpc — cost-per-click paid ads
  • email — email campaigns
  • social — organic social posts
  • referral — links from other websites
  • organic — organic search (usually set by the search engine itself)
  • banner — display banner ads
  • affiliate — affiliate links
utm_medium=email
utm_medium=cpc
utm_medium=social
utm_medium=referral

Why standardize? GA4 uses utm_medium to populate the “Default Channel Group” report. Using non-standard values like utm_medium=newsletter instead of utm_medium=email will break channel grouping.


3. utm_campaign (Required)

What it is: The specific campaign name. This ties multiple sources together under one initiative.

utm_campaign=spring-sale-2025
utm_campaign=developer-onboarding
utm_campaign=product-launch-v2
utm_campaign=retargeting-q1

Best practices:

  • Use lowercase with hyphens: utm_campaign=black-friday-2025 not Black Friday 2025
  • Include the year/quarter for time-bound campaigns
  • Be specific enough to distinguish campaigns, but not so granular that reports become unreadable

4. utm_content (Optional)

What it is: Differentiates links that point to the same URL within the same campaign. Used for A/B testing ad copy, or distinguishing multiple CTAs in one email.

utm_content=cta-top
utm_content=cta-bottom
utm_content=hero-banner
utm_content=sidebar-link

Example: You have two buttons in an email that both point to /pricing. You want to know which gets more clicks:

  • Button 1: utm_content=header-cta
  • Button 2: utm_content=footer-cta

5. utm_term (Optional)

What it is: Originally for paid search—captures the keyword that triggered the ad. Now also used to pass custom information in non-search contexts.

utm_term=javascript+tutorial
utm_term=best+devtools

Modern usage: For non-search campaigns, some teams repurpose utm_term to track newsletter segment, influencer handle, or audience targeting bucket.


Naming Convention Best Practices

Poor naming kills UTM reporting. These conventions will save you pain:

Use lowercase, always

GA4 is case-sensitive. utm_source=Twitter and utm_source=twitter create two separate source entries.

# Bad
utm_source=Twitter&utm_medium=Social&utm_campaign=MarchLaunch

# Good
utm_source=twitter&utm_medium=social&utm_campaign=march-launch

Use hyphens, not spaces or underscores

# Bad (spaces become %20, ugly in reports)
utm_campaign=spring sale

# Acceptable (underscores work but inconsistent)
utm_campaign=spring_sale

# Best (hyphens are standard)
utm_campaign=spring-sale

Define a taxonomy and document it

Create a shared spreadsheet or wiki page with approved values for each parameter. Teams that skip this end up with utm_source=Email, utm_source=email, and utm_source=EMAIL all appearing as separate sources.

Suggested taxonomy:

ParameterApproved Values
utm_sourcegoogle, facebook, twitter, linkedin, newsletter, devto, github
utm_mediumcpc, email, social, referral, banner, affiliate, organic
utm_campaign[product]-[type]-[year], e.g., devplaybook-launch-2025

Include a UTM builder in your workflow

Use a UTM campaign builder to enforce consistency. Many teams integrate this into their CMS or marketing automation platforms so UTMs are generated programmatically.


How UTM Parameters Work with GA4

Viewing UTM data in GA4

  1. Navigate to Reports → Acquisition → Traffic acquisition
  2. Set the primary dimension to Session source/medium or Session campaign
  3. You’ll see your UTM-tagged campaigns broken out

For deeper analysis:

  • Explorations → Free form → drag in Session source, Session medium, Session campaign
  • Use secondary dimensions to correlate UTM data with conversions

GA4 Default Channel Grouping

GA4 automatically assigns traffic to channel groups based on utm_source and utm_medium values. The rules:

ChannelCondition
Organic Searchutm_medium = organic
Paid Searchutm_medium = cpc or ppc
Emailutm_medium = email
Socialutm_medium in social platforms list
ReferralOther sessions with referrer

Using non-standard medium values (like utm_medium=newsletter) puts traffic into “Unassigned” or a custom group—which breaks default reporting.


How UTM Parameters Work with GTM

Google Tag Manager captures UTM parameters as built-in variables:

  1. In GTM, go to Variables → Built-In Variables → Configure
  2. Enable: Traffic Source, Medium, Campaign

These variables are populated from document.referrer and location.search on the page.

Custom GTM variable for manual UTM reading:

// Custom JavaScript variable in GTM
function() {
  var params = new URLSearchParams(window.location.search);
  return {
    source: params.get('utm_source') || '(none)',
    medium: params.get('utm_medium') || '(none)',
    campaign: params.get('utm_campaign') || '(none)',
    content: params.get('utm_content') || '(none)',
    term: params.get('utm_term') || '(none)'
  };
}

Developer Implementation Guide

Reading UTM Parameters in JavaScript

function getUTMParams() {
  const params = new URLSearchParams(window.location.search);
  return {
    utm_source: params.get('utm_source'),
    utm_medium: params.get('utm_medium'),
    utm_campaign: params.get('utm_campaign'),
    utm_content: params.get('utm_content'),
    utm_term: params.get('utm_term'),
  };
}

// Usage
const utm = getUTMParams();
console.log(utm.utm_source); // "newsletter"

Persisting UTM Parameters Across Pages

UTMs are only on the landing page URL. If you need them throughout the session (e.g., for form submissions), persist them to sessionStorage:

// On page load — capture and store UTMs
function captureUTMs() {
  const params = new URLSearchParams(window.location.search);
  const utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];

  utmKeys.forEach(key => {
    const value = params.get(key);
    if (value) {
      sessionStorage.setItem(key, value);
    }
  });
}

// When submitting a form — read stored UTMs
function getStoredUTMs() {
  const utmKeys = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term'];
  return utmKeys.reduce((acc, key) => {
    const value = sessionStorage.getItem(key);
    if (value) acc[key] = value;
    return acc;
  }, {});
}

// Call on every page load
captureUTMs();

Passing UTMs to Your Backend

When users sign up, pass UTM data to your server so you can attribute conversions in your own database—not just in GA4.

// React form submission example
async function handleSignup(formData) {
  const utms = getStoredUTMs();

  await fetch('/api/users', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      ...formData,
      acquisition: {
        utm_source: utms.utm_source || 'direct',
        utm_medium: utms.utm_medium || 'none',
        utm_campaign: utms.utm_campaign || null,
        referrer: document.referrer || null,
      }
    })
  });
}

Next.js: Accessing UTM Params

// app/page.tsx — Server Component
import { headers } from 'next/headers';

export default function LandingPage({ searchParams }: {
  searchParams: { [key: string]: string | undefined }
}) {
  const utmSource = searchParams['utm_source'];
  const utmMedium = searchParams['utm_medium'];
  const utmCampaign = searchParams['utm_campaign'];

  // Pass to analytics or use for personalization
  return <div>...</div>;
}
// Client Component with useSearchParams
'use client';
import { useSearchParams } from 'next/navigation';

export function UTMCapture() {
  const searchParams = useSearchParams();
  const utmSource = searchParams.get('utm_source');

  // Store to sessionStorage on mount
  useEffect(() => {
    if (utmSource) {
      sessionStorage.setItem('utm_source', utmSource);
    }
  }, [utmSource]);

  return null; // invisible tracking component
}

Common Mistakes to Avoid

Never tag internal links (links that go from one page on your site to another) with UTM parameters. Doing so overwrites the original session source, making it look like the user came from utm_source=internal instead of Google or wherever they actually came from.

<!-- Bad: internal link with UTM -->
<a href="/pricing?utm_source=homepage&utm_medium=cta">See Pricing</a>

<!-- Good: internal link without UTM -->
<a href="/pricing">See Pricing</a>

2. Ignoring URL encoding

Spaces and special characters must be URL-encoded. Most UTM builders handle this automatically, but if you’re constructing URLs manually:

const campaign = "spring launch 2025 - dev tools";
const encoded = encodeURIComponent(campaign);
// "spring%20launch%202025%20-%20dev%20tools"

// Or use URLSearchParams which handles encoding automatically:
const params = new URLSearchParams({
  utm_source: 'newsletter',
  utm_campaign: 'spring launch 2025'
});
// "utm_source=newsletter&utm_campaign=spring+launch+2025"

Single-use profile links (like your Twitter bio) don’t need UTMs per click—they should use a UTM once. But utm_content helps if you A/B test different bios.

4. No UTM governance

Without a defined taxonomy and process, teams create duplicate campaigns, typos, and inconsistent casing. The result is fragmented data that’s hard to analyze.


UTM Parameter Quick Reference

ParameterRequiredPurposeExample
utm_sourceYesWhere traffic comes fromgoogle, newsletter
utm_mediumYesThe marketing channelcpc, email, social
utm_campaignYesCampaign identifierspring-sale-2025
utm_contentNoDifferentiate links in same campaigncta-header, cta-footer
utm_termNoKeyword (paid search) or segmentjavascript+tools

Tools for UTM Management

  • UTM Campaign Builder — Build properly-formatted UTM URLs with consistent naming
  • Google Analytics 4 — Primary destination for UTM attribution data
  • Google Tag Manager — Advanced UTM capture and event tracking
  • Bitly / Short.io — Shorten UTM-tagged URLs for social sharing
  • Looker Studio — Build custom UTM attribution dashboards

Summary

UTM parameters are a foundational analytics tool that every developer should understand:

  • 5 parameters: source (required), medium (required), campaign (required), content (optional), term (optional)
  • Naming matters: always lowercase, hyphens over spaces, consistent taxonomy across your team
  • GA4 integration: medium values should match GA4’s default channel grouping rules
  • Persist across pages: use sessionStorage to carry UTMs from landing page to conversion
  • Never UTM internal links: it corrupts session attribution

The 10 minutes you spend setting up proper UTM conventions will pay dividends in accurate attribution for months. Start with a UTM builder and document your taxonomy—your future self (and your marketing team) will thank you.

Free Download

50 CLI Commands That Save Hours Every Week

The exact Git shortcuts, file search tricks, Docker commands, and productivity hacks that senior developers use daily. Compiled from 5+ years of shipping production code.

  • Git mastery (10 cmds)
  • File & search wizardry
  • Docker & DevOps tricks
  • Process & network tools
  • Productivity boosters
  • macOS & Linux install guide

No spam. 1 email/week max. Unsubscribe anytime.

Found this guide useful? Check out our free developer tools.