HubSpot attribution: the complete guide for B2B
HubSpot attribution connects contacts, deals and closed revenue to the marketing touches that came before them: page views, ad clicks, form submissions and email clicks. It is only as accurate as the data that reaches HubSpot. When the reports look wrong, the model is rarely the cause. Source data is lost earlier, in capture, cookie persistence, CRM records or the feedback loop to ad platforms.
By Vladimir Cvetkoski · Last updated
How HubSpot attribution actually works
Most attribution arguments start at the report. That is the wrong end. A HubSpot attribution report is the last step of a chain: a browser loads a script, the script sets a cookie, the cookie gets tied to a contact, the contact gets tied to a deal. Every link in that chain can fail on its own. If you know how each link works, you can find the one that broke.
The tracking code and its cookies
Every page with the HubSpot tracking code sets a few first-party cookies. Two of them carry the attribution story:
hubspotutkholds an anonymous visitor ID. HubSpot passes it with form submissions and uses it to connect the visitor to a contact record. It lasts six months.__hstcis the main tracking cookie. It stores the domain, the visitor ID, the timestamp of the first visit, the last visit, the current visit, and the session number. It also lasts six months.__hssctracks the current session and expires after 30 minutes. It decides when a new session starts.
Before someone fills in a form, HubSpot only knows them as an anonymous visitor with a cookie. Every page view is logged against that cookie, with the referrer and any URL parameters on the first page of each session.
From anonymous visitor to contact
When the visitor submits a HubSpot form, or a non-HubSpot form that HubSpot collects, the submission carries the hubspotutk value. HubSpot matches it to the cookie history and attaches that history to the contact. A visitor who found you through Google in March and filled in a form in September becomes a contact whose first known source is Organic Search, not whatever brought them back in September.
This is the most important mechanic in the whole system. If the cookie never reaches the form submission, the history is never attached. The contact still gets created, but without the past. That is where most Direct and Offline Sources records come from.
Original Traffic Source and its drill-downs
HubSpot now labels the properties Original Traffic Source and Latest Traffic Source. Many teams still call them Original Source and Latest Source. Original Traffic Source is the first known web source through which the contact interacted with your business.
Two drill-down properties add detail. For paid search, drill-down 1 holds the campaign name from utm_campaign and drill-down 2 holds the search term when one is available. For Direct Traffic, drill-down 1 holds the entrance URL. For Offline Sources, the drill-downs tell you how the record was created: in the HubSpot interface, by import, through the API or by a connected app. You cannot edit the drill-downs by hand. You can edit the source itself, on one record, in bulk or by workflow, but doing so clears the drill-downs and the First Referring Site value.
Latest Traffic Source
Latest Traffic Source updates when HubSpot creates a new session for the contact: a website visit, a marketing form view or submission, or a scheduling page submission. An import does not create a session, so it does not change Latest Traffic Source. In practice, Original answers "how did they find us" and Latest answers "what brought them back most recently".
How HubSpot classifies a source
HubSpot checks each session against an ordered list of rules, and the first rule that matches wins. This is what puts a visit in each category:
| Source | What puts a visit there |
|---|---|
| Paid Search | A valid gclid, or a source, medium or campaign parameter containing "cpc", "ppc" or "adword" |
| Paid Social | utm_medium containing "paid", "ppc" or "cpc" with a known social network as source or referrer, or "paidsocial" in source or medium |
| Email Marketing | "email" in a source, medium or campaign parameter |
| AI Referrals | A referrer or UTM matching a recognised AI platform, such as ChatGPT or Perplexity |
| Other Campaigns | Tracking parameters present, but none of the keywords above |
| Organic Social | A social network referrer, or utm_medium=social with a known network |
| Organic Search | A search engine referrer with no tracking parameters |
| Referrals | Any other referring domain |
| Direct Traffic | No referring domain and no tracking parameters |
| Offline Sources | Records HubSpot cannot tie to a tracked web session: imports, integrations, API, manual creation |
Two things follow from this table. First, your UTM naming decides your channel reports. A LinkedIn ad tagged utm_medium=linkedin lands in Other Campaigns, not Paid Social. Second, Direct Traffic is not "people who typed your URL". It is "no evidence found". Lost evidence looks exactly like direct traffic.
If you connect ad accounts in HubSpot and switch on auto-tracking, HubSpot appends its own hsa_ parameters to your ad URLs so it can tie contacts to specific campaigns and ads. It only attributes clicks that happened after auto-tracking was switched on.
Contact, deal and revenue attribution
Source properties live on the contact. Attribution reports go further and look at every interaction on the path. HubSpot offers three report types:
- Contact create attribution: which interactions led to new contacts. Available on Marketing Hub Professional and Enterprise, and Content Hub Professional and Enterprise.
- Deal create attribution: which interactions led to new deals. Marketing Hub Enterprise only.
- Revenue attribution: which interactions led to closed-won revenue. Marketing Hub Enterprise only.
A deal has no web session of its own. Deal and revenue reports find touchpoints through the contacts associated with the deal. For revenue attribution, a deal has to be in a closed-won stage, have at least one associated contact, and have values in Amount, Create date and Close date. A deal with no contact on it is invisible to these reports, however much it is worth.
Interaction types
The reports count these interaction types: ad clicks, CTA clicks, form submissions, marketing email clicks, page views, social post clicks, marketing event registrations and attendance, and connected calls. Notice what is missing: sales emails, LinkedIn conversations, a partner introduction, the conference coffee. Anything that happens outside tracked HubSpot assets is not on the path unless you put it there.
Attribution models
A model decides how credit is split across the interactions on a path. HubSpot offers five:
| Model | How credit is split |
|---|---|
| First Touch | All credit to the first interaction |
| Last Touch | All credit to the last interaction before the conversion |
| Linear | Equal credit to every interaction |
| Time Decay | More credit to interactions closer to the conversion |
| Empirical | Credit weighted by how often each interaction type occurs across conversion paths in your portal. Rarer interaction types get more weight; interactions of the same type get equal weight. |
Empirical replaced the U-shaped, W-shaped, J-shaped and inverse J-shaped models in 2026. If you read older guides or have old screenshots of those reports, that is why the names no longer match. Empirical depends on your own portal's history, so it is only as good as the interactions HubSpot has recorded.
Which model is right matters far less than teams think. Every model reads the same interactions. If half your paid clicks arrive as Direct Traffic, every model will under-credit paid. Changing the model moves the error around. It does not remove it.
Where HubSpot attribution breaks, layer by layer
I split the chain into four layers. Each one fails in its own way and needs its own fix. Look at them in order, because a break in an early layer shows up as noise in every later one.
Layer 1: capture
Capture is the moment the tracking code reads the referrer and URL parameters on the landing page. If the data is gone before the script runs, it is gone for good. The usual causes:
- Redirects and link shorteners that drop the query string, so
utm_sourceandgclidnever reach the page. - Templates where the tracking code is missing, or loads after a redirect has already happened.
- Forms embedded in an iframe or loaded from another domain. The submission is tied to the iframe, not the landing page, and the UTMs stay behind. This is the classic reason for UTMs missing from HubSpot form submissions.
- Ad blockers and privacy browsers that stop the HubSpot script from loading at all.
- Consent banners that hold the cookies back. HubSpot only records page views after the visitor accepts, so if they accept on page three, the parameters from page one are usually lost. A visitor who never accepts and then submits a form is recorded as Direct Traffic.
Capture failures pile up in one place. If your reports are dominated by one bucket, read why HubSpot shows so much Direct traffic. It walks through each cause and how to test it.
Layer 2: persistence
Persistence is whether the visitor ID survives long enough to connect the first visit to the form fill. B2B buyers take weeks or months between those two moments. Things that break it:
- Safari's tracking prevention deletes cookies set by JavaScript after 7 days without user interaction, and caps them at 24 hours when the visitor lands from a link-decorated URL from a site Safari classifies as a tracker.
hubspotutkis set by JavaScript, so a Safari visitor who comes back after two weeks can look like a new person. - Cross-domain journeys. A visitor reads your blog on one domain, books a demo on another, and HubSpot sees two strangers. HubSpot can pass the visitor ID across domains with link parameters, but only when automatic cross-domain link tracking is switched on and every domain runs the same tracking code. See why HubSpot cross-domain tracking breaks.
- Third-party tools in the path: booking tools, chat widgets and app signups that create contacts without sending the
hubspotutkcookie. - Visitors switching device between the first visit and the conversion. Cookies cannot follow that.
Persistence problems also explain most of the gap between GA4 and HubSpot. Each tool has its own cookie, its own session rules and its own consent behaviour, so they lose different visitors. If the two disagree by a wide margin, start with why GA4 and HubSpot lead counts do not match.
Layer 3: CRM
The data reached HubSpot. Now the records have to keep it. This layer breaks quietly:
- Contacts created by import, sales tools or integrations before the visitor ever converts on the site. They arrive as Offline Sources, and their earlier web history may never be attached.
- Workflows or integrations that overwrite source properties, or bulk edits that clear the drill-downs.
- Deals with no associated contacts. Revenue attribution needs at least one, so those deals drop out of the report.
- Lifecycle stages that are skipped or set inconsistently, so "deal created" means different things.
- CRM migrations. Historic records come in as imports, and the attribution history from the old system does not carry over unless someone plans for it.
For a worked example of a CRM-layer problem disguised as a traffic problem, see the anonymized case study on HubSpot reporting the wrong traffic sources.
Layer 4: ad platform feedback
The last layer runs in the other direction. Google Ads, Meta and LinkedIn optimize toward the conversions they are told about. In most B2B accounts that is a form fill. The ad platform has no idea which form fills became qualified pipeline and which were students or competitors, so it keeps buying more of whatever converts cheapest.
- No offline conversion upload, so Google Ads never sees an SQL or a closed deal. See why Google Ads offline conversions are missing.
- Click IDs such as
gclidnot stored on the contact, so a later upload has nothing to match on. - Upload windows missed. Google Ads does not import standard GCLID-based offline conversions uploaded more than 90 days after the click. For Enhanced Conversions for Leads the limit is 63 days. Long B2B sales cycles hit these limits often, so upload an earlier stage too.
- HubSpot ad conversion events created but never checked. They only count lifecycle changes and form submissions that happen after the event was created.
How to fix each layer
Fix the layers in order. A perfect offline conversion upload is wasted if the click ID was lost at capture. Here is what each fix looks like in practice.
Fixing capture
Start with a capture test: tagged test visits through every paid channel, every landing page template and every form type, then check what landed on the test contact. That alone usually finds the leak. The fixes are often small. Fixing a single broken integration, such as an embedded form that drops UTMs, is typically 2 to 5 hours of work. Then fix the UTM conventions so the classification rules above put each channel where you expect it.
Where browsers and blockers stop scripts from running, the fix is to move collection off the browser. Server-side tracking that works when browsers block your data routes events through your own subdomain and a server-side GTM container, then sends them on to GA4 and the ad platforms. A server-side GTM rebuild with Meta CAPI and GA4 routing is typically 15 to 20 hours.
For EU and UK traffic, capture also has to respect consent. The goal is to keep tracking compliant without losing the source data you are allowed to keep. That means a banner that maps cleanly to Google consent signals, HubSpot cookies held until consent, and source parameters read correctly once consent is given. That is the work in Consent Mode setup that keeps tracking compliant without losing your data.
Fixing persistence
Switch on cross-domain link tracking and put the same HubSpot tracking code on every domain in the journey. For tools that create contacts outside HubSpot forms, such as booking tools and app signups, pass the visitor ID and source data with the submission or through the API. Store first-touch UTMs and click IDs in your own contact properties at the moment of conversion, so a later cookie loss cannot erase them.
Server-side collection can help here too. Safari caps cookies written by JavaScript at 7 days, or 24 hours after a click from a decorated link. Cookies set in an HTTP response by your own server are not under that cap, but Safari also caps them at 7 days when the tracking subdomain is a CNAME to a third-party host or resolves to a third-party IP address. The design trade-offs are on the server-side attribution architecture page.
Fixing the CRM layer
Write down the rules: which properties hold source data, which systems may write to them, and what happens when a contact is created outside the website. Then enforce them. Lock source fields against overwrites, associate contacts to every deal, and make lifecycle stages move in one direction. Clean historic records with a rule you can explain, not ad hoc edits.
If you are moving to HubSpot from another CRM, plan attribution before the import, not after it. That means mapping old source fields, re-installing tracking on every domain and form, and checking that integrations write to the right properties. Rebuilding tracking during a HubSpot migration covers this.
Fixing ad platform feedback
Feed the outcomes back. Store the click ID on the contact at capture. Send qualified stages, such as SQL or opportunity created, to Google Ads as offline conversions or through Enhanced Conversions for Leads. Do the same for Meta and LinkedIn through their Conversions APIs. Then the ad platforms optimize toward pipeline, not form fills. This is getting real conversions back into Google Ads, Meta and LinkedIn.
How I run this work
Most of the time it starts with an Attribution Audit: a fixed-scope, read-only review of all four layers, from $2,000. You get written findings ranked by cost and a fixed-price fix plan. The work itself is a one-time attribution fix, scoped and priced before anything starts. Most fix projects complete within 1 to 2 weeks. Everything happens in your own GTM, HubSpot and GA4 accounts, and you get written documentation of what changed and why.
Tracking does not stay fixed. A developer changes a form, a new landing page goes live without the script, an ad platform changes its API. Attribution Monitoring flags tracking breaks before they hit your reports, with alerts in Slack or email. Most clients move here after their first fix, and you can try it free for 2 weeks.
When an attribution tool helps, and when it does not
Dedicated B2B attribution tools such as HockeyStack and Dreamdata promise the full picture: account-level journeys, ad spend joined to revenue, custom models. They can deliver that. They cannot deliver it from broken inputs.
These tools read the same raw material HubSpot reads: a tracking script on your site, form submissions, CRM records and ad platform data. Their script is subject to the same blockers, consent rules and Safari limits. Their CRM sync inherits your missing deal associations and overwritten source fields. Contacts that reach HubSpot without a source will reach the new tool without a source too, just in a nicer chart.
A tool helps when
- Capture, persistence and the CRM layer are already in good shape, and you have checked them.
- You need account-level views across many contacts in a buying group, which HubSpot's contact-centric reports handle less well.
- You want to join ad spend and costs from several platforms to pipeline without building it yourself.
- You are not on Marketing Hub Enterprise and need deal or revenue attribution.
- Someone on the team owns the tool and will act on what it shows.
A tool does not help when
- Most new contacts are Direct Traffic or Offline Sources. That is a capture problem, not a reporting one.
- Deals are not consistently associated with contacts and companies.
- Nobody agrees what counts as a qualified lead, so there is no stable conversion to attribute.
- The real goal is better ad platform optimization. That needs conversion feedback, not another dashboard.
My honest order of operations: fix the inputs, use HubSpot's own reports for a quarter, and decide on a tool once you know which question HubSpot cannot answer. Any attribution tool still needs implementation, and it goes much faster on clean data.
Where to start: a short checklist
You can do most of this yourself in an afternoon.
- Build a report of new contacts in the last 90 days by Original Traffic Source. Note the share of Direct Traffic and Offline Sources.
- Open ten recent Direct Traffic contacts. Check drill-down 1 for the entrance URL and look for a pattern: one landing page, one form type, one domain.
- Click one of your own ads, submit a test form, and check the test contact. Did the campaign, source and click ID arrive?
- Repeat the test in Safari, with the consent banner declined and then accepted.
- List every domain and tool in the journey: site, blog, app, booking tool, chat. Check the tracking code and cross-domain settings on each.
- Find closed-won deals from the last two quarters with no associated contact.
- Check what your ad platforms count as a conversion. If it is only form fills, they are optimizing for volume, not pipeline.
- Compare lead counts in GA4, HubSpot and each ad platform for the same month. Write down the gaps before you try to explain them.
If step 3 or 4 fails, start at capture. If the tests pass but the numbers still disagree, the problem is further down the chain. Either way, you now know which layer to look at.
Common questions
Contact create attribution reports are available on Marketing Hub Professional and Enterprise, and on Content Hub Professional and Enterprise. Deal create and revenue attribution reports are Marketing Hub Enterprise only. The Original and Latest Traffic Source properties exist on every contact regardless of tier.
HubSpot labels a visit Direct Traffic when it finds no referring domain and no tracking parameters. A high Direct share in B2B usually means UTMs and referrers are lost before the tracking code reads them, through embedded forms, redirects, cross-domain hops, consent banners or blocked scripts. See why HubSpot shows so much Direct traffic.
Yes. You can edit it on a single record, in bulk, or with a workflow. Editing it clears the drill-down properties and the First Referring Site value, so the detail of where the contact came from is gone. Fix the capture problem first, then correct historical records with a clear rule you can explain later.
Start with first interaction and last interaction side by side. They answer two different questions: what brings people in, and what makes them convert. Try Linear or Empirical once you trust the inputs. A sophisticated model on top of broken source data only spreads the errors across more touchpoints.
Not usually as a first step. Tools like HockeyStack or Dreamdata read from the same tracking, forms and CRM records as HubSpot does. If those inputs are broken, the tool reports the same gaps with better charts. Fix capture and CRM hygiene first, then decide whether HubSpot reporting is enough.
Describe what you are seeing
Send a few lines about what looks wrong. I reply within 1 business day and tell you whether it needs an audit, a fix, or nothing at all.