SEO
Written on 19/9/2026
Updated on 19/9/2026
3min

SEO ROI: the three assumptions nobody measures

Thibaut Legrand
Thibaut Legrand
Co-founder - Vydera
SEO ROI calculation assumptions measured Vydera
Table of contents

Your SEO ROI, with its real bounds

Vydera measures your assumptions before pricing them.

Talk to an expert

Key takeaways

  • Of 338 real queries submitted to a volume tool, 294 come back with no declared volume, that is 87%. Another 90 could not even be submitted, too long or outside the character set
  • Caveat published as measured: 229 of those 294 are variants around a third-party brand name. Strip that block out and 65 queries still have no declared volume against 44 that do
  • No CTR curve is publishable from this property: excluding the brand and 7 excluded pages, 1,918 impressions and 48 clicks remain across positions 1 to 10, and the relationship is not monotonic
  • Across 53 pages tracked for four months, monthly traffic varies by a factor of 7 at the median, and 94% vary at least twofold. With a floor of 10 impressions per month, n = 20, the median ratio drops to 3.94, and the de-trended ratio confirms it at 3.77
  • Search Console attributes only 39.5% of site impressions to a query. That is the error floor of any keyword-level analysis, on our property and on yours

A CFO asks what SEO actually returns. You open a spreadsheet and lay out four cells: search volume, CTR at the target position, conversion rate, value of a customer. You multiply. You produce a number.

That number is wrong, and not by a little. We wanted to know by how much. We took the Search Console of vydera.com and tried to measure the first three inputs on our own property, under one rule: write nothing we had not recorded.

None of the three holds. And the weakest is not the one you would expect. It is not the conversion rate, which everybody knows is rough. It is search volume, the cell nobody ever argues about.

The dataset, and the error floor you have to state first

Window: 27 January to 25 August 2026, that is 211 days and six complete calendar months. 1,371 clicks, 109,907 impressions, 1.25% overall CTR. We would have liked twelve months; the property does not have them.

Before any query-level figure, state this: Search Console attributes only 39.5% of site impressions to a query, 43,416 out of 109,907, and 30% of clicks, 411 out of 1,371. The privacy threshold removes the rest. Everything that follows at query level therefore rests on 39.5% of the property. That is the error floor of any keyword-level analysis, ours and yours alike.

A second, less familiar methodological point. The sum of impressions by page, 114,960, exceeds the total by date, 109,907. This is not double counting: when two URLs of the site surface on the same query, the date dimension counts one impression and the page dimension counts two. Query-level sums, by contrast, stay comfortably under the total.

The three assumptions, measured on vydera.com

Assumption 1 · Volume: the tool does not know 87% of the queries that bring us impressions

Everybody runs the same check, in the same direction: take the keyword list a volume tool produced, then look at where the site ranks on it. We ran it. Of the 154 keywords pulled to build the editorial strategy, only 7 appear as exact matches in Search Console, and just one at an average position under 10.

That result measures nothing. At n = 7, it is not an estimation gap, it is the observation that a young domain does not rank on the keywords used to build it. The direction of the join is the problem.

So we reversed it. Start from the queries that actually bring impressions, then ask the tool for their volume. 499 queries with at least 10 impressions over the window, Vydera brand queries excluded, of which 428 fall in the two markets tested, France and the United States. Two surprises.

90 of them could not even be submitted. The Keyword Planner refuses anything past 80 characters, past 10 words, or outside its character set. Those 90 queries carry 2,566 impressions. A format rejection is not a zero volume: it is an absence of measurement, and it shows up nowhere in a spreadsheet.

Of the remaining 338, 294 come back with no declared volume at all, that is 87% of submitted queries. Only 10% of the 428 candidates have a volume in the tool.

The weight falls on the wrong side. The 294 without volume carry 17,614 impressions, the 44 with volume carry 1,760. Against the whole site, queries a volume tool declares anything about account for 1.6% of impressions, 4.1% of query-attributable impressions, 8.0% of the candidate set. Adding back the Vydera brand queries, excluded from the set, would add 759 impressions: it does not move the first figure by a point.

The caveat that stops us overselling this

229 of the 294 queries with no declared volume are variants around a competing tool name, and they carry 15,244 of the group's 17,614 impressions, for zero clicks. A volume tool has no reason to know a young brand: on that block, the missing volume is expected, not revealing.

So strip the block out and look at what is left. Excluding those 229, 65 queries still come back with no declared volume against 44 that do, carrying 2,370 impressions against 1,760. The gap drops from tenfold to one and a half. It still points the same way, and it is still uncomfortable: even after removing everything that looks like brand noise, most of the queries keeping the site alive are invisible to the tool used to pick its topics.

The profile of the two groups reads without interpretation. Among the 294 with no volume: 58 contain the operator "or", 137 run to at least six words, and their average CTR is 0.01%. Among the 44 with volume: zero "or", two at six words or more, average CTR 0.68%.

