Lead-to-sale reporting: connect marketing sources to CRM revenue
How to carry each lead's source into HubSpot or GoHighLevel, report won revenue by campaign, and avoid the mistakes that leave deals with no source.
On this page
Analytics knows where a lead came from. The CRM knows whether that lead became a customer, and for how much. Lead-to-sale reporting joins the two, so a campaign is judged by the revenue it closed, not by the forms it filled.
The join is simple in principle: the source has to be written on the contact when the lead arrives, and stay there until the deal closes. Most broken reports fail at one of those two moments.
Step 1: write the source on the lead
There are two ways, and the best setups use both.
Hidden form fields. Add hidden fields for utm_source, utm_medium, utm_campaign, the ad click id (gclid, fbclid) and the landing page. A small script fills them from the landing page address, saved when the visitor arrived, so the values survive a visit to three other pages before the form.
The CRM's own tracking. Both big small-business CRMs record a source on their own:
- HubSpot sets Original Traffic Source, the first known web source of the contact, from a fixed list: Organic search, Paid search, Email marketing, Organic social, Referrals, AI Referrals, Other campaigns, Direct traffic, Paid social and Offline sources. Its two drill-down properties hold the detail, such as the
utm_campaignfor paid search (HubSpot). - GoHighLevel keeps a First attribution and a Latest attribution on every contact. The first one never changes; the latest one follows the most recent interaction (HighLevel).
HubSpot notes that an ad blocker can block its tracking cookies and affect these values (HubSpot). That is why hidden fields filled by your own site's code are worth adding even when the CRM tracks sources itself.
Step 2: define the stages, with dates
A report by source is only as good as the stages behind it. Agree on a short list, and record the date each one is reached:
| Stage | Meaning | Who sets it |
|---|---|---|
| Lead | A form, call or booking with contact details | Automatic |
| Qualified | Fits your customer and wants to talk | Sales, by a rule everyone uses |
| Opportunity | A quote or proposal is out | Sales |
| Won | Signed or paid, with the amount | Sales or billing |
| Lost | With a reason | Sales |
The dates matter because sales take time. A lead from March that closes in May belongs to March's campaign.
Step 3: report by when the lead came in
Two ways to cut the same data, both needed:
- By lead month (cohort). "Of the leads Google sent in March, how many closed, and for how much?" This is how you judge a campaign. It keeps growing for months as deals close.
- By close month. "What did we win in May, and where did it come from?" This is how you report revenue.
Read cost per won deal next to cost per lead. A cheap lead source that never closes is expensive.
A worked example
Example numbers, made up for illustration. A web design studio, leads from January to March, read in June:
| Source | Leads | Qualified | Won | Revenue | Spend | Cost per won deal |
|---|---|---|---|---|---|---|
| Google Ads | 96 | 31 | 7 | $42,000 | $6,300 | $900 |
| Meta ads | 140 | 18 | 3 | $13,500 | $4,200 | $1,400 |
| Referrals | 22 | 15 | 8 | $61,000 | $0 | $0 |
| Organic search | 51 | 12 | 4 | $19,000 | $0 | $0 |
Meta ads sent the most leads and the least revenue. On cost per lead, Meta looks best ($30 against Google's $66); on cost per won deal it is the worst. Referrals, invisible in an ads report, closed the most business.
Step 4: send results back to the ad platforms
Once won deals carry their source and click id, the ad platforms can learn from them:
- Google Ads imports offline conversions from HubSpot directly through its Data manager (Google), or from any CRM by upload. See Google Ads conversion tracking for lead generation.
- Meta takes CRM lead stages for its own lead forms through the Conversions API for CRM. Website leads go through the regular Conversions API. See offline conversions explained.
Mistakes that leave deals with no source
- Contacts created by hand. A salesperson types in a lead from a call, and it has no source. Add a required "How did you hear about us?" field for manual entries.
- The source overwritten. An import or a later form fill replaces the first source. Keep a first-touch field that is written only when empty.
- Duplicates. The same person under two emails splits their history. Merge on email and phone.
- Deals without a contact. A deal must be tied to the contact that carries the source, or the source never reaches the revenue.
- Judging too early. A campaign launched in May cannot be judged in June if deals take 60 days.
Deciding which touch gets credit when a deal had several is a separate question; see attribution models explained.
Common questions
How do I track which marketing source a sale came from in my CRM?
Write the source on the contact when the lead arrives, with hidden form fields and the CRM's own source tracking, tie every deal to that contact, and report won revenue by the contact's source.
What is HubSpot's Original Traffic Source?
HubSpot's property for the first known web source of a contact, from a fixed list such as Paid search or Organic social, with drill-down properties for the campaign or site.
Should I report by lead date or close date?
Both. Lead date (cohort) judges campaigns. Close date reports revenue for the period.
Why do so many CRM deals show as direct or offline?
Contacts added by hand, imports, ad blockers stopping the CRM's tracking, and first sources overwritten by later activity. Hidden form fields and a first-touch field written once fix most of it.
Sources
- HubSpot Knowledge Base: Understand Original and Latest traffic source properties. Checked October 2026.
- HighLevel Support Portal: Understanding attribution source. Checked October 2026.
- Google Ads Help: HubSpot. Checked October 2026.
Spotted something wrong or out of date? Email hello@sporetag.com and we will fix it.