Skip to content

BlogHow To Guides

PostHog Attribution: How It Works and Where It Stops

PostHog can tell you where a user first came from and put ad spend next to your conversions. Here is exactly how its attribution works, what quietly breaks it, and the point where teams add something next to it.

PostHog attribution explained: how it works and where it stops
Contents
  1. In short
  2. First and last touch
  3. Marketing analytics
  4. What breaks it
  5. CRM revenue
  6. Back to the platforms
  7. What it does well
  8. Is it enough
  9. What teams add
  10. Further reading
Summarise this article with AI

Opens the page with a ready prompt in:

Nothing is sent until you pick a service.

PostHog was built for product teams, and it shows in the best way: autocapture, funnels, retention, session replay, feature flags and experiments on one platform, with a free tier most companies never leave. Attribution arrived later and from the same direction. It answers where a user came from as a property on that user, and since the marketing analytics beta it can put ad spend from eight platforms next to your conversion goals.

That covers a lot of what a SaaS team needs on day one. It gets harder when the conversion that matters is not an event in the product but a deal sales closes six weeks later, when the question is which of five touches deserves the credit, or when Google Ads should learn from the customers who paid rather than the ones who signed up.

This guide explains how PostHog attribution works, piece by piece, what PostHog's own documentation says breaks it, how teams get CRM revenue into it, and when it is enough.

In Short: How Attribution Works in PostHog

In short

PostHog attribution is first touch and last touch, stored as properties on the person: $initial_utm_source and $initial_gclid for the first visit, utm_source and gclid for the latest one. You read them by breaking a conversion event down by those properties. The marketing analytics beta adds ad spend from eight platforms and matches it to conversion goals on utm_campaign and utm_source. CRM deals reach PostHog as warehouse tables you join with SQL, and conversions go back to Meta and LinkedIn through destinations, with Google Ads marked experimental. It is a strong fit when the conversion is a product event, and it runs out when the conversion is a CRM deal.

Everything below comes from PostHog's own documentation, read in September 2026. PostHog ships quickly and the marketing analytics product is still a beta, so check the docs for anything that has moved since.

First Touch and Last Touch: The Two Properties Behind It

PostHog captures campaign parameters on every event: the UTM set, the click IDs and the referrer. What turns them into attribution is where they end up on the person, and there are two kinds of property with different rules.

The two campaign properties on a PostHog person

First-touch attribution in PostHog is therefore a breakdown: pick your signup or purchase event, break it down by Initial UTM Source or Initial Referring Domain, and read the bars. Last touch is the same breakdown on the latest properties. PostHog's own tutorial on first and last touch attribution works exactly this way.

What is not there

There is no built-in linear, position based or time decay model. Those need every touch in order, per person, and a rule for splitting the credit. In PostHog that is a query over the events table that you write yourself.

Marketing Analytics: Ad Spend Next to Conversions

Marketing analytics is the newest piece and the closest PostHog comes to an attribution product. It is an opt-in beta you switch on under feature previews.

  • Spend from eight platforms: Google Ads, LinkedIn Ads, Meta Ads, Pinterest Ads, TikTok Ads, Reddit Ads, Bing Ads and Snapchat Ads, with clicks, impressions and cost, converted to your base currency.
  • Matching on UTMs: campaigns are tied to traffic through utm_campaign and utm_source, by campaign name or ID, with manual mappings for the ones that do not line up.
  • Conversion goals are PostHog events, actions or data warehouse tables. A warehouse table needs a UTM campaign column, a UTM source column and a timestamp.

That puts cost per conversion per campaign on one screen, which is genuinely useful. Two things follow from the design. The match is only as good as your UTM discipline, because a campaign that arrives with a different utm_campaign than the ad platform's name is a campaign with spend and no conversions. And the conversion is whatever you define as a goal, so a signup is easy while a closed deal is only as good as the warehouse table you build for it.

What Quietly Breaks PostHog Attribution

PostHog documents these itself on its campaign attribution troubleshooting page. None of them is a bug; they follow from attribution living on a browser-side identity that has to be joined to a person.

  • Anonymous visitors never reach a person. With the default person_profiles: 'identified_only', events from anonymous users do not update person profiles, so the campaign on those events never lands anywhere until the user is identified.
  • identify() placed late. If the user is identified after the signup form rather than on it, the conversion happens before the person exists and the latest campaign is lost.
  • Safari and in-app browsers. Safari clears cookies and localStorage aggressively, and the LinkedIn, Instagram and Facebook in-app browsers keep isolated storage, so the first-touch cookie is often gone by the second visit.
  • A second device. Cross-device journeys are only joined when you call identify() on both, which a marketing visitor rarely gives you before they convert.
  • Ad blockers. PostHog says a reverse proxy typically increases event capture by 10 to 30 percent, which is also a measure of what an unproxied setup is missing. The managed proxy is free on PostHog Cloud and worth switching on either way.

The practical effect is that PostHog's first-touch numbers are most reliable for users who converted in one sitting on one device, and least reliable for exactly the long, multi-visit journeys a B2B or high-ticket buyer takes.

Getting CRM Revenue Into PostHog

PostHog's data warehouse syncs managed sources, including HubSpot, Salesforce, Pipedrive, Attio, Close, Stripe and Shopify, every few minutes, and lets you query them with SQL next to your events. That is how a closed deal gets into PostHog: as rows in a table, joined to people by something both sides share.

