How we compute decay and intent, threshold by threshold
Every constant behind our decay and intent flags: 20 percent clicks, 100 impressions, 5 clicks, the keyword lists, and where they are weakest.
A page gets flagged as decaying when it lost at least 20 percent of its clicks across two adjacent 28-day windows, and the earlier window earned at least 100 impressions and at least 5 clicks. A query gets its intent from a keyword list with a fixed precedence order. Those are the real numbers, not a description of them.
Below is every constant behind both judgments, and the three places ours are weaker than a threshold usually looks: one that exists only to replace an accident, one nobody can validate against a published figure, and one list the code declares and never reads.
TL;DR:
- Decay is clicks down 20 percent or more across two adjacent 28-day windows ending three days back, with at least 100 impressions and 5 clicks in the earlier one. Ranked by absolute clicks lost, five kept per run.
- The impression bar is higher than the click bar (30 percent against 20). Impressions are noisier, so the signal that fires first has to move further than the one it warns about.
- The 5-click floor is not a tuned parameter. It replaced a damping effect that the old overlapping windows had been supplying by accident.
- Intent is a keyword match with precedence, and informational is the default arm rather than a detection. The classifier carries a list of informational keywords it never consults.
What counts as a decaying page?
A page decays when its clicks fell by at least 20 percent between two adjacent 28-day windows, and the earlier of those windows earned at least 100 impressions and at least 5 real clicks. Both windows read the stored daily data, end three days back, and never overlap each other.
click decline >= 20%
prior impressions >= 100
prior clicks >= 5
window 28 days, adjacent, non-overlapping
window ends 3 days back
ranked by absolute clicks lost
kept per run top 5
Three labels ride on top of that row, and each one changes the recommended move. A page is structural when its average position also fell by 2 or more, which separates a page losing rank from a page holding rank and losing clicks. It is recoverable when impressions fell while the click rate held or improved: the snippet still converts the people who see it, so the page lost visibility rather than appeal, and the content is the thing to change rather than the title. It is persistent when the window before this one also decayed, which needs three consecutive windows, or 84 days of stored daily data, before it can be computed at all.
One edge case is worth naming because it looks like a bug and is not. A page that disappeared from the current window entirely keeps its last known position rather than being assigned a fake one, so it never reads as structural. The 100 percent click loss already carries the severity, and inventing a position to make the label fire would double-count it. If you want the same comparison run by hand instead, content decay detection walks the window discipline without the constants.
Why is the impression bar higher than the click bar?
Because impressions are noisier than clicks. An impression drop has to reach 30 percent before it counts, against 20 percent for clicks. That is deliberately backwards from how an early warning usually works: the signal designed to fire first is held to a stricter bar than the one it is warning about.
The reasoning is that an impression is not a human decision. It moves when Google reshuffles a results page, when the query mix behind a page shifts, when a SERP feature appears above you, and when seasonal demand fades, all without your ranking changing at all. A click is somebody choosing you. So the earlier signal is also the less reliable one, and setting both bars at 20 percent would have produced a warning queue that fires constantly and means little. Breadth is the other half of that read: a batch of pages sliding together is usually one update re-scoring the site rather than pages rotting individually.
Why does a five-click floor exist at all?
Because the window arithmetic changed and the floor had to become explicit to replace something that used to happen by accident. The detector once compared consecutive weekly snapshots, which overlapped by roughly 75 percent. That shared span damped small drops as a side effect, so low-traffic pages rarely cleared the decline bar.
Adjacent, non-overlapping windows are the correct comparison, and they are noisier. When the overlap went away, the buckets filled with pages that went from one click to zero, which is a 100 percent decline and no information at all. Nothing was wrong with the new arithmetic. The old one had been suppressing that noise as a consequence of being wrong, and the suppression turned out to be load-bearing without anyone having decided it should be.
So the 5 is not fitted to anything. It is a correction restoring what a bug used to provide, set at a level low enough that any real site's genuine drops sit far above it. That is the honest provenance of the number, and it is the sort of thing that stays invisible when a tool reports which pages are losing clicks without saying how it decided.
Read your own Search Console, not just an essay about it.
QueryScope brings your real Search Console data into Claude Code or Cursor, so your agent reads it for you. From $14.99/month.
Where does the three-day lag come from?
From us, not from Google. Both windows end three days before today so they sit on data that has stopped moving. Google documents that recent data is provisional, saying "the newest data can be preliminary, meaning it's still being collected and might change in the next few hours," [1] but it publishes no figure for when a given day is finished.
That leaves nothing to validate three days against. It is a judgment call: long enough that a filed issue is not reacting to a day that has not finished arriving, short enough that the flag is still about the present. The site's headline numbers use a one-day lag instead, on the reasoning that a glance can afford to be provisional and a filed issue cannot. Two different lags on the same data, chosen by what the number is for rather than by a published settle time.
How does a query get an intent label?
By keyword match with a fixed precedence. The classifier lowercases the query, splits it into words, then tests three sets in order: transactional, then commercial, then navigational. First match wins and testing stops. Single words match whole words, while multi-word phrases match as substrings.
- Transactional tokens include buy, purchase, order, price, pricing, cost, cheap, deal, coupon, discount, free, trial, demo, download, signup, subscribe, hire, and quote, plus the phrases "how much", "sign up", "for sale", and "free trial".
- Commercial tokens include best, top, review, vs, versus, comparison, compare, alternative, software, tool, service, and platform, plus the phrase "near me".
- Navigational tokens are login, dashboard, and account, plus "log in", "sign in", and "official site".
Precedence decides more than the lists do. A query like "best free crm" carries a commercial word (best) and a transactional one (free), transactional is tested first, so it grades transactional and nothing records that the query was mixed. The whole-word rule is the deliberate part: "best" does not fire on "bestseller" and "free" does not fire on "freelance". What the label deliberately does not carry is whether that searcher is worth anything, because buying quality is a separate grader with its own token lists, and a free-seeker and a buyer both score transactional here.
Why is informational always the biggest bucket?
Because it is the fall-through, not a detection. Transactional, commercial and navigational each get a test. Anything matching none of them returns informational by default, so there is no positive test for an informational query anywhere in the classification path.
The file does contain a list of informational keywords: how, what, why, guide, tutorial, meaning, definition, examples, tips, explained, plus the phrases "what is" and "how to". That list is never read. The default arm catches those queries before anything could consult it, so the constant is declared in the file and referenced nowhere in the codebase. The behavior is identical either way, which is exactly why it survived: a "how to" query with no buying signal lands informational whether the list is consulted or not.
What it means is that the informational count is precisely "everything else", and it should be read that way. In the 30-day report on a live SaaS, 514 of 662 named queries came back informational. That number is accurate. It is not evidence that 78 percent of the demand is research-shaped, because it is 78 percent of named queries carrying no buying, comparison, or brand-navigation token, which is a different claim and a weaker one.
What these numbers are not
None of them is a measurement. Every threshold above is a judgment about where noise ends, and not one was fitted to an outcome, because there is no labelled set of genuinely-decaying pages to fit against. They are defensible, they are consistent, and a different team would reasonably pick different ones.
Two limits sit under the whole set. The intent classifier reads strings and nothing else, so it cannot see that a query's results page is full of product listings, which is the strongest real signal of commercial intent and the one that would improve the classification most. And the counts it produces come from named queries only, which under-report by design, so an intent mix is a direction rather than a statistic. The other half of this discipline is measuring whether the flags were right at all, which is what 32 marked fixes, wins and misses reports. If you would rather read these thresholds firing against your own data than take our word for the numbers, that is what Search Console in the terminal does.
Sources
- Source: QueryScope's own
GscSnapshotDiff(decay windows, thresholds, structural and recoverable labels) andQueryIntent(token lists, precedence, default arm), read on 2026-08-11. Constants quoted as they run in production on that date. - [1] Google Search Console Help, Performance report (newest data can be preliminary and may change within hours; no published finalization time).
- Site figures: AppScreenshotStudio's Search Console, read through QueryScope, as published in the 28-day report through 2026-06-29.
Read your Search Console where you code.
Ask your coding agent how your site is doing. QueryScope reads your real Search Console data in the terminal: clicks, queries, intent, and indexing. From $14.99/month. One to ten sites.