Direct answer
An additive engine took 741 GEO/AEO structural errors to zero across 194 bilingual articles (IT+EN): 386 came from missing FAQ blocks, closed in a single automated pass that never touches the existing prose; 310 came from missing citations, closed only through a separate manual review, because the engine never fabricates a source.
Most GEO advice floating around online is cosmetic: lengthen the meta description, cram one more keyword into the H1, slap an "optimized for AI" badge somewhere. None of it moved a single structural error across my 194 bilingual articles. What actually zeroed them out was a mechanical, boring engine that injects two fixed blocks (direct answer, FAQ) without ever rewriting a single word of the prose already published.
Method note: this article describes the same engine published as an open-source repository, with synthetic fixtures and 13 automated reproduction tests. The production numbers cited here (741, 386, 310) are real, measured on the site's actual corpus before and after the retrofit, not an illustrative example.
Why most GEO advice is cosmetic
The most common GEO checklists talk about title length, keyword density,
alt tags on images: real details, but not what a search engine or a
language model actually uses to decide whether an article genuinely
answers a question. The structural gate I use internally
(audit-geo.mjs) ignores all of that and measures four binary
things instead: whether the article opens with a direct answer or a long
preamble, whether the answer block has a reasonable length, whether at
least one cited external link exists, and whether there are between 3 and
5 FAQ pairs. These are structural checks, not aesthetic ones: either the
shape is there, or it is not.
The additive engine: injects, does not rewrite
src/geo-retrofit.mjs takes an answer paragraph and a set of
FAQ pairs (in production, generated natively per language by an on-prem
LLM (Ollama, until 2026-10-23; since 2026-11-12 the site uses a local AI engine on its own server, with a job queue), never translated 1:1) and injects two fixed-shape HTML fragments: a
.geo-retrofit-lead block prepended as the literal first
content, and a .geo-retrofit-faq block appended as the
literal last content. Everything in between, the prose already written and
published, is never touched: no rewriting, no deletion, no
reformatting.
| Error type | Before retrofit | After lead+FAQ | After citation review |
|---|---|---|---|
| Missing direct answer | 0 | 0 | 0 |
| Missing or out-of-range FAQ | 386 | 0 (-386) | 0 |
| Missing external citation | 310 | 310 | 0 (-310) |
| Total structural errors | 741 | 310 | 0 (-741) |
The stated trade-off: additive versus a full rewrite
I could have gotten a "better" result on paper with a full rewrite of every article: paragraphs rebalanced into the 40-60 word window, citations added everywhere, structure made uniform. I deliberately ruled it out. Rewriting 194 already-indexed articles, with existing backlinks and rankings, means risking ranking regressions that no automated gate catches before deploy. The additive approach has an explicit cost, a lower quality ceiling than a full rewrite could reach, but it limits the risk to "I add two blocks at the margins" instead of "I rewrite everything and hope Google does not notice."
Two idempotency guards, not one
The engine uses two independent checks to avoid repeating itself. The
first is a marker attribute (data-geo-retrofit) that skips
injection if already present. The second is more interesting:
needsLead() and needsFaq() reuse the same
checkAnswerFirst() and countFaqPairs() functions
the detection gate uses, so an article that already satisfies the criteria
on its own, with no marker at all, is left untouched too. The engine's
self-check and the acceptance gate agree by construction: they are
literally the same function, never re-derived.
Why bilingual doubles the surface
194 articles across two languages means 388 HTML documents to run the gate
against, not 194. Each language generates its own direct answer and its
own FAQ natively, never translated 1:1 from the other: a model that
translates mechanically produces prose that reads as translated, with a
negative effect on the reading experience and, indirectly, on the
perceived editorial signal. The cost is a second dedicated check,
assertParity(), which verifies that the FAQ pair count
matches between the IT and EN versions of the same article, so one
language does not end up out of range while the other stays compliant.
The honest limits: the engine does not close everything on its own
The 310 missing-citation errors were not closed by this engine, and could
not have been by construction: the integrity rule is that the retrofit
never fabricates a source. test/reproduce.test.mjs verifies
this directly, counting href="https://..." links before and
after the run and asserting the count stays identical. Closing the 310
residual errors required a separate manual pass, article by article, with
a verified external source added by hand: slower, but the only approach
compatible with the "no fabricated sources" rule.
Who this approach is for
If you have an already-published, already-indexed content corpus that needs to meet a new structural standard (GEO, accessibility, schema.org), the practical advice is: prefer an additive, idempotent engine over a rewrite, measure the gate before and after with the exact same script (not an "equivalent" one), and never delegate to an automated engine the job of creating a source or a data point you have not verified yourself.
In the "Original Research" series, previous: 01 - Sport Intelligence Benchmark; next: 03 - Four Production Postmortems.
Frequently asked questions
Why 741 errors and not a different, already lower number?
741 is the real total measured before any retrofit across 194 bilingual (IT+EN) articles, not an example chosen to look impressive: 386 came from missing or out-of-range FAQ, 310 from missing external citations. Reporting the real starting number, even if high, is part of the same integrity rule this engine applies to its own output.
Does the engine rewrite existing articles to fix them?
No. It is additive by construction: it injects a direct-answer block as the first content and an FAQ block as the last content, both marked with a data-geo-retrofit attribute, without ever modifying, deleting, or reformatting a single word of the prose already published between the two.
How does the engine know if an article is already fine as-is?
It reuses the exact same detection-gate functions (checkAnswerFirst(), countFaqPairs()) to decide whether an injection is needed, plus a separate marker-attribute check for articles already processed. The result is that the engine's self-check and the acceptance gate can never drift out of sync, because they are literally the same code.
Why were the 310 citation errors not closed by the same engine?
Because of an explicit integrity rule: the engine never fabricates a source. Automatically adding an external link without verifying its content would risk citing something irrelevant or no longer valid, so closing the 310 residual errors required a separate manual review, article by article, with a hand-verified source.
Related deep dive: Sport Intelligence Benchmark: Brier 0.5783 su 97.000 partite, ensemble V2 LightGBM.
Related deep dive: Quattro Postmortem di Produzione: Perché i Test Verdi Non Bastano.
Sources and further reading
- Idempotence (Wikipedia)
- Latest Google Search Documentation Updates (Google Search Central): removal of the FAQ rich result documentation - the "FAQPage structured data" page cited before no longer exists: Google removed the documentation of the FAQ rich result (June 2026) and states that from May 7, 2026 the feature no longer appears in search results; consulted on 2026-11-13
Commenti
Caricamento commenti...
Sign in to comment