SEO attribution: how to build one number when two systems disagree
SEO attribution breaks because Search Console and analytics do not share a key. Chain four ratios that each live inside one system, record the gap between them as a constant, and report the inputs with the number.

SEO attribution fails because the two systems you have do not share a key. Search Console knows searches and pages but has no sessions and no money; analytics knows sessions and money but has no searches. This chapter builds one number anyway — by chaining ratios that each live inside a single system, and by writing down the gap between them instead of explaining it away.
Read this first
You need at least 28 days of data in both systems for the same set of pages, and one conversion event you already trust. If the event is new, wait a month before doing any of this; an attribution chain built on a metric that was still being debugged produces a number nobody will defend later.
This chapter teaches the manual calculation. QueryWin does not compute this for you and is not being built to — the arithmetic is easy, the judgement calls are not, and the judgement calls are the whole job.
Why the two systems cannot simply be joined
A click in Search Console and a session in analytics are different events, counted by different code, with different filtering. One is recorded when a result is clicked; the other when a page loads and a script runs. Between those two moments sit consent banners, script blockers, prefetching, redirects and people who leave before the page finishes.
There is also an aggregation difference inside Search Console itself, and it is documented. From the performance report help page, read 2026-08-20: "Data grouped by Queries, Countries, Devices, or Dates is aggregated by property. Data grouped by Pages or Search appearance is aggregated by page." The same page adds: "The chart totals can sometimes differ from the table totals."
That means two of your own numbers, pulled from the same report on the same day, are allowed to disagree — for a documented reason. So the goal is not reconciliation.
Do not reconcile the two systems. Measure each step inside one of them, and record the gap between them as a constant you watch.
The seo attribution worksheet
Six rows. Each row names the system it comes from, and no row crosses systems except row four, which exists precisely to measure the crossing.
| Step | System | What you record |
|---|---|---|
| 1 | Search Console | Impressions for your page set, fixed 28-day window |
| 2 | Search Console | Clicks for the same page set, same window |
| 3 | Analytics | Organic search sessions landing on those same URLs |
| 4 | Both | Carry-through = sessions ÷ clicks, as a ratio |
| 5 | Analytics | Conversion rate for those sessions, one event only |
| 6 | You | Value per conversion, and where the figure came from |
The number is then clicks × carry-through × conversion rate × value per conversion, reported together with the window and all four inputs. Never report the product alone. A single figure with no constants attached is the thing that gets quoted back at you in six months when every input has moved.
Row four is the important one
Carry-through is the ratio between what Search Console says arrived and what analytics says arrived. Its absolute value is not very interesting — it depends on your consent setup, your audience's blockers and your redirects. What matters is that it should be roughly stable from period to period.
When carry-through moves sharply between two windows, something in the measurement changed, not something in the world. A consent banner rollout, a tag migration, a new redirect. Treat a large move as a signal to stop and find the change, not as a result to explain.
Row six is a decision, not a measurement
If you have revenue per conversion, use it. If you do not — most sign-up, demo and lead events — pick a value, write down how you picked it, and keep it fixed across periods. An invented constant that stays constant still lets you compare two periods. An invented constant you quietly revise makes every comparison meaningless, and it is very easy to revise it in the direction you were hoping for.
Where the AI side goes
It goes on a separate line, with its own denominator, and it does not get added into the number above.
Two reasons, both concrete. Search Console's reporting on AI surfaces is page-level and does not give you the same fields, which is covered in what the generative AI report answers and what it does not. And a large share of visits that came from an AI answer arrive without a referrer and land in the direct bucket, which is the subject of pulling AI referrals out of the GA4 direct bucket.
So the honest presentation is two lines and one sentence: the attributed number, the partially-attributed AI line, and an explicit statement of how much of your traffic you could not assign to either. That last sentence is the one that makes the first two credible.
Write the unassigned share as a proportion of sessions, not as a footnote. "Of the sessions in this window, this share arrived with no referrer and no campaign, and we did not attempt to attribute them" is a sentence a finance team can work with. A footnote saying attribution is imperfect is a sentence nobody reads, and it does not stop the composite number from being treated as complete.
The temptation you are resisting here is to model the unassigned share — to assume a split and fold it in. That converts an honest gap into a number with a decimal point, and the decimal point is what makes people stop asking about it.
Doing it, in order
Seven steps, and the order is doing real work: every one of them fixes a choice that would otherwise be made differently next month. Fix the window before the pages, the pages before the pulls, and the carry-through before you have seen the conversion rate — because knowing the answer changes how forgiving you are about the inputs.
- Fix the window. 28 days, ending at least three days ago so both systems have finished processing.
- Fix the page set. A list of URLs, saved in the sheet, not a folder pattern you might re-interpret next quarter.
- Pull rows one and two from Search Console with the page filter, not the search-term filter, so the aggregation stays page-based throughout.
- Pull row three from analytics with the same URL list and the organic search channel only.
- Compute carry-through and write it down before looking at anything else.
- Pull the conversion rate for exactly those sessions, then apply your fixed value.
- Write the four inputs, the window, and the resulting number in one row of a sheet, and never edit past rows.
Step seven is the whole discipline. The value of this exercise appears on the fourth or fifth repetition, when you have a series, and a series only exists if nobody went back and improved the earlier entries.
Three ways the number goes wrong
None of these throw an error. Each one produces a plausible figure with a defect built into it, and the defect only becomes visible when someone asks why last quarter looked different.
- Mismatched windows. 28 days in one system and 30 in the other produces a carry-through that drifts for no reason. Both windows must be the same days, not the same length.
- Default channel grouping. If you take "organic" from the default grouping without checking what falls into direct, the AI-driven part of your traffic is already excluded and you will not know by how much.
- A value per conversion that follows the mood. Raising it after a bad quarter is not analysis. Fix it once, in writing, with the reasoning.
What this cannot tell you
It cannot tell you causation. This produces a consistent, auditable number, and consistency is not the same as truth — every input still carries the biases of the system it came from, and chaining four of them multiplies those biases rather than cancelling them.
We also cannot validate any of this against server logs, and neither can most people running it. Without logs there is no third source to arbitrate when Search Console and analytics disagree, so carry-through stays a black box that you monitor rather than a quantity you understand.
And this stops working entirely below a certain volume. If your page set gets a few hundred impressions a month, the conversion rate in row five is a handful of events, and multiplying four noisy ratios together will produce swings that look like performance. Under roughly a thousand clicks in the window, use the raw click and conversion counts, and skip the composite number altogether.
What the number is for is comparison against your own previous rows — the same discipline as the shorter check in the 14-day check, at a longer horizon and with money attached. Making that comparison something you do not assemble by hand is what QueryWin is being built to do.
Common questions
Why do Search Console clicks and analytics sessions never match?
They count different events at different moments with different filters, and Google documents that even two views inside Search Console can disagree because of how they aggregate. Stop trying to make them equal and start tracking the ratio.
Which number should I report to a client or a boss?
The composite one, with the window and all four inputs printed next to it, plus the separate AI line and the unassigned share. A number without its inputs invites the question you least want, which is "where did that come from".
Can I use last-click attribution instead?
You can, and for a single-channel site it changes little. The reason this chapter avoids naming a model is that the failure here is upstream of the model: the two systems disagree before any attribution model is applied.
How often should I run this?
Monthly, on a fixed schedule, with the window ending the same number of days before you run it. Running it when something looks interesting produces a series shaped like your curiosity.
Part of the QueryWin handbook · Level 3


