- Most HVAC accounts spending $25k+/month have CallRail or CallTrackingMetrics installed, but no booked-job signal flows back to Google Ads. Smart Bidding ends up optimizing toward form fills and quote-shopper calls.
- The common 60-second qualifying threshold counts hangups as conversions because a real HVAC dispatch conversation typically runs roughly 110–140 seconds: greeting, address, problem, service window, truck-roll confirmation, ETA.
- The fix is a six-component hvac call tracking attribution stack for paid media wired in order: call tracking + DNI, GA4 event layer, Google Ads conversion actions, dispatch software webhook, Offline Conversion Import keyed on GCLID, and a Smart Bidding hierarchy that demotes form fills.
- Flat-value conversions force Smart Bidding to maximize the cheap outcome. A $79 tune-up call and a $9,000 replacement lead cannot be the same event.
- LSA and Meta calls don’t carry GCLID. They need separate attribution paths, not a forced fit into the Search conversion action.
Your Call Tracking Is Installed. Your Attribution Stack Doesn’t Exist.
Nearly every HVAC contractor spending $25k–$500k/month on paid media has call tracking installed. CallRail or CallTrackingMetrics is running. Dynamic Number Insertion (DNI, the JavaScript that swaps the phone number on your site based on traffic source) is firing. Calls are recording. And Google Ads is still buying $79 tune-up tire-kickers instead of $8,000 system replacements.

