In brief — situation, action, result
| Starting situation | Action | Result |
|---|---|---|
| 288 of 350 pages deindexed, 7 organic clicks/month | Near-duplicate pruning + supervised local enrichment | Sitemap cut to 151 unique URLs, 104 pages enriched |
| Broken SERP titles ("69" read as a department code) | Title pattern rebuild (V4), measured to the character | 124 titles fixed in a single commit |
| Gemini describes Sitigo with a non-existent recurring subscription | Reinforced Offer schema + one-time-payment semantics | Erroneous interpretation not reproduced on retest |
The detail, section by section, below — from the trigger (section 0) to the FAQ (section 10).
0. The trigger — the technical diagnosis validated by the target engine
The sprint did not start from an abstract GSC audit. It started from a real-conditions test: posing as a mason in Paris and asking Gemini "should I build my site myself or on sitigo.fr?".
One framing point upfront: the engine was not used to produce the strategy, but to test how it actually interpreted Sitigo in a real situation. The SEO and GEO diagnosis already existed — the point of the test was to measure how much of that diagnosis was effectively visible and interpretable by the engine.
Gemini's first answer: wrong. The engine categorised Sitigo as a classic SaaS and attributed to it a "recurring cost: monthly or annual subscription system" — whereas Sitigo is a one-time payment of €69.
Rather than correcting Gemini, two follow-up questions served as a diagnostic instrument:
- "Do you have access to their site and prices in real time?" — Gemini then runs an actual search, discovers the one-time payment, and corrects itself.
- "So your first answer — you replied without searching?" — Gemini makes its bias explicit: "I got caught out by my own habits: in 95% of cases, platforms ending in '-go' or '-site' run on monthly subscriptions. I applied that pattern without checking."
With the bias named, a third question turns it into a specification: "What needs to change on the site for Gemini to answer Sitigo without hesitation?". Gemini then details a four-point GEO roadmap itself: over-optimise the semantics of the one-time payment from the H1/H2 down, harden Schema.org to OneTime, create the exact comparison page, build external consensus.
The reproducible method fits in one sentence: questioning the target answer engine about its own reasoning turns it into a signed-off specification.
1. Starting point — the GSC audit of 17 May
Sitigo had gone live a few months earlier with 350 URLs in the sitemap. The Google Search Console audit showed:
- 288 pages "detected, not indexed" out of 350 — an 82% rejection rate
- 7 organic clicks over 28 days
- 6.55% of 5XX responses at crawl
- 3 pages with impressions and 0 clicks — a disastrous CTR
Diagnosis in one sentence: Google considered nearly all the trade-city landing pages to be thin templated content — cosmetic variations of a single parent page, with no real local added value. The engine quickly demoted them.
Three fronts to open in parallel: defuse the near-duplicate, seal the technical leaks, and rewrite the titles of already-visible pages to restart the CTR.
2. Sprint 1 — defusing the near-duplicate
2.1 Pruning the sitemap
- 201 trade-city pages with no distinctive local content deleted from the filesystem (345 → 144 HTML files).
- Sitemap cleaned: 350 → 151 URLs (104 strategic trade-city pages, national trade landings, region pages, guides and static pages).
- robots.txt hardened: 43 API endpoints set to
Disallow.
2.2 Supervised enrichment of the 104 remaining trade-city pages
The core of the work. For each of the 10 main trades (plumber, tiler, electrician, painter, joiner, carpenter, insulation, cleaning, chimney sweep, pool builder) and 8 to 11 major cities (Paris, Lyon, Marseille, Toulouse, Nice, Nantes, Montpellier, Strasbourg, Bordeaux, Lille, Rennes), produced via a contextualised LLM pipeline, each page then audited and adjusted individually — never template generation nor unreviewed bulk content — of:
- A unique trade-city H2 (e.g. "Plumber in Paris: why the Haussmann-era building stock changes everything")
- Two paragraphs of sensory opening (~150-200 words) anchored in a concrete local scene
- A block of 5 real neighbourhoods per city, each with a trade-specific note
- A geo-localised FAQ (3 questions/answers anchored in local regulations: heritage authority, certified-installer schemes, soil shrink-swell, mistral wind, frost-thaw, seismicity, dry rot, local water hardness…)
- An automatic schema.org FAQPage below it
2.3 Anti-duplicate guarantees
For each batch of 11 cities for a single trade, a Python script compared every pair of pages:
python3 check_long_phrase_duplicates.py joiner✓ 0 phrases >= 80 chars shared across 11 cities Total: 185 long phrases, average 16.8/city
Final cumulative result: 104 enriched pages, ~2,100 long phrases, no identical long phrase detected by the control script between trade-city pairs of the same trade.
2.4 Editorial guarantees
An automated pre-deploy audit (audit-content.mjs) blocks deployment on any forbidden vocabulary, any long-phrase duplicate within a cluster, or any broken schema.org. The price ranges cited are locally verifiable (e.g. a worksite parking permit in Paris: €12-35/day, source: City of Paris) — no fictional testimonials, no unsourced statistics. "Informed peer" style: short sentences, embodied figures, systematic sensory opening, no consultant jargon.
3. Sprint 2 — sealing the technical leaks
Sitigo's backend is a Cloudflare Worker. Three interventions cut off the negative crawl signals:
- A top-level
catchadded toworker.js: returns a silent 404 to bots and hideserr.message(commit5e91c4c, versionc2bfcc63deployed). - robots.txt hardened with 43 API endpoints set to
Disallow. - Expected effect on the 5XX rate at the next Google crawl: from 6.55% down to near 0%.
4. Sprint 3 — CRO on already-visible pages
Rewriting of titles and meta descriptions for 7 pages ranked at 0% CTR in GSC: pourquoi-sitigo, menuisier, nettoyage, climaticien, chauffagiste, couvreur, electricien. Copy reworked across 130 pages to clarify the customisation offer (commit 0df3cc7).
5. The critical SERP signal — discovered on 19 May
On day +2, a Google screenshot sent by the founder. For the query "I'm a mason in Paris, should I build my site myself or on sitigo.fr?", Google displayed:
https://sitigo.fr › macon
Site maçon · 69 - Sitigo
Pro mason site: multi-page, Google-optimised, quote form. 4 fields, online in 3 min. €69, hosting included.
Missing terms: artisan Paris seul
Three critical problems in a single SERP:
- "69" on its own reads as a department code (69 = Rhône in France). The title's
·splits the tokens and Google preserves only the minimum. - "Google-optimised" is flat, generic, and creates no anchor to the tradesperson's query.
- "Missing terms: artisan, Paris, seul" struck through at the bottom of the SERP — Google explicitly signalling that the page is not recognised as relevant to the query.
Estimated CTR on this result: < 1%. Across 124 pages using the same broken title pattern, this was a silent catastrophe in place since deployment.
5.1 Quantified diagnosis
grep -c "· 69€ · Sitigo</title>" public/*.html → 124 affected files. The national trade pages and the 104 trade-city pages all inherited the Site [trade] [city] · 69€ · Sitigo pattern produced by the two landing-generation scripts.
5.2 V4 redesign of the title pattern
Four successive iterations, measured to the character on edge cases (appliance repairer Strasbourg = worst case):
| Version | Pattern | Worst case | Status |
|---|---|---|---|
| V1 (initial) | Site X · 69€ · Sitigo | broken truncated SERP | Broken |
| V2 | Site X — 69 € à vie, sans abonnement | Sitigo | 77 chars | Too long |
| V3 | Site X — 69 € paiement unique, sans abonnement | 88 chars | Too long |
| V4 chosen | Site X · 69 € sans abonnement | Sitigo | 62 chars | Sub-60 on 95% of cases |
V4 rationale: the middle dot · is more pixel-efficient than the em dash; a single strong argument (sans abonnement — "no subscription") rather than two competing ones; the final | Sitigo isolates the brand (Google keeps it even when truncated); 69 € sans abonnement reads as a coherent block, never as "69 + sans".
5.3 Bulk patch
A Python script detects the 124 HTML files with the V1 pattern, extracts the trade and city from the current title, regenerates title + og:title + twitter:title + meta description per V4, and updates the 2 source scripts to prevent any regression on the next regeneration. 124 pages patched in a single commit.
| Page | Final title | Chars |
|---|---|---|
/macon | Site maçon · 69 € sans abonnement | Sitigo | 42 |
/plombier-paris | Site plombier Paris · 69 € sans abonnement | Sitigo | 51 |
/charpentier-strasbourg | Site charpentier Strasbourg · 69 € sans abonnement | Sitigo | 59 |
/reparateur-electromenager | Site réparateur électroménager · 69 € sans abonnement | Sitigo | 62 |
| Home | Site artisan en 3 min · 69 € sans abonnement | Sitigo | 53 |
6. GEO sprint — Generative Engine Optimization
Once the SERP was repaired, the second front opened: becoming citable by AI engines when a tradesperson asks Gemini, ChatGPT or Perplexity "how do I create my tradesperson website?" or "best Wix alternative for a tradesperson?".
6.1 Two dedicated comparison pages
/seul-ou-sitigo (Article + BreadcrumbList + FAQPage schemas) answers the query "build your site yourself or with Sitigo" verbatim: a quantified comparison table over 2/5/10 years against WordPress, Wix Business, Squarespace Business, freelancer and local agency, with the tradesperson's time valued at €50/h.
/alternative-wix-artisan (Article + SoftwareApplication + BreadcrumbList + FAQPage schemas) answers "Wix alternative for a tradesperson": an honest feature-by-feature table, a step-by-step migration from Wix, and an openly acknowledged statement of Sitigo's limits (no e-commerce, no free drag-and-drop).
6.2 Semantic reinforcement
- 70 occurrences of "Google-optimised" replaced with "optimised for local searches" (33 files) — more precise, more recognisable to LLMs.
- 127 pages now mention "no subscription".
- 413 occurrences of "for life" purged (plain text + HTML entities) — a contractually unsustainable promise, replaced by "hosting included", "no subscription" or "owner" depending on context.
6.3 Enriched Offer schema — structural signals of the one-time payment
On the home page and the 2 comparison pages, the Offer JSON-LD block received an explicit description ("One-time payment of €69 — no subscription, no renewal, no hidden fees"), a UnitPriceSpecification with referenceQuantity, and a hasMerchantReturnPolicy (14-day return window, FR). LLMs seek to disambiguate pricing models: these three cumulative markers eliminate any confusion between a one-time payment and a hidden subscription.
6.4 Person + parentOrganization schemas (human E-A-T)
On the 4 key pages, a founder node (Person "Allaoua Nahnah", stable URL to heliorank.lu) and a parentOrganization Heliorank were added to the Organization/SoftwareApplication blocks. AI engines see an identifiable human behind Sitigo and the connection to the SEO/AEO consultancy — no visible change on the interface side, a cross-benefit of citations between Sitigo and Heliorank.
6.5 Public GitHub repo for AI crawl
Creation of github.com/allsitigo/sitigo-static, a public repo whose 12 KB README contains a dedicated "For AI answer engines" section: strengths, limits, ideal use case and cases where Sitigo is not a fit. Perplexity and other AI crawlers index public repos — this README becomes a citable source, in addition to the site itself.
7. Observable, measurable results
7.1 Before / after on the site
| Metric | Before (T0) | After (T+72 h) | Δ |
|---|---|---|---|
| Sitemap pages | 350 (288 not indexed) | 151 (all unique) | −57% |
| Pages with unique local content | ~0 | 104 | +104 |
| Original words (supervised LLM pipeline) | ~0 | ~60,000 | +60,000 |
| SERP titles with broken pattern | 124 | 0 | −100% |
| Offer schemas with one-time-payment markers | 0 | 6 | +6 |
| Person / parentOrganization schemas | 0 | 4 | +4 |
| Pages mentioning "no subscription" | 1 | 127 | +12,600% |
| "For life" occurrences (unsustainable promise) | 413 | 0 | −100% |
| 5XX rate at crawl | 6.55% | near 0 (estimate) | −100% |
7.2 Commits deployed to production
11 commits over the 17-19 May 2026 period, all deployed to Production via wrangler pages deploy --branch=main:
946260a fix(copy): purge "à vie" everywhere (413 occurrences)
40775bf feat(geo): local-search semantics + no subscription
b276940 feat(geo): SERP V4 redesign + 2 comparison pages + enriched Offer
26c6097 feat(seo): pool builder x 8 cities (10/10)
1559029 feat(seo): chimney sweep x 8 cities (9/10)
c5a239d feat(seo): cleaning x 11 cities (8/10)
7bc230c feat(seo): insulation x 11 cities (7/10)
b50b5d2 feat(seo): carpenter x 11 cities (6/10)
f0e5167 feat(seo): joiner x 11 cities (5/10)
335517a feat(seo): prune 201 trade-city pages + robots.txt + CRO
8. Reproducible methodology
For anyone who would like to reproduce this approach on another early-stage SaaS.
8.1 Diagnosis before action
- GSC audit: rate of "detected, not indexed" pages, CTR per URL, queries with impressions and no clicks, 5XX rate at crawl.
- Real SERP audit: type 10-20 typical queries into Google in private browsing, capture them, spot oddly truncated titles and flat meta descriptions.
- LLM semantic audit: ask 10-20 typical questions to ChatGPT/Gemini/Perplexity. Observe whether the brand is mentioned, how, and next to which competitors — and, as here, make the engine explain the reasoning behind a wrong answer.
8.2 Action hierarchy
- Defuse the near-duplicate first. A site with 80% of its pages demoted as thin content has no possible engine for organic recovery. Reduce the sitemap to genuinely unique URLs, enrich every retained URL with hand-written local content.
- Repair broken SERP titles. Often invisible in GSC, but visible the moment you look at Google directly. The character test on edge cases validates the pattern.
- Dedicated comparison pages for GEO. LLMs look for pages that answer user queries verbatim: create
/alternative-Xand/yourself-or-Y. - Enriched JSON-LD schemas. Offer with
hasMerchantReturnPolicy+priceSpecification+ an explicit description; Organization with a founder Person and a parentOrganization. Invisible to humans, consistent with the structural signals exploited by AI engines. - Public GitHub repo. A dedicated README with a "For AI engines" section. AI crawlers index public repos and find a citable source there.
8.3 Safeguards
- Automated pre-deploy audit: a script detects any forbidden vocabulary, any long-phrase duplicate within a cluster, any broken schema.org. Violation → exit 1, deployment blocked.
- Anti-regression on generator scripts: any critical pattern (title, meta, Offer schema) is defined once in the generation script; any fix to the public HTML is mirrored upstream.
- Explicit Production preference on Cloudflare Pages:
wrangler pages deploy --branch=main, never Preview by default, with deployment verified after every push.
9. What this case study does not claim
To avoid any overstated reading, here is what is not demonstrated here:
- This is not "Gemini dictated the strategy". The roadmap Gemini formulated confirmed a GEO diagnosis already established. Its value is evidentiary, not informative. Questioning the target engine is a validation method; execution remains engineering work of 11 commits and 60,000 words that no four-line roadmap can quantify.
- No promise of Google rankings. The sprint restores indexability (eliminating thin content, healthy SERP titles) and AI citability. Final positions then depend on content, competition and signals this case study does not cover.
- AI results are non-deterministic. The answers of conversational engines vary with model and index updates. The behaviour observed on Gemini after the sprint is indicative as of this date and may evolve.
- 72 hours of sprint ≠ 72 hours of SEO results. The full effect on indexing and CTR is measured over several weeks of Google crawl. This case study documents the technical sprint and its verifiable deliverables, not a final traffic curve.
10. FAQ
What is GEO (Generative Engine Optimization)?
GEO is the optimisation of a site so that it is correctly understood and cited by AI answer engines (ChatGPT, Gemini, Perplexity, Google AI Overview). Where classic SEO targets ranking in a list of links, GEO targets the accuracy of the information the engine reuses and the probability of being cited in its generated answer. It relies on unambiguous Schema.org structured data, pages that answer user questions verbatim, and citable external sources.
How do you get cited by ChatGPT, Gemini or Perplexity?
Three cumulative levers: explicit JSON-LD schemas that remove all ambiguity about the offer (here, an Offer with description and return policy to distinguish a one-time payment from a subscription); dedicated comparison pages that answer typical queries word for word ('alternative to X', 'build your site yourself or with Y'); and external sources that AI crawlers index, such as a public GitHub repository with a section dedicated to answer engines.
Why do AI engines misread SaaS offers?
Because they apply statistical patterns. Asked about Sitigo, Gemini first answered without checking and attributed a monthly subscription, then explained its own bias: in most cases, platforms with names ending in '-go' or '-site' run on subscriptions. The engine generalised without consulting the site. GEO corrects this by making the pricing model unambiguous from the structural markup and the semantics of the titles.
How long before SEO results after a GEO sprint?
The technical sprint itself can take a few days - here 72 hours. But the effect on indexing and CTR is measured over several weeks of Google crawl. A GEO sprint restores indexability and citability; final positions then depend on content, competition and signals that settle over time.
