The site was commissioning its own worst pages
Gematria.Today was earning impressions for archaic dictionary words (dull-pated, filamentule, gauping) and no clicks at all. The cause was not a crawler finding pages it shouldn’t. It was a loop in the site’s own code that manufactured the evidence of demand those pages needed to get indexed, once a day, every day.
The symptom
What the numbers said
Three months of Search Console data for a site a few months old. Low volume, which is normal at this stage. One number is not normal, and it is the one that matters.
Average position 15.1 puts the site on the second page, where click-through is negligible whatever the snippet says. That rules out the usual first move: title and meta-description rewriting is worthless here, because almost nobody is seeing the snippets. Rank is the binding constraint.
The genuinely diagnostic figure is buried in the query breakdown. Every one of the top eight queries by impressions returned zero clicks. All ten clicks came from queries below them.
Sorted by impressions, the top of the list splits cleanly in two. Five terms are archaic English words someone was looking up in a dictionary. Three are people asking how gematria works, which is precisely what the site is for.
Top queries by impressions · 3 months to 6 Aug 2026
| Query | Impressions | Impr. | Clicks | What the searcher wanted |
|---|---|---|---|---|
| dull-pated | 16 | 0 | A definition | |
| gematria blog | 9 | 0 | Our content | |
| filamentule | 7 | 0 | A definition | |
| gauping | 6 | 0 | A definition | |
| well-affectedness | 6 | 0 | A definition | |
| chronogrammatic | 6 | 0 | A definition | |
| how to use gematria | 6 | 0 | Instructions | |
| gematria calculator how to use | 5 | 0 | Instructions |
Two findings, not one: something is publishing dictionary pages we never wrote, and nothing is answering the question our actual audience is asking.
The finding
Where the dictionary pages came from
The site generates a page for every word in its database: /w/light gives the word’s
gematria value and lists every other word sharing it. There are tens of thousands of rows, so publishing all
of them would be exactly the mass of thin pages that Google’s helpful-content signals exist to catch.
A guard against that already existed in the code. Only words somebody had actually looked up were
offered to search engines: in SQL, search_count > 0. Reasonable rule. It did not hold,
because the site was supplying the lookups itself.
The loop, and where it was cut
Two further callers fed the same loop. A single search fanned out into a database write for every related word the dictionary API returned, registering a dozen searches the visitor never made. And the site’s own definition pages turned every long word in a definition into another one of those calculator links, so crawling one definition seeded a page for each word inside it.
The corroboration
The date stamp that confirmed it
A mechanism you can describe is a hypothesis. What made it a finding was the timing, and the timing came from version control rather than from the analytics.
The generated word pages and their sitemap were committed on 27 July. Impressions had been flat at a handful a day for two and a half months. They stepped up two to four days later, the ordinary lag between submitting a sitemap and Google working through it. This is not a site that started growing. It is a site that started being crawled somewhere new.
Daily impressions · 14 May to 6 Aug 2026
A second leak, found the same way
Reading the surrounding code turned up a route nobody had flagged. The site’s definition pages (/definition?word=filamentule) were serving fully indexable HTML: titled
Definition: filamentule, canonical to themselves, carrying no robots
directive at all, and with a body consisting of a third-party dictionary’s text reproduced
verbatim. The home page linked a fresh one every day.
For a query like filamentule, that page is a closer match than the gematria page it was assumed to be. Some share of the leaked impressions was almost certainly this route: a page that would never have surfaced in a crawl-based audit, because from the outside it looks like a perfectly ordinary content page.
The change
What shipped
Four changes, in one reviewed pull request. The first two close the loop; the third stops the republishing; the fourth serves the demand that was going unanswered.
- The lookup no longer counts as demand when nobody asked for it. Page-load lookups declare themselves, return the value as before, and neither create a row nor increment one. Applied to the query prefill, the name prefill, and the related-word fan-out.
- The indexing gate now asks for demand and substance. A word page needs repeated searches and enough words sharing its value to be a genuine list rather than a lone letter sum. Both conditions are applied in one shared definition, used by the page and the sitemap alike.
- Definition pages are out of the index. Delivered as a meta tag and an HTTP header, and deliberately without a robots.txt block: a blocked page cannot be re-read, so blocking it would have frozen every existing URL in place rather than removing it.
- A real answer to the on-topic queries. A guide covering what the queries actually ask, including the part competitors leave out: the arithmetic reasons most gematria “matches” are inevitable rather than meaningful.
Why a threshold, and not simply hiding the pages
Blanket removal was tempting: at ten clicks a quarter there is nothing to lose. It was the wrong call, and the reason is worth stating because it is the kind of judgment the numbers alone don’t make.
| Option | Stops the leak | Keeps what’s differentiated | Cost |
|---|---|---|---|
| Hide every generated page | Yes | No | Throws away the value pages, which aggregate data no dictionary holds and match on-topic intent |
| Write real content for all of them | Yes | Yes | Not viable across tens of thousands of pages: there is no source of substance beyond a letter sum |
| Raise the threshold Chosen | Yes | Yes | Some currently-indexed pages drop out; the exact count is only knowable from the live database |
The call
Recorded before deployment
Written on the day the change merged, with the baseline fixed and the expected outcome stated in advance, including the part that will look like a failure.
- EXPECT Total impressions will fall, probably sharply. The leaked dictionary terms were a large share of the 512. Removing them is the intended effect. Any report treating an impression decline here as a regression has misread the objective.
- EXPECT CTR will rise as impressions fall, because the denominator was inflated by queries the site was never going to satisfy. The interesting figure is clicks, not ratio.
- TARGET The three on-topic queries move off page two. Baseline for how to use gematria, gematria calculator how to use and gematria blog: 20 impressions, 0 clicks, at an average position of 15.1 sitewide. That is the number to beat.
- TIMING Weeks, not days. Every affected URL has to be recrawled before the directive is seen. Sitemap output is cached for six hours; recrawl is on Google’s schedule, not ours.
- FALSIFIES If the dictionary terms are still drawing impressions in six weeks, the diagnosis was wrong: either the leak runs through a route not found here, or the pages are held in the index by something other than the mechanism described above.
One number is deliberately absent: how many generated URLs were index-eligible. It is written at runtime and readable only from the production database, so it was shipped as a reporting command rather than estimated here. Guessing it would have been the easiest sentence in this document to write.
Nothing measurable yet. The affected URLs have to be recrawled before any of this shows up, so the first honest read is due around mid-September 2026. This block gets filled in with the actual figures then, whichever way they go, and the prediction above will not be edited to match them.
The check
How it was verified
SEO changes are unusually easy to get wrong quietly. A gate that silently stops matching, a sitemap that keeps serving a stale cache, a threshold nobody can find later: all of them fail without an error. So the reasoning went into the test suite alongside the code.
The tests assert things a linter cannot: that a single lookup no longer qualifies a word, that the read-only branch returns before any database write, that the sitemap and the page apply the same two conditions, that the definition pages carry the directive and stay crawlable so it can be read. Every number quoted in the new guide is recomputed by a test against the site’s own engine, so a published claim cannot drift from the arithmetic behind it.
One helper was deleted rather than kept: a convenience function that answered “is this page publishable?” from a single database row. It could only ever check half the rule (how many other words share a value is a property of the whole table) while reading like the whole of it. That gap is roughly how the original one-lookup gate survived as long as it did.