HogQL sketch, table and column names depend on your source schema
SELECT
  p.properties.$initial_utm_source   AS first_touch_source,
  p.properties.$initial_utm_campaign AS first_touch_campaign,
  count()                            AS deals_won,
  sum(d.amount)                      AS revenue
FROM hubspot_deals AS d
JOIN hubspot_contacts AS c ON c.id = d.contact_id
JOIN persons AS p ON p.properties.email = c.email
WHERE d.dealstage = 'closedwon'
GROUP BY first_touch_source, first_touch_campaign
ORDER BY revenue DESC

It runs, and it gives you first-touch revenue by campaign. It also quietly assumes five things worth knowing before a number from it reaches a board slide:

  1. One contact per deal. In HubSpot a deal and its contacts are linked through associations, not a column on the deal, so the first join above is already a simplification you have to replace.
  2. The email matches. The person in PostHog was identified with the same email the CRM holds, which breaks on a work address against a personal one.
  3. The person was identified at all. Every deal from a lead who never logged in or filled a tracked form drops out of the join, silently.
  4. First touch is the model. Any other split needs the ordered touch history, not the person property.
  5. Spend is somewhere else. The query has revenue but no cost, so return on spend is another join, against the marketing analytics tables.

None of this is hard for a data team. It is a small project with a maintenance tail, and it is the part that tends to become one person's spreadsheet.

Sending Conversions Back to the Ad Platforms

Attribution tells you where to move the budget. Sending the conversion back tells the ad platform's bidding who to find more of. PostHog does this with realtime destinations.

  • Meta Ads Conversions sends hashed email, name and the Meta click and browser identifiers with the events you filter for.
  • LinkedIn Ads Conversions sends the conversion with an optional value and currency.
  • Google Ads uploads offline conversions matched on gclid, and PostHog labels it an experimental destination it does not officially support. Google itself needs 6 to 48 hours to process them.

The detail that matters for a sales-led business

PostHog's docs say ad destinations filter the realtime event stream and use person data as it exists at the moment the event is processed, not data added later. A closed deal in your CRM is not an event in that stream, so before it can reach Google as an offline conversion somebody has to turn the stage change into a PostHog event, with the click ID still attached.

What PostHog Attribution Is Good At

  • Attribution next to behaviour. The same person carries their first campaign, every product event, their session replays and the flags they saw, so you can ask which channel brings users who activate, not only users who sign up.
  • Product-led conversions. When the conversion is a signup, a trial start or an in-app upgrade, first and last touch on a PostHog event is exactly the right place to measure it.
  • Spend in the same tool. The marketing analytics beta removes the spreadsheet for cost per signup per campaign across eight ad platforms.
  • Price. A million events a month are free, and there are no seat charges, so the whole team can look.
  • Everything queryable. When the built-in view is not enough, the SQL editor and the warehouse mean you are never locked out of your own data.

When PostHog Attribution Is Enough, and When It Is Not

PostHog attribution against the question you are asking

The pattern is the one you would expect from a product platform. Wherever the conversion lives in the product, PostHog is excellent. Wherever it lives in the CRM or on the phone, PostHog can hold the data but the attribution becomes something your team builds.

What Teams Add Next to It

Teams in that second situation rarely replace PostHog, and they should not: the product team keeps its analytics, replays and experiments. What they add is an attribution layer owned by marketing, which tracks the website server-side, keeps every touch rather than the first and the last, reads deal stages and values from the CRM natively, and sends the closed deal back to the ad platforms without anyone writing an event for it.

That is what LeadJourney does, and the comparison page sets it against PostHog row by row, including the rows where PostHog is ahead.

Further Reading

FAQ

Frequently Asked Questions

The questions PostHog users ask about attribution.

Does PostHog have multi-touch attribution?

Not as a built-in model. PostHog stores the first and the latest campaign as properties on each person, so first-touch and last-touch attribution are a breakdown away. A linear, position based or time decay model needs every touch in order and a rule for splitting the credit, which in PostHog means writing a query over the events table.

How do I see first-touch attribution in PostHog?

Create an insight on your conversion event, such as a signup, and break it down by the person property Initial UTM Source or Initial Referring Domain. The initial properties are stored in a cookie on the first visit and backfilled onto the person when you call identify(), so identify users as early as you can.

Why do PostHog's UTM numbers not match Google Ads or Meta?

Mostly for three reasons. The platforms count conversions in their own attribution windows and claim view-throughs; PostHog only sees users whose browser kept its cookie and who were identified; and the latest campaign properties hold only within the same tab and domain. Missing identify() calls, Safari clearing storage and in-app browsers widen the gap further. A reverse proxy, which PostHog says typically recovers 10 to 30 percent of events, closes part of it.

Can PostHog attribute revenue from HubSpot or Salesforce?

Yes, with some work. Both sync into the PostHog data warehouse as tables you can query with SQL. You then join deals to contacts, contacts to PostHog persons by email, and read the campaign property you trust. Deals with several contacts, leads who were never identified and anything beyond first touch make that join a small project to build and maintain.

Should we replace PostHog to get marketing attribution?

Usually not. PostHog is excellent at the product: analytics, replays, flags and experiments. Teams that need CRM revenue per campaign, every touch rather than two, or closed deals sent back to the ad platforms tend to add a dedicated attribution tool owned by marketing and keep PostHog for the product team.

PostHog attribution

Attribute the deal, not only the signup

Server-side tracking at 95%+ accuracy, every touch kept for months, CRM revenue per campaign and the closed deal sent back to four ad platforms, next to PostHog.

LeadJourney dashboard showing lead sources, campaign performance and attributed revenue side by side