That shape looks like generative query fan-out. We write it as a reading, not as a measurement: the shape of the queries is measured, their origin is not. Search Console does not say who typed what.

The only place where a volume comparison is honest

Comparing impressions to a declared volume only makes sense on the days the site sits on page 1 in the country concerned. Anywhere else you are comparing demand against visibility that does not exist. Google Ads volumes are also national and per language, whereas a site's impressions are worldwide: each query was therefore attached to its dominant country and compared on that country alone.

Apply both constraints and nine queries remain. All nine are underestimated by the tool, none overestimated, with a median ratio of 4.86, a first quartile at 3.04 and a third at 5.65.

That figure does not travel alone. All nine sit at 10 searches per month, the Keyword Planner floor. A ratio of 3 to 7 against a denominator rounded down is arithmetic, not a discovery. It does not say the tool underestimates demand fivefold. It says this property has not one mid or high volume query on which to check anything.

Assumption 2 · CTR: we tried to produce a curve, and could not

Second cell in the spreadsheet. We grouped query x page x day rows by rounded average position, weighting CTR by impressions. First result, all pages included: 3.43% at position 1, 0.97% at position 2, 0.52% at position 3, 0.15% at position 10.

Those numbers are meaningless as a CTR curve, and it is better to say why than to smooth them. Seven pages of the site accumulate heavy impressions and near-zero CTR. The rule removing them is arithmetic and declared in advance: at least 1,000 impressions and CTR under 0.5%. One of them alone carries 72,050 impressions for 16 clicks, that is 66% of the site's impressions.

The rule also catches a glossary entry at average position 29.6, which is nothing like a fan-out page. That is deliberate: we name the rule, not the interpretation. An exclusion picked page by page after seeing the result is no longer a measurement.

With those seven pages removed, the curve reads 13.54% at position 1, 29.91% at position 2, 19.65% at position 3, then falls to 4.67% at position 4. Position 2 is almost double position 1. The relationship is not monotonic.

The explanation is measured, not assumed. The brand query holds 1,415 of the 1,588 impressions at position 1 and 206 of the 215 clicks. On its own it gives 14.56% at position 1, 34.70% at position 2 and 35.29% at position 3. That is a composition effect: when people search a brand, they click wherever it sits.

Remove the brand and nothing publishable is left. 1,918 impressions and 48 clicks across positions 1 to 10, of which 173 impressions and 9 clicks at position 1. One click either way moves that point by more than half a CTR point.

One last warning, the one rank trackers keep quiet about: a rounded average position is not a position. A row at 3.5 can hide a 1 and a 6. Restrict the calculation to rows whose average position falls within 0.1 rank of an integer and position 1 drops from 13.54% to 12.50%, position 3 from 19.65% to 9.20%. That is the scale of the distortion, on the same dataset.

Direct consequence: our calculator hard-codes no CTR curve. Not ours, which rests on 173 impressions at position 1, and not a market curve, which no single property can establish. CTR is a user input there, exactly like the conversion rate. If you reuse a published curve, label it as third-party, and remember you know neither its brand composition nor which pages its author removed.

Assumption 3 · Stability: a factor of 4 from one month to the next

Third input, and the only one of the three we managed to measure cleanly. Not at query level: anonymisation empties that level, and a single query survives all six complete months. At page level it holds.

From April to July 2026, 53 pages are present in all four months. The ratio between their best and their worst month is 7.0 at the median, and 94% of them vary at least twofold. Impose a floor of 10 impressions per month and 20 pages remain, with a median ratio of 3.94 and 85% varying at least twofold.

A fair objection: on a property going from 493 to more than 6,000 monthly impressions, a raw ratio measures growth as much as variability. So we redid the calculation as a share, each page's share of site impressions. Median 3.77 against 3.94 raw on the same sample, and 90% varying at least twofold. The two methods agree: the variability is not an artefact of growth.

A word on the base of that share. It removes the seven excluded pages, because the raw site total is itself crushed by the May spike, 57,369 impressions almost all of it from a single page. Against that total, shares produced absurd ratios, up to 131. The 20-page set itself holds every page present in all four months, excluded ones included: it is the base of the ratio that removes them, not the sample.

Direct consequence for an ROI calculation: monthly revenue computed on one given month is off by a factor of 4 at the median the following month. An ROI presented as a number is wrong before the quarter closes. Presented as a range, it holds.

The calculator: four assumptions, each as a range

Hence its shape. Every input is entered as a low and a high. The output is a range, with the ratio between its two bounds, and a bar saying which assumption widens it most. That is the only actionable piece: it tells you which one to tighten first.

SEO ROI calculator: the output is a range, not a number

Four assumptions, each as a range. Nothing is pre-filled.

