Ranked by installed value
Replacements and installs rank above service calls, because that is what they are worth.
Marketing attribution for HVAC Companies
Match installed equipment and invoiced work to the calls and ads that produced them, so the channel that fills your install schedule is obvious.
$349,200 68% of $513,500 paid
The blind spot
A $180 diagnostic and a $14,000 system replacement come from the same ad and the same phone number. Your cost-per-lead report treats them as one lead each, which is why the channel that actually pays for the trucks can look like the worst performer.
What you get
Replacements and installs rank above service calls, because that is what they are worth.
Compare this August with last August, so a heatwave is not mistaken for a winning campaign.
An October quote approved in March still matches the ad that produced the original call.
A worked example
Not impressions, not leads, not cost per click. Closed revenue, by the channel that produced it, for a period you choose — with the portion we could not trace shown rather than quietly shared out across your paid channels.
| Channel | Sales | Revenue | Share | % |
|---|---|---|---|---|
| Google Ads | 38 | $241,400 | 47% | |
| Meta Ads | 24 | $61,600 | 12% | |
| Email marketing | 19 | $46,200 | 9% | |
| Direct / Unknown | 63 | $164,300 | 32% |
Most HVAC marketing is measured on call volume, and call volume is dominated by service work. Replacements are rarer, far larger, and often produced by different creative, different keywords and sometimes a different channel entirely.
Ranking channels by invoiced value separates them. It is common to find a campaign producing a third of the calls and most of the install revenue — and equally common to find a cheap lead source producing volume that never converts above a diagnostic fee.
An aging system gets quoted in October and replaced in March when it finally fails. Click attribution lost that connection months earlier; the ad platform closed its books on October and moved on.
Matching on the customer's phone number or email means the March invoice is credited to the October call. For a trade where a large share of replacement revenue is deferred, this routinely changes which channel looks profitable.
Heating and cooling demand is weather-driven, and the weather does not respect reporting periods. A homeowner gets a diagnostic in the first hot week of June, decides to nurse the system through the summer, and replaces it when it fails properly in August — or in the first cold snap of November.
That puts the campaign and the revenue in different months and frequently different seasons. Any measurement built on a window credits whichever branded search happened in the final week and scores the original campaign as a cost with no return.
Because the match is on the homeowner rather than a session, the gap is irrelevant. The person who called in June and the invoice raised in November are one match, and the June spend is credited with the November revenue.
A maintenance plan is worth a modest amount in its first year. What it is actually worth is the renewals, the priority service calls, and the replacement quoted by a technician who is already standing in the house and has the homeowner's trust.
Marketing reports value the first payment. Matching on the customer attaches every later invoice to the channel that produced them, which usually moves plan-generating channels up the ranking sharply.
It also lets you ask a question most contractors cannot currently answer: whether the channel that produces the most replacements is the same one that produces the customers who stay.
The revenue file is a list of completed jobs or invoices, one row each, carrying the customer's phone or email, the amount and a date. Almost every field service system exports this; it is the report the office already runs to reconcile the month. Business unit or job type is optional; mapped as Product / service, it is the breakdown most worth adding, because it is what separates service from replacement.
The second file is whatever your demand looks like. A Google Ads or Local Services export, a call tracking export, a list of inquiries from a home services marketplace. Any one of them is enough to start. Several can be combined into that one lead file, each row tagged with its source, and every source you add is one less row sitting in the unattributed bucket.
Nothing goes on your website, nothing connects to your field service software, and no permissions are granted. That is also why a period that has already finished works exactly as well as the current one — the records were kept for billing, not for tracking.
Why it matters
"We generated 400 leads" invites an argument. "This channel closed $186,400 last quarter, here is the reconciliation" ends one. The teams that can show closed revenue by channel are the teams that get the next increase approved, because they are asking with evidence rather than with conviction.
Killing spend is politically harder than adding it, because someone always owns the channel being cut. A number that reconciles to the sales export takes the argument out of the room — you are not overruling a colleague's judgment, you are reading the same ledger they are.
Platform-reported conversions do not reconcile to revenue, and eventually someone in finance notices. Reporting built from your own closed-sales export starts from the number finance already trusts, which is why it holds up when it is checked.
Because this reconciles exports rather than tracking visitors, it works on months that have already closed. You are not instrumenting now to learn something in ninety days — you can answer for last quarter today, which is usually when the question is being asked.
Honest answers
Only completed, invoiced jobs need to be in it, with a phone or email, an amount and a date. That is a standard report and usually a few hundred rows a month.
Then it should show as Direct / Unknown rather than being credited to whichever ad ran that month. Knowing that maintenance customers are a third of revenue is useful; hiding them inside Google Ads is not.
Keep it — its export is one of the two files. It tells you the call came from Google Ads; CloseRev tells you the call became a $14,200 install.
Pricing
The price here is the price on the invoice, plus any sales tax that applies — no per-call, per-minute or per-form fees. Growth usually fits heating and cooling contractors buying ads — thirteen months of history to compare a month to the same month last year, and a PDF you can put in front of whoever holds the budget.
A business scaling ad spend
$49/mo
billed monthly
Questions
Anything else? Talk to us — a person answers, usually the same day.
Completed, invoiced jobs: customer phone or email, the amount, and the date. ServiceTitan, Housecall Pro, Jobber and FieldEdge all produce this as a standard report.
Yes — map a job-type column as Product / service and the report breaks down by it, which is usually the most useful cut for an HVAC business.
They match like anyone else. Most appear under Direct / Unknown on a later job, which is the honest answer — they were not produced by that month's advertising.
Compare any two ranges, including the same month a year earlier. Comparing August to July in this trade measures the weather.
No. No numbers, no minutes, no per-form fees — one flat price per plan.
Yes, with a service-area or ZIP code column mapped as Location. The report then shows revenue by area and how much of each traces to a channel.
As far as your exports go. Nothing had to be installed at the time, so last season can be analyzed today.
Invoiced job rows analyzed in a calendar month. Call and lead rows do not count.
Invoices. Estimates and finals diverge most on replacements, which are the jobs that decide which channel wins.
Yes, with a business-unit column mapped as Product / service. Blending them produces an average ticket that describes neither.
Yes, credited to the channel that produced the customer originally.
Yes, with a branch column mapped as Location, so each branch gets its own line in the breakdown.
Twelve months minimum, so a full heating and a full cooling season are both inside the file.
Add the marketplace's lead export to your lead file, each row tagged with the marketplace as its source. It is then ranked on invoiced revenue beside your own campaigns, which is a comparison the marketplace itself will never provide.
Nearby
Match invoiced jobs to the calls and ads behind them, and separate the drain clears from the repipes.
See how it worksMatch completed jobs and their revenue to the calls and campaigns that produced them, from a $140 outlet to a $22,000 service upgrade.
See how it worksMatch your invoiced jobs to the calls and ads that produced them, and find out which channel is actually paying for the trucks.
See how it worksWhere your sales already are
Export completed jobs and match them to the campaigns and calls that produced the customer — including the estimate that sat for four months.
What to exportMatch paid jobs to the campaigns and calls behind them, and rank channels on collected revenue rather than booked work.
What to exportExport invoices from QuickBooks Online, upload your call and lead records beside them, and see revenue by channel — from the ledger rather than from a guess.
What to exportCallTrackingMetrics attributes the contact. Match those contacts against your sales export and rank channels on the money rather than on the volume.
What to exportExport completed jobs, upload the calls and leads beside them, and rank your marketing on invoiced work instead of on booked calls.
What to exportExport your jobs, upload the calls and leads beside them, and rank channels on what was charged rather than on what was booked.
What to exportExport invoiced jobs, upload your calls and leads beside them, and get revenue by channel — with the trade that earned it as a cut of its own.
What to exportExport invoices from Kickserv, upload the leads behind them, and find out which marketing produced work rather than calls.
What to exportExport invoices from FieldPulse, upload the leads behind them, and see which channels produce work that closes.
What to exportExport the leads your campaigns produced, match them against closed sales, and find out which campaigns produced revenue rather than form fills.
What to exportExport invoices from Tradify, upload the leads behind them, and see which channels produce work rather than price comparisons.
What to exportExport your Angi leads, match them against the jobs you invoiced, and find out what a won job actually cost.
What to exportExport customers and paid invoices from Thryv, match them on the customer, and see what each source produced in money you received.
What to exportCallRail tells you which campaign produced the call. Match the caller against your sales export and find out which calls became money.
What to exportFrom the blog
Multi-crew home and field services businesses run on phone calls and job management software, not on web forms. Which means the standard marketing dashboard is measuring the smallest part of the business and missing where the money actually is.
Read the articleGoogle's Local Services Ads charge for the phone call, not the click, and they hand you the caller's number with the invoice. It is the easiest channel in the budget to attribute to closed revenue. Almost nobody does, because the lead inbox is not where the reports live.
Read the articleAttribution needs history and privacy law needs forgetting, and those two facts are in direct tension. A practical retention policy for marketing data: what to keep, what to aggregate, what to delete, and how to prove you did.
Read the articleStart today
Upload two exports and see your real revenue by channel in minutes. 14 days free, no card.