Cost per lead is the number that quietly makes HVAC accounts worse
Two lead sources on the same ad spend, and the one with leads at half the price sells fewer jobs. The arithmetic, and how to pull the real number out of the software you already run.
TL;DR
- There is no HVAC cost per lead worth aiming at on its own: it tells you what a call or a form cost, not what a job cost. Cost per sold job is cost per lead divided by the share of leads that booked a visit and the share of visits that sold. In the illustrative example below, the source whose leads cost twice as much sells jobs for $150 less each.
- Google Ads bids toward whatever sits in your "Conversions" column, and "Cost / conv." is your spend divided by that count. If the column counts calls, the campaign looks for cheap calls. In the accounts we run, the cheapest calls are the ones least likely to become work.
- ServiceTitan can send job revenue back to Google Ads through Ads Optimizer, which needs its Marketing Pro package with Ads. Revenue goes only after a job is marked Complete, and Google files it under the date of the ad click, so last month's numbers keep changing for weeks.
- Without ServiceTitan, count sold jobs by hand, the same way every month: finished jobs invoiced above your diagnostic fee. Match a Housecall Pro job export against your call log, or start from Jobber's Lead Source Report, whose "Leads with invoice" also counts diagnostic-only visits.
What does a lead actually tell you?
A lead is a promise that somebody might buy something. Google Ads sees a form submitted or a call connected. Whether the caller lives inside your service area, whether a CSR picked up, whether a visit got booked and whether the tech sold the job all happen in your phone system and your CRM, which the ad platform cannot see unless you send the answer back.
Google's help page on conversion reporting defines the two columns in most monthly reports. "Conversions" is "the number of conversions that you've received across your primary conversion actions", and "Cost / conv." is calculated "by dividing your total cost by the number in your 'Conversions' column". The same page says that "in most cases, all of your conversion actions are included in your 'Conversions' column unless you've unchecked the setting." In most accounts, "Cost / conv." is a cost per whatever got counted: a call, a form, sometimes a tap on the phone number.
In the accounts we run, the cheapest conversions are usually these:
- homeowners fixing it themselves who want a part number or a breaker reset;
- techs looking for work, who type the same words a customer does;
- shoppers pricing a portable or window unit, who will never hire a contractor;
- people an hour past the drive time your trucks cover, whose click costs the same as one ten minutes from the shop;
- taps on the phone number after hours, when nobody answers;
- existing customers who are already in your CRM, bought again by the click.
If your account counts them, each one lands in the "Conversions" column and lowers your cost per lead.
Why does bidding to cost per lead make it worse?
Google describes Target CPA this way: "Some conversions may cost more than your target and some may cost less, but altogether, Google Ads will try to keep your cost per conversion equal to the target CPA you set." Maximize conversions has no target; Google says it sets bids "to help get the most conversions for your campaign while spending your budget."
To both strategies, a breaker question and a call that became a new system are one conversion each. What follows is our reading, not a statement from Google: a system told to hit an average cost per conversion buys more of whatever converts cheaply and less of whatever converts at a high price. When the conversion is a call, the cheap ones are the list above. The owner rarely sees it happen, because the lead report improves while it does. For form fills bought by Performance Max, see cheap Performance Max leads that never book.
A worked example: same spend, two lead sources
These numbers are an illustration, not client data. Put your own in their place.
Two campaigns spend $4,000 a month each. Campaign A runs broad terms across the whole metro. Campaign B runs repair and replacement terms inside a 30-minute drive of the shop.
| Campaign A | Campaign B | |
|---|---|---|
| Ad spend | $4,000 | $4,000 |
| Leads (calls and forms) | 80 | 40 |
| Cost per lead | $50 | $100 |
| Leads that booked a visit | 25% (20) | 60% (24) |
| Booked visits that sold | 50% (10) | 2 in 3 (16) |
| Cost per sold job | $400 | $250 |
On a lead report, Campaign A wins with half the cost per lead. On the invoices, Campaign B sells each job for $150 less.
Now the account is told to bring cost per lead down, and it moves $2,000 from B to A. Assume, generously, that A's extra leads book and sell at the same rates as its first 80. In the accounts we run, the extra leads usually book and sell at lower rates than the first ones.
| Whole account, $8,000 a month | Before | After moving $2,000 to A | Change |
|---|---|---|---|
| Leads | 120 | 140 | +17% |
| Cost per lead | $67 | $57 | −14% |
| Booked visits | 44 | 42 | −5% |
| Sold jobs | 26 | 23 | −12% |
| Cost per sold job | $308 | $348 | +13% |
The monthly report shows 17% more leads at a 14% lower cost per lead. The job board shows three fewer sold jobs for the same $8,000.
The formula to keep:
Cost per sold job = cost per lead ÷ (booked rate × close rate)
Campaign A: $50 ÷ (0.25 × 0.50) = $400. Campaign B: $100 ÷ (0.60 × 2/3) = $250. A lead at half the price comes out ahead only if its booked rate times its close rate is better than half of the other source's.
What it looked like in an account we run
The Comfort Authority fixes air conditioning and plumbing in Tampa from one shop, and its service area page listed forty-seven cities. Calls were first wired through to the CRM, so a call could be followed to a sold job. Then the radius was rebuilt on drive time, and search terms that never become jobs were cut, among them "how to reset ac breaker" and "hvac jobs tampa". Plumbing got its own budget, and spend moved to the hours someone answers.
The Comfort Authority, Tampa Bay. After those changes: Calls from ads: −22%. Window: 90 days against the 90 before. Source: Call tracking.
Limit: Nothing here separates the effect of the radius change from the effect of the search term cleanup. They shipped three weeks apart in the same account and we did not hold one back to prove the other.
Same account. Jobs sold from paid search: 1.6×. Window: 90 days against the 90 before. Source: Client CRM.
Limit: Jobs sold come from the client's CRM, which means they depend on technicians closing tickets correctly. We did not audit that, we read it.
Same account. Cost per sold job: −30 to −35%. Window: 90 days against the 90 before. Source: Call tracking.
Limit: The two windows are not weather-matched. Two Tampa quarters are never identical, and some of this movement belongs to the season rather than to us.
A report that counted only leads would have shown that quarter as a decline.
How does ServiceTitan send revenue back to Google Ads?
If you run ServiceTitan, the sold-job number can go back into Google Ads automatically. ServiceTitan's help page "How Revenue Import works in Ads Optimizer" sets the conditions first: "Your account needs to have a Marketing Pro package with Ads enabled to use Ads Optimizer", and Ads Optimizer needs the Google Ads integration, the Google Analytics integration and Dynamic Call Tracking using DNI.
The steps, in ServiceTitan's order:
- A customer clicks a Google ad and calls the ServiceTitan tracking number on your website, or a ServiceTitan call extension number on the ad. ServiceTitan stores the Google Click ID (GCLID).
- ServiceTitan ties that click ID to the lead for the caller.
- "After the Lead is converted to a job and that job marked as Complete in ServiceTitan, revenue is attached to it."
- ServiceTitan sends the revenue into Google Ads using the click ID, under a conversion action it creates called "ServiceTitan Completed Jobs Conversion Action". The revenue appears in the "All Conversion Value" column.
- Google Ads assigns the revenue to the click that produced the call.
The note under step 5 is the one that confuses owners:
"Google Ads assigns the Revenue to the date and time of the ad click, not the date of the completed job and import. For example, if someone clicks an ad on January 1 and calls that same day, but the job isn't completed until January 5, the Conversion Value appears in the reports as happened on January 1."
The same Revenue Import page states the cost-per-lead problem in one line: "a keyword may appear to be successful by generating low-cost phone calls, but now you can see there is no conversion value being attributed to it."
Four things follow for your reports.
- Last month is not finished on the 1st. ServiceTitan's Job Value Predictor page says revenue goes to Google Ads "only after a job is completed, which can take days, weeks, or even months." Each late completion lands back on the day of the click, so a month's revenue in Google Ads keeps rising after the month ends.
- You can reconcile it. ServiceTitan's mismatch page recommends adding the column "All conv. value (by conv. time)" and segmenting by conversion action. That column "shows the conversion value on the date it was sent into Google Ads, which should align closely with the job completion date in ServiceTitan."
- Long jobs may never reach Google. Google's offline conversion FAQ says: "We retain the GCLID for only 90 days." ServiceTitan's pages don't say what happens to a job completed more than 90 days after the click. Our reading is that its revenue cannot attach to that click.
- With Job Value Predictor on, Google bids on a forecast. JVP sends a predicted job value "as soon as a job is booked" and makes it the primary conversion. Activated through the Ads Optimizer page, it also sets the completed-job actions to Secondary. Google's conversion page says the "Conversions" column counts primary actions and is the data "used for your bidding strategies", so the completed-job revenue still shows in reports but no longer steers bids. For new Ads Optimizer customers, JVP "is activated by default for all campaigns."
No ServiceTitan? Jobber, Housecall Pro or a spreadsheet
Our definition of a sold job, kept the same every month: a job marked finished with an invoice above your diagnostic fee.
- Jobber. The Lead Source Report shows "Leads", "Leads with job", "Leads with invoice" and "Invoice value" per lead source, and Jobber defines invoice value as "The total amount from the first invoice linked to the lead." It filters by the date the lead was created and exports to CSV. A lead counts under "Leads with invoice" if it has "an invoice associated", a diagnostic-only visit included, so spend on a source divided by that column is a floor on its cost per sold job. For the real number, count only the leads with an invoice above your diagnostic fee. Both depend on your office recording the lead source on every new client. Sending those jobs back to Google Ads is covered in which Jobber stage to send to Google Ads.
- Housecall Pro. Its help page on exported reports lists the customer's mobile and home phone numbers, "Amount" (the invoice total) and "Job Status" among the exported fields, with "Done" meaning "Finish" was clicked. Match those phone numbers against your call tracking log for the same period and count, per campaign, the Done jobs whose Amount is above your diagnostic fee.
- Anything else. To send the result back to Google Ads, Google's offline conversion FAQ says you don't necessarily need a CRM: "Any system that captures lead information can be adapted for this use. A Google spreadsheet will also work." It advises a separate conversion action for each stage, and adds: "Usually, you would only want to bid to one stage of the lead funnel".
What this doesn't cover
- Job size. Cost per sold job counts a repair and a new system as one job each. To compare sources on money rather than job count, divide spend by invoice value instead: Jobber's "Invoice value" column or the "Amount" field in a Housecall Pro export.
- Wiring phone calls to click IDs outside ServiceTitan. That depends on your call tracking product and deserves its own piece.
- Why reports lead with leads. Part of the answer is how the agency is paid, which how HVAC marketing agencies charge works through.
Do this in your account
- See what Google counts. In Google Ads, go to Summary in the Goals menu and write down which conversion actions are primary. If the list is calls and form fills, your "Cost / conv." is a cost per call or form, not per job.
- Export last quarter's calls from your call tracking: caller number, date, campaign.
- Export last quarter's jobs with customer phone, status and invoice amount. In Jobber, the Lead Source Report does most of the work. In Housecall Pro, open the Jobs report on the Dashboard with the eye icon, then use the Excel icon to download a CSV.
- Match by phone number. For each campaign, count leads, booked visits and sold jobs (finished, invoiced above your diagnostic fee).
- Rank campaigns both ways, by cost per lead and by cost per sold job. Where the order flips, the account is paying for leads that don't become jobs.
- On ServiceTitan with Ads Optimizer, add "All conv. value (by conv. time)" in Google Ads, segment by conversion action, and check whether the JVP actions or the completed-job actions are the primary ones.
- Judge a month late. Read a month's revenue in Google Ads once most of its jobs are marked Complete. The rest of the account is covered in the 30-minute Google Ads audit checklist.
FAQ
What is a good cost per lead for HVAC? No single number tells you whether a lead source makes money. In the example above, a $100 lead costs less per sold job than a $50 lead because 40% of its source's leads become sold jobs against 12.5% of the cheaper source's. We don't publish a benchmark. Judge sources by cost per sold job.
How do I calculate cost per sold job? Divide the ad spend for a source by the jobs sold from that source in the same period, with calls and forms matched to CRM jobs by phone number. If you know your booked and close rates, cost per lead ÷ (booked rate × close rate) gives the same answer.
Is cost per sold job the same as customer acquisition cost? Not quite. Customer acquisition cost usually spreads all sales and marketing cost over new customers. Cost per sold job, as used here, puts one campaign's ad spend against the jobs sold from it, repeat customers included, which makes it the number to compare campaigns with.
Does ServiceTitan send revenue to Google Ads? Yes, through Ads Optimizer, which needs a Marketing Pro package with Ads plus the Google Ads integration, Google Analytics integration and DNI call tracking. Revenue goes after the job is marked Complete and shows under "ServiceTitan Completed Jobs Conversion Action".
Why doesn't revenue in Google Ads match ServiceTitan? ServiceTitan's mismatch page lists three common causes. The first is dates: ServiceTitan records revenue on the completion date, and Google Ads files it back under the ad click, which the page calls "the ad impression date"; for a call from a search ad, we'd expect that to be the same day. The other two are office staff changing a job's campaign by hand, and call extension numbers dialed when no ad was showing, whose revenue Google rejects.
Sources
All read in full on September 24, 2026. Every quotation above is from these pages.
- Google Ads Help, "Understand your conversion tracking data", https://support.google.com/google-ads/answer/6270625
- Google Ads Help, "About Target CPA bidding", https://support.google.com/google-ads/answer/6268632
- Google Ads Help, "About Maximize conversions bidding", https://support.google.com/google-ads/answer/7381968
- Google Ads Help, "Offline conversion imports FAQs", https://support.google.com/google-ads/answer/10029210
- ServiceTitan Help Center, "How Revenue Import works in Ads Optimizer", https://help.servicetitan.com/docs/how-revenue-import-works-in-ads-optimizer
- ServiceTitan Help Center, "Understand revenue mismatches between Google Ads and ServiceTitan", https://help.servicetitan.com/docs/understand-revenue-mismatches-between-google-ads-and-servicetitan
- ServiceTitan Help Center, "Use Job Value Predictor (JVP) in Ads Optimizer", https://help.servicetitan.com/docs/use-job-value-predictor-jvp-in-ads-optimizer
- ServiceTitan Help Center, "Enable Marketing Pro Ads Optimizer", https://help.servicetitan.com/docs/enable-marketing-pro-ads-optimizer
- Jobber Help Center, "Lead Source Report", https://help.getjobber.com/hc/en-us/articles/32898448087959-Lead-Source-Report
- Housecall Pro Help Center, "Exported Report Breakdown", https://help.housecallpro.com/en/articles/2999685-exported-report-breakdown
- Housecall Pro Help Center, "Navigating Your Dashboard Reports", https://help.housecallpro.com/en/articles/4671115-navigating-your-dashboard-reports