Three choices are worth explaining.

  • Nothing is pre-filled. Offering a default CTR or conversion rate would mean inventing them, and you would keep them. We have measured neither on your side.
  • No payback period in the output. It would require a measured time-to-rank, and our property has too little history to produce one. Better to show nothing than to show a comfortable figure.
  • The "monthly variability" checkbox applies 3.94, the median measured above, split as a square root either side of your range. It applies to the result, not to the volume cell: 3.94 measures observed monthly impressions, not the uncertainty of a declared volume. The two are not the same thing.

The method, to rerun it on your own property

  1. Export Search Console as query x page x day, over the longest window available, with the country dimension. One dimension at a time is not enough: aggregated average positions flatten everything.
  2. Measure your attribution rate first: sum of impressions by query divided by the total by date. If you get 40%, that is your error floor, and it goes in before the conclusions.
  3. Remove your outlier pages with an arithmetic rule, written before you look at the result. Ours: at least 1,000 impressions and CTR under 0.5%.
  4. Run the join to the volume tool in the opposite direction to habit, from real queries to the tool, never from the tool's keywords to the site. Count format rejections separately: they are not zeros.
  5. Only compare impressions to volume on days spent on page 1, in the query's dominant country, and publish that country's share query by query.
  6. Measure variability at page level, raw and as a share, and publish both. If they diverge sharply, you are measuring growth, not variability.

Two checks we impose on ourselves, and recommend. A control query recounted from three independent pulls: 14 clicks and 101 impressions in all three, against 14 and 100 in a snapshot taken on a slightly different rolling window. And a partition check: the three published curves recompose exactly, zero deviation position by position, 400 cumulative clicks against 402 in the source. A curve exceeding its source is a join bug, not a discovery.

One budget detail: the volume pull cost 0.73 USD for two calls announced at 0.09 USD each. Check your balance, not the cost line in the response.

What this dataset does not say

The most useful part of a data article is its list of holes. Here is ours, in full.

  • 60.5% of site impressions are attributed to no query at all. It is the largest unmeasured quantity in the dataset.
  • Conversion rate, average order value and margin. No analytics or CRM data is wired into this measurement. That is why they are inputs, not constants.
  • Time to rank, and therefore payback period. The property has too little history to produce it.
  • Seasonality. Six complete calendar months, no annual cycle observable.
  • CTR by SERP type: AI Overview, local pack, images, sitelinks. Search Console does not expose it.
  • The real origin of the 294 queries with no declared volume. Their shape is measured, their provenance is not.
  • The volume of the 90 queries the tool rejected. A format rejection is not a zero.

What goes in the slide

A range, its two bounds, and the list of assumptions producing it, each with its source. A CFO never objects to a range. They object to a number that collapses in the second quarter.

Three sentences worth keeping verbatim. Declared volume covers only a fraction of the queries actually bringing you impressions, and you can check that on your own property in an afternoon. No CTR curve from a single property deserves to be hard-coded. And the month you are presenting varies by a factor of 4 against the next one.

To sort what belongs in reporting from what does not, we went through the SEO KPIs worth deciding on. On the levers that actually move positions, our internal linking method gives the measured thresholds. And for the definitions: organic traffic and query fan-out.

If you want this dataset produced on your property, with the list of your queries that volume tools cannot see, that is exactly what our audit delivers: let's talk.

  • How do you calculate SEO ROI?

    Search volume times CTR at the target position, times conversion rate, times the value of a conversion, minus cost. The formula is not the problem: its first three inputs are estimates, not measurements. Enter each as a range and output a range. An SEO ROI expressed as a single number is wrong by the following month.

  • Can you trust the search volume tools report?

    To pick a topic, yes. To price revenue, no. On our own Search Console, 294 of the 338 real queries submitted to the Keyword Planner come back with no declared volume, and another 90 could not even be submitted. Queries the tool declares a volume for account for 1.6% of the site's impressions.

  • Which CTR by position curve should you use?

    None, without knowing how it was produced. On our property, position 1 moves from 3.43% to 13.54% depending on whether seven pages are removed, and position 2 is almost double position 1 because of the brand query. Excluding the brand, 173 impressions remain at position 1: far too few to publish anything.

  • Over how many months should SEO ROI be calculated?

    Never over one month. Across 53 pages tracked for four consecutive months, the ratio between the best and the worst month is 7.0 at the median and 94% of pages vary at least twofold. A rolling average over the longest window you have, with the bounds shown, is the minimum defensible in front of a CFO.

  • What conversion rate should you use as a default?

    Yours, or none. Our calculator offers no default value on that field, nor on CTR: we have measured neither on your side, and a suggested value becomes a kept value. If you do not have the data yet, enter a wide range and watch how much it widens the output.

  • How do you justify an SEO budget without promising a number?

    By presenting a range, its two bounds, and the source of every assumption producing it. Then by naming the one that weighs most on the width, with the plan to tighten it: instrument conversion, record real CTR per page, rerun the query join three months later. A range that narrows quarter after quarter convinces more than a number.


Thibaut Legrand
Thibaut Legrand
Co-founder - Vydera