Skip to main content

02 - GEO Retrofit Benchmark: 741 Structural Errors to Zero Without Touching Existing Prose

An additive engine that injects and does not rewrite took 741 structural GEO errors to zero across 194 bilingual articles, leaving the prose untouched.

What do you think about this article?

02 - GEO Retrofit Benchmark: 741 Structural Errors to Zero Without Touching Existing Prose
Original Researchfedericocalo.dev

At a Glance

An additive engine that injects and does not rewrite took 741 structural GEO errors to zero across 194 bilingual articles, leaving the prose untouched.

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.

GEO/AEO structural errors before and after the retrofit, across 194 bilingual IT+EN articles
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)
194 bilingual (IT+EN) articles, additive lead+FAQ retrofit engine (this repo) plus a separate manual review pass for citations. Full methodology and numbers: see the linked repo.

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.

Sources and further reading

Commenti

Caricamento commenti...

Sign in to comment

Discuss this article in the community

Join the Telegram group to discuss with other developers, ask questions and share your experiences.

Did you like this article?

Explore other content on the blog or discover my projects