HubSpot says 12 leads from paid social. Ads Manager says 41. Neither is lying.

This one comes up in almost every account that runs paid media into HubSpot. The media buyerMedia buyer The person who runs the ad accounts day to day: sets up campaigns, manages budgets and bids, and reports on results. reports 41 leads from Meta for the month. The sales lead opens HubSpot, filters contacts by Original SourceOriginal Source HubSpot's record of the first channel that brought a contact to your website. It is set once, on the first visit HubSpot can see, and never changes afterwards. = Paid Social, and sees 12. Somebody’s numbers must be wrong.
They’re both right, about different questions. Once you understand the rules each side is using, the gap usually explains itself, and the part that’s a real problem is fixable in an afternoon.
What HubSpot is actually doing
HubSpot sets Original Source from the first known web visit it can tie to a contact, and once set, it doesn’t change. Latest SourceLatest Source HubSpot's record of the most recent channel that brought a contact back to the site. Updates on every visit, unlike Original Source. updates on every visit; Original Source is frozen at the first touch HubSpot saw.
How it classifies that first touch is a fixed rulebook. The traffic source rules for paid social require utm_medium to contain paid, ppc or cpc and utm_source to be exactly the name of a recognized social network.
Paid search needs utm_source to contain adword, ppc or cpc, or a valid gclid on the URL. Miss those conditions and the visit falls through to Organic Social, Referral, or Direct.
Three consequences follow.
Untagged clicks vanish. A Meta ad with no UTMsUTM parameters Tags added to the end of a link (utm_source, utm_medium, utm_campaign, utm_content, utm_term) that tell analytics tools where a visit came from. They only work if everyone spells them the same way. sends someone to your site with a Facebook referrer and an fbclid. HubSpot files that as Organic Social. The 41 leads become 12 because 29 of them were never tagged as paid.
First touch wins forever. Someone who found you through a blog post in March and converted through a retargetingRetargeting Showing ads to people who have already visited your site or interacted with your business. Cheap and effective, and also the easiest place for a platform to claim credit for a sale that was going to happen anyway. ad in July has Original Source = Organic Search. Meta counts the July conversionConversion The action you want someone to take after seeing an ad: a purchase, a form fill, a booked call. Each platform counts conversions by its own rules, which is why two dashboards rarely agree.. HubSpot credits March. Both are true.
The cookieCookie A small file a website stores in your browser to recognize you on later visits. Ad tracking depends on them, and browsers and privacy laws increasingly limit them. has to connect. HubSpot ties the visit to the contact through its tracking cookie. If the form is on a third-party landing pageLanding page The page someone arrives on after clicking an ad. Built for one action, unlike a homepage that tries to do everything. without the HubSpot tracking code, or the visitor’s browser blocked the cookie, the contact gets created with no web history and Original Source becomes Offline Sources, which is HubSpot’s polite word for “no idea”.
What Meta is doing
Meta counts a lead when its pixelMeta pixel A small piece of code on your website that reports visits and actions (page views, leads, purchases) back to Meta from the visitor's browser. Blocked by ad blockers and some browser privacy settings. or Conversions APIConversions API Meta's server-to-server channel for sending events like leads and purchases from your own server or CRM, instead of relying on the browser pixel. Usually run alongside the pixel, which is where double counting comes from. sees the lead event, and attributes it to any ad the person clicked in the last 7 days or viewed in the last day, by default.
It doesn’t care whether HubSpot saw the visit, whether it was the first touch, or whether the lead ever became a real opportunity. That’s a wider net by design, and it’s a reasonable number for optimizing delivery. It’s not a number to run pipeline reports on.
Closing the fixable part of the gap
The first-touch versus last-touch difference is a definitional gap. You can’t close it, but you can report both and stop arguing. The untagged-click problem is a real leak and it’s the one to fix.
1. Tag every paid URL so HubSpot can read it. utm_source=facebook&utm_medium=paid_social (or cpc) on every Meta ad. utm_source=google&utm_medium=cpc on every Google ad, with auto-taggingAuto-tagging A Google Ads setting that adds the GCLID to your landing page URLs automatically. Required for offline conversion import and for clean Google Analytics reporting. on so the gclid is there too. Set these at the account or campaign level with dynamic parameters so nobody has to remember.
2. Capture the UTMs on the contact record. HubSpot’s own source properties are read-only and reflect its rules, not yours. Create custom contact properties (utm_source, utm_medium, utm_campaign, utm_content, utm_term) and add them as hidden fieldsHidden field A form field the visitor can't see, filled in automatically by a script with things like the campaign name or click ID, so that information is saved on the contact record when they submit. on your forms.
A short script on the landing page reads the URL parameters, drops them into a first-partyFirst-party data Information you collect directly from your own visitors and customers (form fills, purchases, your own site's tracking), as opposed to data collected by or bought from someone else. cookie, and fills the hidden fields on submit. Now every contact carries the exact campaign and ad that created them, even when HubSpot’s classification disagrees.
3. Put the HubSpot tracking code everywhere a form lives. Every landing page tool, every microsite. No tracking code, no web history, no source.
4. Build the report on your properties, not just theirs. A contacts report grouped by your utm_campaign property will match the ad platform’s campaign names one to one. Original Source stays useful for first-touch questions. Your custom properties answer “which ad created this lead”, which is the question the media buyer was actually asking.
What to expect afterwards
The gap won’t go to zero. Meta’s view-throughView-through A conversion credited to an ad the person saw but never clicked. Ad platforms count these; your analytics and CRM cannot see them. and 7-day-clickAttribution window How long after someone clicks or sees an ad a conversion still counts as caused by it. Meta's default is 7 days after a click or 1 day after a view. Longer windows mean more conversions claimed. windows will always count more than a first-touch CRMCRM Customer relationship management software, such as HubSpot or Salesforce, where leads, contacts and deals are recorded. Usually the only system that knows whether a lead was real. property. But with UTMs captured on the record, the conversation changes from “whose number is right” to “here are 41 leads Meta claims, 33 of them have a Meta UTM on the contact, 8 are view-through or multi-touch, and 6 of the 33 are qualifiedQualified lead A lead that meets your sales team's definition of real: right kind of company, a budget, a working phone number. Different from a form fill, which anyone (or any bot) can produce.”. That’s a report someone can make a budget decision from.
If your HubSpot portal has never had the hidden-field setup done, or the source data looks like it’s mostly Offline Sources and Direct, that’s usually a one-day fix. It’s part of the tracking and attribution work I do, and it’s the first thing I check on any account that reports out of HubSpot.