Attribution · Sprites diagnoses this

PostHog UTM tracking

PostHog captures utm_source, utm_medium, utm_campaign and the common click IDs from the URL automatically and stores them on the event, the session and the person. The person keeps the first touch as $initial_utm_source, so a signup can be traced to the ad that first brought the visitor in. If those properties are empty, the UTMs never reached the page PostHog loaded on.

$1 today. Cancel anytime before day 7.

What Sprites checks

  • ?Signups with $initial_utm_source62%
  • ✓Pageviews with gclid or fbclidPresent
  • ✓Signups from paid by sourceLinkedIn 41, Google 88
  • !Signups on another domainapp subdomain loses UTMs
Illustration of a typical broken account. Your own readout comes from your account.

Why it happens

The signup happens on another domain or subdomain

  1. The signup happens on another domain or subdomain

    Marketing site and app on different domains, with PostHog cookies not shared, start a new anonymous person with no UTMs at signup.

  2. Identify is never called, or called too late

    Without posthog.identify at signup, the anonymous visitor who carried the UTMs never joins the person who converted.

  3. A redirect or router dropped the UTMs

    PostHog reads the URL it loads on. If a redirect cleaned it first, there is nothing to capture.

  4. Ad blockers and consent

    Visitors who block PostHog or decline cookies never send the pageview that carried the UTMs, unless you proxy PostHog through your own domain.

How to line them up, step by step

  1. Check one tagged visit

    Load your site with a test UTM, then open Activity in PostHog and check the $pageview carries utm_source and the person shows $initial_utm_source.

  2. Break down signups by first source

    Create a Trends insight on your signup event and break it down by the person property $initial_utm_source.

  3. Share the cookie across subdomains

    Initialize PostHog with cross-subdomain cookies on, so the marketing site and the app share one anonymous ID.

  4. Call identify at signup

    Call posthog.identify with your user ID the moment the account is created, on the same browser session that carried the UTMs.

  5. Proxy PostHog

    Set up a reverse proxy on your own domain so ad blockers do not drop the first pageview.

Steps checked against PostHog Docs: UTM segmentation; PostHog Docs: Identifying users; PostHog Docs: Deploying a reverse proxy.

Sprites diagnoses this

Sprites diagnoses it

Sprites breaks PostHog signups down by utm_source and shows which paid clicks arrive with no UTMs.

What Sprites does

  • Reads what your PostHog project actually captures: events, their 30-day volume and property keys.
  • Breaks signups and activations down by any UTM or click ID property on the event, session or person.
  • Builds funnels from first visit to activation by source, so you see which ad sources bring users who stick.
  • Puts those numbers next to the ad platform conversions for the same days.

What it doesn't do

  • It does not change your PostHog setup, identify calls or cookies.
  • It does not send PostHog events back to ad platforms as conversions.

Questions

Does PostHog track UTM parameters automatically?

Yes. posthog-js captures utm_source, utm_medium, utm_campaign, utm_content and utm_term from the URL on every pageview with no extra setup.

Does PostHog capture gclid and fbclid?

Yes. It captures the common ad click IDs, including gclid, fbclid, msclkid and li_fat_id, as properties alongside the UTMs.

What is $initial_utm_source?

A person property holding the utm_source from the first time PostHog saw that person. Use it for first-touch attribution of signups.

Why do my PostHog signups have no UTM source?

Usually because signup happened on another domain without shared cookies, or identify was never called, so the person who signed up is not the visitor who carried the UTMs.

See where it breaks

Connect your accounts. Sprites reads them side by side and shows you exactly where the numbers split.