Skip to main content
When a visitor lands on your site, you can’t ask them how they got there. UTMs answer that for you — small URL parameters that tell your analytics tool the exact source of every visit. Done right, you can measure which LinkedIn post drove revenue, which email variant converted, which affiliate actually worked.

The 5 UTM Parameters

  • utm_sourcewhere the click came from (google, linkedin, newsletter, affiliate_name)
  • utm_mediumhow the click happened (cpc, email, social, referral)
  • utm_campaignwhich campaign it belongs to (spring_sale, launch_2026, retarget_abandoners)
  • utm_contentwhich variant of the ad/link (sidebar, cta_button, hero_v2)
  • utm_termwhich keyword (for paid search only)

Example Tagged URL

https://yoursite.com/signup?utm_source=linkedin&utm_medium=social&utm_campaign=april_launch&utm_content=post_1
This one URL tells you: someone clicked a LinkedIn social post, specifically the first variant, as part of the April launch campaign.

Three Paths

Ask the AI:
Generate UTM-tagged URLs for my LinkedIn, Twitter, and 
email campaigns for our April product launch. Target URL 
is yoursite.com/signup.
The AI generates the URL variants and exports them as a CSV or ready-to-paste list for your marketing tools.

Capture UTMs on Your Site

Reading UTMs is easy. Persisting them across pages and attaching them to conversions is where most sites go wrong.
1

Read from the URL on first load

const params = new URLSearchParams(window.location.search);
const utms = {
  source: params.get('utm_source'),
  medium: params.get('utm_medium'),
  campaign: params.get('utm_campaign'),
  content: params.get('utm_content'),
  term: params.get('utm_term'),
};
2

Save to localStorage or a cookie

if (utms.source) {
  localStorage.setItem('utms', JSON.stringify(utms));
  localStorage.setItem('utms_first_touch', JSON.stringify(utms));
}
Use utms_first_touch only if it’s not already set, so first-touch attribution doesn’t overwrite on later visits.
3

Attach to signup/form submit

When a user submits a signup form, include the stored UTMs in the payload so they end up on the user record.
4

Persist across pages

Storing in localStorage or cookies automatically survives page navigation. If you set them via a third-party script, make sure scripts run on every page that might capture a signup.

Database Schema

Add UTM columns to your users or signups table:
ALTER TABLE users ADD COLUMN utm_source text;
ALTER TABLE users ADD COLUMN utm_medium text;
ALTER TABLE users ADD COLUMN utm_campaign text;
ALTER TABLE users ADD COLUMN utm_content text;
ALTER TABLE users ADD COLUMN utm_term text;
ALTER TABLE users ADD COLUMN first_touch_campaign text;
Store both the most recent touch (at signup) and the first touch (earliest captured).

Analytics Integration

  • Google Analytics picks up UTMs automatically. You’ll see Campaign, Source, Medium in the Acquisition reports out of the box. See Add Google Analytics.
  • Hiveku visitor analytics captures referrer by default; adding UTM capture lets you attribute beyond raw referrer.
  • Event-based tools like Segment, Mixpanel, or PostHog: forward the UTMs as properties on every event for proper funnel breakdowns.

Attribution Models

There’s no single “right” answer — each model tells a different story:
ModelCredit goes toBest for
First-touchThe first UTM a user sawTop-of-funnel / awareness campaigns
Last-touchThe last UTM before conversionBottom-of-funnel / closing campaigns
Multi-touchSplit across all touchesLonger sales cycles, multiple channels
Most teams use both first-touch and last-touch side-by-side — awareness and conversion credit serve different marketing decisions.

Build an Attribution Dashboard

Query your users table:
SELECT 
  utm_source, utm_medium, utm_campaign,
  COUNT(*) as signups,
  COUNT(CASE WHEN converted = true THEN 1 END) as paid,
  SUM(CASE WHEN converted THEN ltv_cents ELSE 0 END) / 100.0 as revenue
FROM users
WHERE created_at >= now() - interval '30 days'
GROUP BY utm_source, utm_medium, utm_campaign
ORDER BY revenue DESC;
Plug this into your admin dashboard so the marketing team can see per-campaign performance without asking you.

Naming Conventions

Consistency matters more than cleverness:
  • Lowercase only. LinkedIn and linkedin are different values in analytics.
  • No spaces. Use - or _ (pick one and stick with it): email-newsletter or email_newsletter.
  • Abbreviate predictably. cpc not click_per_cost; oct_launch not october_product_launch.
  • Standardize values. Don’t use social, Social, and social-media for the same medium.
Create a shared UTM naming spreadsheet for your team. Inconsistent capitalization or typos fragment your data and make reporting useless. A 30-minute alignment meeting upfront saves weeks of cleanup later.

Verify It Worked

1

Tag a test URL

https://yoursite.com?utm_source=test&utm_medium=qa&utm_campaign=verify
2

Visit it in an incognito window

Incognito avoids picking up your existing session’s UTMs.
3

Open browser devtools

Check localStorage: you should see utms and utms_first_touch keys.
4

Submit a signup form

Complete a test signup. Then query your DB: the new user row should have utm_source = 'test', utm_campaign = 'verify', etc.

Troubleshooting

Most common cause: JavaScript error on the page blocking the capture script. Open devtools console and look for red errors. Also check cookies aren’t disabled (try in normal browsing mode, not incognito with strict settings).
Standardize going forward and clean up historical data with a SQL UPDATE:
UPDATE users 
SET utm_source = LOWER(REPLACE(utm_source, ' ', '-'))
WHERE utm_source IS NOT NULL;
Add a constraint or transformation at write time so it can’t happen again.
If visitors bounce between yoursite.com and app.yoursite.com, cookies may not transfer. In GA4, enable cross-domain tracking in Admin > Data Streams. For your own capture logic, use a cookie scoped to the top-level domain (.yoursite.com).
Google auto-tags paid search as google / cpc via Google Ads’ auto-tagging feature (gclid parameter). Don’t manually add UTMs on top of this — you’ll double-count. Respect the auto-tagging and only use manual UTMs where the source doesn’t provide its own attribution.
Attribution captures revenue at signup; refunds and chargebacks happen later. Build your attribution report off net revenue (post-refund) for accuracy. Update the stored ltv_cents monthly from Stripe data.

What’s Next?

Analytics

Track every important action on your site

Google Analytics

Connect GA4 for deeper attribution reports