The tool isn’t broken. The hvac call tracking attribution stack for paid media doesn’t exist yet. The tool is one component sitting in isolation, not wired into a chain that feeds Smart Bidding the signal it needs. Smart Bidding (Google’s automated bidding that learns from your conversion data) only learns from what you send it. Right now, most accounts are sending it the wrong thing, or nothing at all.
This is a six-component problem with a specific fix order. The first thing breaking your account is almost certainly a call duration threshold that was set too low. The second is that booked jobs from ServiceTitan or Housecall Pro never make it back into Google Ads as a conversion. Let’s walk it.
The 60-Second Qualifying Threshold Counts Hangups as Conversions Because the HVAC Dispatch Call Takes 130 Seconds
Pull a sample of your last 100 booked-dispatch recordings and time them. When we audit HVAC accounts, the structure is consistent:
- Greeting and caller gives address: 15–25 seconds
- Caller describes the problem: 25–40 seconds
- CSR proposes a service window: 20–30 seconds
- Caller confirms truck roll and provides payment method: 15–20 seconds
- ETA and close: 15–20 seconds
That works out to roughly 110–140 seconds for a call that actually books a job. The widely used 60-second qualifying threshold (see CallRail’s qualified call documentation for how qualification is configured) doesn’t even get the caller past the address confirmation in HVAC.
What clears that 60-second bar? Quote-shoppers asking for a phone price on a tune-up. People asking if you service their ZIP. Robocalls that hold the line. Folks who hung up after the CSR asked for a credit card. Smart Bidding sees those as conversions, learns the keywords that produce them, and buys more of the same.
Why 90 Seconds Is the Floor, Not the Ceiling
Move the threshold to 90 seconds as your floor. That catches the call past intake and into the service-window negotiation, which is where intent actually lives. For replacement-lead calls (where the homeowner is asking about a new system), the right threshold is closer to 120 seconds, because those calls include a longer diagnostic conversation before any booking happens.
A reasonable starting setup:
| Call type | Duration threshold | Typical conversion value |
|---|---|---|
| Service / repair call | 90 seconds | Gross profit per service ticket |
| Tune-up / maintenance | 90 seconds | Gross profit per tune-up |
| Replacement-lead call | 120 seconds | LTV-weighted lead value |
When you raise the threshold, expect reported conversion volume to drop noticeably in the first week. That’s not the algorithm starving. That’s the noise leaving the signal.
Disposition Codes Do What Duration Thresholds Can’t
Duration alone misses the inverse failure: a 4-minute call where the caller argued about pricing and never booked. That’s a long unqualified call, and your threshold lets it through.
The second layer is disposition codes from the CSR or from your dispatch software. The minimum useful set:
- BOOKED: truck rolled or appointment confirmed
- QUOTED_NO_BOOK: quote given, no commitment
- OUT_OF_AREA: not serviceable
- WRONG_NUMBER / SPAM
- EXISTING_CUSTOMER: already on the books, not a new lead
Only BOOKED feeds the primary conversion. Everything else gets demoted or excluded. This is the cleanup that makes the rest of the stack honest.
The Six Components, Wired In This Order, Are What Actually Feeds Smart Bidding
Here’s the full stack. The order matters because each component depends on the previous one being wired correctly.
1. Call tracking platform plus DNI with keyword-level number pools. CallRail or CallTrackingMetrics, with a pool of numbers large enough that each concurrent session gets its own. The pool size should cover your peak-hour visitor count, not your average. When DNI swaps the displayed number, it also captures the GCLID (Google Click ID, the parameter Google Ads appends to ad clicks when auto-tagging is enabled, per Google Ads Help) from the URL and stores it against that call record. No GCLID on the call record means no path back to the click later.
2. GA4 event layer. GA4 (Google Analytics 4) is connective tissue, not the source of truth. The call tracking platform fires a phone_call event into GA4 with the GCLID, the call duration, the disposition, and a value. GA4’s job is to be the staging layer that downstream tools can read, and to give you a place to debug what’s flowing without logging into three platforms.
3. Google Ads conversion actions, configured with a real hierarchy. Most accounts have five conversion actions all set to Primary. That’s the same as having no hierarchy. The setup that works:
- Primary: Booked job (from dispatch software via OCI)
- Secondary: Qualified call (90s+, valid disposition)
- Secondary: Form fill
- Observation only: Page views, button clicks, short calls
See Google’s documentation on primary vs. secondary conversion actions for the exact mechanics. Only Primary actions drive Smart Bidding. Secondary actions are reported but ignored by the bidder.
4. Dispatch software webhook or integration. ServiceTitan, Housecall Pro, and Jobber all expose job-status data through APIs and integration platforms (Zapier, Make, or native connectors), so you can trigger an outbound event when a job moves to Booked, Dispatched, or Completed. The payload needs to carry the original GCLID that was captured at the call tracking layer in step 1 and passed into the customer record. Without that GCLID on the booked-job event, OCI has nothing to match against.
5. Offline Conversion Import (OCI) keyed on GCLID. This is the piece that closes the loop. The event from step 4 fires into a middleware layer (Zapier, Make, or a custom endpoint) that formats the booked-job event and pushes it into Google Ads via the Offline Conversion Import API. For call-driven leads, you key on GCLID so Google attributes the booked job back to the original click, even if the booking happened 11 days later. (The API also supports other identifiers like GBRAID or order ID for non-click scenarios, but GCLID is the right key for this stack.)
6. Smart Bidding hierarchy on a value-based bid strategy. With booked jobs flowing in as the Primary action, switch the bid strategy from Maximize Conversions or tCPA (target cost-per-acquisition) to tROAS (target return on ad spend) or Maximize Conversion Value. Now the algorithm is optimizing for booked-job revenue, not call volume.
The GCLID Capture-and-Pass Bridge Most Setups Miss
Here’s the failure mode we see most often. CallRail captures GCLID correctly at the call. The CSR creates a customer in ServiceTitan. The GCLID never makes the jump.
The fix is a custom field on the ServiceTitan customer record called gclid, populated either by a CallRail-to-ServiceTitan integration or by the CSR pasting it from the CallRail call detail screen. The webhook in step 4 reads that field and includes it in the outbound payload. Skip this and the entire stack downstream of step 3 is dead weight.
Why GA4 Is Connective Tissue, Not the Source of Truth
GA4’s attribution is its own model. It will disagree with Google Ads on conversion counts. That’s fine. Don’t try to reconcile them. Use GA4 to debug data flow (is the phone_call event firing with GCLID attached?) and to look at channel-level patterns. Use Google Ads conversion reporting for bidding decisions. Two tools, two jobs.
Flat-Value Conversions Force Smart Bidding to Maximize the Cheap Outcome
If you send Google Ads a $79 tune-up call and a $9,000 replacement lead as the same flat-value qualified call event, you’ve told the algorithm both outcomes are equally valuable. Smart Bidding’s job is then to maximize the volume of the cheaper, more frequent one. That’s why good tracking still produces tune-up calls at scale.
A reasonable value map, anchored to gross profit per outcome:
| Conversion event | Assigned value | Logic |
|---|---|---|
| Tune-up call (booked) | $40–$80 | Gross profit per tune-up |
| Service / repair call (booked) | $300–$800 | Average gross profit per repair ticket |
| Replacement-lead call (booked appointment) | $3,500–$9,000 | LTV-weighted lead value × close rate |
| Form fill | $5–$15 | Treated as an upper-funnel signal, not a primary |
Once values are flowing, move to value-based bidding. Google’s value-based bidding documentation walks the mechanics. The bidder will start preferring keywords that produce replacement-lead calls over keywords that produce tune-up clicks, because the revenue per click is higher.
LSA and Meta Calls Don’t Carry GCLID, So They Need Separate Attribution Paths
The stack above is GCLID-keyed. It works for Google Search. It breaks for Local Services Ads and Meta because neither passes a GCLID on the call.
For LSA: Use the Local Services Ads to Google Ads conversion link, which imports LSA calls directly as a conversion source. Don’t try to force LSA calls into your Search conversion action. Segment them. The booked-job feedback for LSA happens inside the LSA dashboard itself, where you mark leads as booked, archived, or disputed. That feedback shapes LSA’s ranking algorithm. Our electrical contractor LSA setup playbook covers the dispute-code discipline that translates to HVAC almost line-for-line.
For Meta-driven calls: There’s no click ID equivalent to GCLID on a phone call from a Meta ad. The attribution path is Meta’s Conversions API (CAPI), keyed on hashed phone number plus event time. The dispatch webhook fires a booked-job event into CAPI with the customer’s phone number hashed, and Meta matches it back to the original ad exposure. Match rates won’t be as clean as GCLID matching, but they’re functional once you’ve got the phone number flowing as a CAPI parameter.
Most accounts double-count or under-count here. Either Meta calls get attributed to the Google session that happened earlier in the journey, or LSA calls get ignored entirely. Segment by channel at the conversion action level, and accept that some cross-channel overlap is unavoidable.
Your Attribution Window Is Probably Shorter Than Your Sales Cycle
The last common failure: the booked-job event fires into OCI correctly, but the conversion window is set to 7 days and the install booked on day 11. Google Ads receives the conversion, can’t match it to a click inside the window, and drops it. Smart Bidding’s model never learns which keywords produce installs.
Replacement leads in HVAC don’t book on day one. The homeowner gets two more quotes, sleeps on it, talks to a spouse, and books the install the following week. Service calls book same-day. The two need different windows.
- Service / repair conversion action: 7-day click window
- Replacement-lead conversion action: 30-day click window
- Booked-install conversion action: 60–90 day click window (per Google Ads conversion window documentation)
During the lag while the model learns, expect Smart Bidding’s reported CPA to climb before it falls. That’s the bidder waiting for delayed conversions to arrive. Don’t panic-pause campaigns during the relearn. A two-week patience window is reasonable.
The 9-Point Audit Checklist for an Existing Stack
If you’re auditing your own setup or one your agency built, walk this list:
- Is DNI swapping numbers, and does each call record have a GCLID attached?
- Is the qualifying call duration threshold set above 60 seconds?
- Are disposition codes being captured (BOOKED vs. QUOTED_NO_BOOK vs. SPAM)?
- Are call events firing into GA4 with GCLID, duration, and value?
- Are Google Ads conversion actions configured with one Primary and the rest as Secondary?
- Is your dispatch software (ServiceTitan, Housecall Pro, Jobber) storing GCLID on the customer record?
- Is there a webhook firing booked-job events with the GCLID attached?
- Is OCI matching booked jobs back to clicks via GCLID, with a conversion window wider than your sales cycle?
- Is the bid strategy value-based (tROAS or Max Conversion Value), not volume-based (Max Conversions)?
If you can’t say yes to all nine, the gap is somewhere in that list. The earlier the gap in the chain, the more downstream components are broken.
FAQ
What should the qualifying call duration threshold be for HVAC?
90 seconds as a floor for service calls, 120 seconds for replacement-lead calls. The common 60-second default catches the call before the customer has even confirmed their address. The actual booking conversation runs 110–140 seconds, so anything shorter is mostly quote-shoppers, wrong numbers, and people checking if you service their ZIP.
How do I send booked jobs from ServiceTitan back into Google Ads?
You need an event in ServiceTitan that fires when a job moves to Booked status, carrying the original GCLID stored on the customer record. That event hits a middleware layer (Zapier, Make, or custom) that formats the payload for Google Ads Offline Conversion Import. Google matches the GCLID back to the original click and credits the booked job to that ad. Housecall Pro and Jobber both support the same pattern through their APIs and integration partners.
Should I import LSA calls into the same conversion action as Search calls?
No. LSA calls don’t carry GCLID, so they can’t be GCLID-keyed. Use Google’s LSA-to-Google-Ads conversion link to import LSA calls as a separate conversion source, and segment them at the conversion action level. Forcing them into the same action either double-counts or drops them entirely.
Why does my Smart Bidding CPA keep climbing while booked-job revenue is flat?
The algorithm is optimizing toward a noisy signal, usually short calls or form fills that don’t translate to bookings. It’s buying more of what it thinks is converting, but those conversions aren’t producing revenue. Until booked jobs are flowing back via OCI as the Primary conversion action, Smart Bidding has no way to know which clicks produce real money.
What conversion values should I assign to different call types?
Anchor each conversion to gross profit (or LTV-weighted lead value, for replacement leads): roughly $40–$80 for a tune-up, $300–$800 for a service/repair booking, $3,500–$9,000 for a replacement-lead appointment. Flat-value setups force Smart Bidding to maximize the cheaper, more frequent outcome. Differentiated values are the lever that shifts the bidder toward revenue.
How do I handle a booked install that closes 11 days after the click?
Extend the conversion window on the booked-install conversion action to 30–60 days, per Google’s conversion window guidance. The default 7-day window drops anything that books after the homeowner shops around. Expect Smart Bidding’s reported CPA to climb before it falls during the relearn, because the bidder is waiting for delayed conversions to arrive.
If I demote form fills to Secondary, won’t my conversion volume crash?
Your reported volume drops. Your actual revenue per click goes up. Form fills in HVAC convert to booked jobs at a fraction of the rate that calls do, so optimizing toward them is the source of the tire-kicker problem. Demoting them to Secondary keeps the data visible for reporting without letting it drive the bidder. This is the offline conversion tracking pattern that most mature lead-gen stacks settle into.
Build the Stack Once, Then Let Smart Bidding Do Its Job
The six-component stack is a one-time wiring job. Once GCLID flows from click to call to dispatch software to OCI, and once conversion values reflect actual job economics, Smart Bidding has the signal it needs to stop buying $79 tune-up tire-kickers and start buying replacement leads.
The reason most HVAC accounts are still optimizing toward the wrong calls isn’t a Google Ads problem or a CallRail problem. It’s a stack-architecture problem that nobody owns. The agency installed the tool. The dispatch software vendor exposed the data but nobody wired it. The in-house marketer assumes call tracking is on means attribution works. Nothing connects.
If you want a second set of eyes on your setup, book a free strategy call with Elevarus and we’ll map your existing stack against the nine-point audit, identify the missing components, and build a custom paid media plan around the signal Smart Bidding actually needs to see. Bring your CallRail account, your ServiceTitan login, and your Google Ads conversion actions. We’ll find the gap in 30 minutes.