Lead attribution for home services:
from search click to paid invoice.
Rankings are not proof — an invoice is.
Ihor Odariuk builds closed-loop lead attribution for home service businesses — HVAC, plumbing, appliance repair, cleaning — connecting the organic search visit, the landing page, the lead, the completed job and the invoice amount, so an owner can see which page produced which order instead of arguing about which channel deserves credit.
Closed-loop lead attribution means every lead is traced from its first source through to revenue in the CRM. Most service businesses can see website traffic and can see revenue, but nothing joins the two: analytics counts anonymous sessions, the CRM counts named customers, and no shared field connects them. The fix is four links — first-touch source tracking on the visit, lead capture that carries that source, an offline conversion join to the CRM by phone number, and an audit of paid lead spend once the denominator finally exists.
How do you prove SEO ROI to an owner?
Not with a monthly SEO report. That report shows impressions, positions and clicks; the owner looks at the bank account. Nothing in the report explains the bank account, so within a few months it becomes decoration — and marketing is the first budget cut when the year gets tight. Proving return on investment means showing jobs and invoice amounts per channel, in the CRM the owner already trusts.
This is not a reporting-style problem. It is a data problem: the analytics platform stores anonymous sessions, the CRM stores named customers, and there is no shared key between them. The business genuinely cannot answer "which page produced this order" because nothing in the stack ever recorded it.
What the starting position looked like
The client in this case study is a residential appliance repair company operating across eight US metros, running roughly 1,600 jobs a month, buying leads through Google Local Services. On arrival:
- Analytics had recorded zero conversions in its entire history. The key events were setup-wizard templates that matched nothing on the site. Calls and form submissions had never been counted once.
- The ad account was optimising toward a page view. A booking conversion fired on every page load in one metro account, producing 596 phantom conversions. The algorithm was being trained to buy browsers.
- 45% of jobs had no source at all. Dispatchers create jobs by hand and rarely fill the lead-source field, so nearly half the work in the CRM was unattributable to anything.
- The website was credited with 1.4% of monthly jobs — a number nobody trusted, and which nothing in the stack could confirm or refute.
The four links, in the order they have to be built
Each link is useless without the one before it. This is why starting with content or ads, which is what most engagements do, produces work nobody can defend later.
SEO, GEO and AEO: which one actually produced the job?
Search engine optimization (SEO) earns the ranking. Generative engine optimization (GEO) and answer engine optimization (AEO) earn the mention inside an AI answer — ChatGPT, Google AI Overviews and AI Mode, Perplexity, Gemini, Copilot. Most businesses now buy all three and can measure none of them separately, because AI assistants send a visitor with no search query and, in analytics, land in the same bucket as someone who typed the domain from memory.
The first-touch cookie separates them. When a visit arrives with chatgpt.com or perplexity.ai as the referrer, that value is stored and travels with the lead into the CRM, so an AI-assistant referral that becomes a $400 job is visible as exactly that. Alongside it, a server-side log records every AI crawler hit by URL, which distinguishes the two signals people constantly conflate: a bot fetching a page live to compose an answer is not the same as the page being cited, and it is not the same as a human arriving from that answer.
On this client the AI-assistant channel is small but real and growing — and it is now the only channel in the business measured the same way as the rest: source, landing page, job, invoice amount. Businesses investing in AI visibility without that plumbing are buying a channel whose only evidence is a screenshot of a chatbot answering nicely.
What the chain cannot do, said out loud
It cannot tell you which keyword an organic visitor typed. Google removed that in 2011 and no tool has it. What the chain gives per lead is the source and the landing page; which queries feed that page comes from Search Console in aggregate. Paid clicks are the exception — there the click id resolves to the real keyword through the ad platform API.
It also does not tie one specific phone call to one specific visitor unless you pay for dynamic number insertion. A number per channel and logged tel: clicks get you most of the way there for nothing, which is usually the right trade.
Search visibility, month by month
| Month | Search visits | Impressions | CTR |
|---|---|---|---|
| Sept 2025 — baseline | 388 | 6,119 | 6.34% |
| Dec 2025 | 381 | 15,601 | 2.44% |
| Mar 2026 | 431 | 31,747 | 1.36% |
| May 2026 | 569 | 70,224 | 0.81% |
| Jun 2026 | 664 | 92,811 | 0.72% |
| Jul 2026 | 1,098 | 140,641 | 0.78% |
| Aug 2026 | 1,465 | 260,233 | 0.56% |
Source: Google Search Console API. CTR falls as the site starts appearing for thousands of new queries where it ranks below the top positions — the number that matters, actual visits, tripled. This is the one metric no CRM setting, booking widget or ad budget can explain away, which is why it is the one shown here. Client anonymized.
The first thing attribution did was kill my own numbers
Before the chain existed, this engagement looked far more impressive. Jobs credited to the website had gone from 23 to 127 a month. Then the attribution was built, and it took that number apart: the growth was two booking channels switching on, not the website earning work. One was paid — bookings billed through Local Services Ads at full lead price, indistinguishable from organic in the CRM. The other came from a booking form embedded in the company's Google Business Profiles, not from the site at all. Calls to the site's own tracked number had not grown in twelve months.
The same happened to the lead-dispute automation. By the ad platform's lead status it looked like a success. Cross-checking the tool's own list of filed disputes against the API told a different story: 3,614 disputes filed, 14 credited — 0.39%, while leads the tool never touched were credited 8.46% of the time. The platform issues credits automatically by its own models; disputing does not move them. The invoices confirmed it: in the month with 1,284 filed disputes, total credit memos came to $77.89.
Both findings cost me results I would rather have kept. They are on this page because that is the entire point of the work: a measurement system that can only confirm you is not a measurement system. What survived — the search data, the lead-to-invoice chain, the recovered job sources — survived a deliberate attempt to break it.
Every figure here was pulled programmatically from the Search Console API, the CRM job and call-log APIs, and the ad platform's reporting and billing APIs. All of it can be reproduced on request. None of it comes from a dashboard screenshot.
Common questions about lead attribution.
No, and neither can anyone else. Google stopped passing the search term to websites in 2011. What is knowable per lead is the source (organic, paid, AI assistant, direct, referral) and the exact landing page. Which queries bring people to that page comes from Search Console in aggregate. For paid clicks it is different — the gclid resolves to the actual keyword through the Ads API. Anyone promising per-lead organic keywords is selling something that does not exist.
Three ways, cheapest first. One number per channel — a site line, profile lines, paid lines — proves the channel without any software. A click on a tel: link is logged with its source and page, which proves intent from a specific page. Dynamic number insertion is the only method that ties one specific call to one specific visitor, and it costs money per number. Most businesses do not need the third one to make better decisions.
That is the normal case, not the exception — in this project 45% of jobs had an empty source field. The join runs on the phone number instead: the lead log stores a normalized 10-digit key at the moment of submission, and the CRM is matched on it afterwards. The dispatcher's workflow does not change at all, and the attribution still holds retroactively.
No. The work sits on top of what already exists — WordPress and Housecall Pro in this case. The pieces are a first-touch cookie, a hidden field in existing forms, a server-side log file, and read-only API access to the CRM and ad accounts. Nothing about how the team books jobs changes.
The tracking itself is live within a week and starts collecting immediately, though it is not retroactive — it measures from the day it goes in. Historical attribution can often be rebuilt separately from call logs, which is how the 2026 job history in this project was recovered. Content and ranking effects run on their own timeline, typically one to three months before revenue moves.
Both, and that is the point. SEO without attribution produces rankings nobody can connect to revenue, which is why marketing budgets get cut first in a downturn. Attribution without SEO measures a channel that is not growing. The sequence that works is: make the channel measurable, then grow it, then prove what the growth was worth in the CRM.
By referrer, captured on the first visit and carried into the lead record. A visitor arriving from chatgpt.com or perplexity.ai has no search query attached, so default analytics files them as direct traffic and the channel looks like it does not exist. Storing the referrer in a first-touch cookie makes AI-assistant visits countable, and joining that cookie to the CRM makes them countable in dollars. Separately, a server-side log records which URLs AI crawlers fetch, which is a useful early signal but is not the same thing as being cited or as a human actually arriving.
SEO earns a ranking in classic search results. GEO, generative engine optimization, earns a mention inside AI-generated answers such as ChatGPT, Perplexity, Gemini and Google AI Mode. AEO, answer engine optimization, is the overlapping practice of structuring content so a machine can lift a direct answer from it — self-contained paragraphs, real tables, genuine FAQs, clean schema. For a local service business the same underlying assets serve all three, so the practical question is not which to buy, but whether you can tell them apart afterwards. Without attribution you cannot, and every claim about AI visibility stays a screenshot rather than a number.
Find out what your website is actually worth.
If your CRM cannot tell you which orders came from search, that is the first thing to fix — before any content, before any ad budget. I build the chain, then grow the channel it measures.