seo-audit-geo — Analyse GEO (visibilité IA générative)
Couvre l'intégralité de la méthode GEO (references/process.md, copie fidèle de la spec phase 5). Produit findings/geo.json.
Architecture hybride — deux couches, aucun process omis
- Couche script (
scripts/analyze.py) : tout le mécanisable — matrice d'accès bots LLM (5.1-5.5), llms.txt (5.6), FAQ/glossaire par URL + FAQPage schema (5.12-5.14), Organization/Person completeness (5.16-5.17), Wikidata (5.19), cohérence de marque (5.20). Écritfacts+findings. - Couche agent (CE SKILL.md) : les jugements sur le contenu réel que le crawl ne porte pas — structure AEO sur 20 pages (5.8-5.11), contenu caché par JS (5.7), liens d'identité externes (5.18). Listés dans
to_judgeavec rubrique exacte. Plus la visibilité LLM (5D-5F) quand DataForSEO AI sera branché.
Le script ne fabrique pas de proxy. Il ne sait pas si une page a des
<ul>/<table>(le crawl DFS OnPage n'expose pas le HTML) → il inscrit l'évaluation AEO dansto_judgeavec le barème, et l'agent va WebFetch les pages pour scorer réellement.
Procédure de l'agent
Étape 1 — Lancer le socle script
python seo/skills/seo-audit-geo/scripts/analyze.py <slug>
python seo/skills/seo-audit-geo/scripts/analyze.py <slug> --offline # sans HTTP (réserve seule)
Étape 2 — Exécuter chaque évaluation de to_judge
5.7 — Contenu caché par JS (échantillon 10 pages) : pour chaque page, comparer le rendu sans JS (HTTP brut / curl) vs avec JS (WebFetch rendu). Title, H1, word count. WC sans JS=0 & avec JS>0 → contenu caché (critique pour les LLM). >1.5× → contenu majoritairement JS. JS_dependency_score = pages avec issue / total × 100. Seuils : <5% bon, 5-15% surveiller, >15% risque élevé.
5.8-5.11 — Structure AEO (20 pages clés : home, pricing, features, top blog) : pour chaque page (WebFetch HTML), scorer → réponse/résumé en tête (les ~100 premiers mots répondent au sujet) +20, listes <ol>/<ul> +15, tableaux <table> récap +15, hiérarchie H2/H3 claire +15, section FAQ +20, définitions de termes +15. AEO Score/page = somme (max 100). Confirmer que les listes numérotées sont de vrais how-to instructionnels (5.11). Renvoyer la moyenne sur 20 pages + les pages faibles. Seuils (thresholds.geo.aeo_score) : >70 bon, 50-70 moyen, <50 faible.
5.18 — Liens d'identité externes : WebFetch about/home, chercher des liens vers Wikidata, Wikipedia, Crunchbase, LinkedIn entreprise, profils sociaux officiels. Compter les liens d'autorité, vérifier qu'ils sont officiels et pertinents.
Étape 3 — (Quand DataForSEO AI est branché) Visibilité LLM 5D-5F
Tant que collecte_a_brancher, ces findings sont affichés "à venir". Quand la collecte est branchée, exécuter le process complet :
- 5.21-5.22 : générer 20-30 prompts (JTBD / transactionnels / comparaison / problème) depuis GSC + feature pages + concurrents, faire valider par l'utilisateur.
- 5.23-5.26 :
ai_opt_llm_ment_searchpar prompt → marque mentionnée/position/contexte/concurrents ;ai_opt_llm_ment_agg_metrics→ mention rate, share of voice ;ai_opt_llm_ment_top_domains/top_pages→ domaines et pages cités. - 5.27-5.30 :
chat_gpt_scraperpour vérifier exactitude ; sentiment (positif/neutre/négatif/mixte) ; exactitude de la description produit sur 5 dimensions (catégorie, features, audience, prix, différenciation) ; mentions négatives à corriger. - 5.31-5.34 : query fan-out (sources qui influencent les réponses), pages concurrentes les plus citées, pages à créer, pages à optimiser (avec gains AEO estimés).
Étape 4 — Write-back des jugements (OBLIGATOIRE)
Une fois les to_judge évalués, réintègre les résultats dans findings/geo.json via le module partagé — sinon le rapport ne voit pas tes scores et l'audit n'est pas comparable d'un run à l'autre :
python seo/seo-os/scripts/judgment.py <findings/geo.json> \
--results '{"aeo_score": <moyenne 20 pages>, "js_dependency_score": <pct>, "lists_pct": <%>, "tables_pct": <%>, "external_authority_links": <n>}' \
--rule geo_aeo
Cela hydrate facts.aeo.content_depth_score (via la clé judged) et émet geo.aeo.weak_structure si le score AEO moyen < seuil (thresholds.geo.aeo_score.warning_min). Ajoute aussi manuellement geo.js.hidden_content (via un 2e appel write-back avec un finding construit) si JS_dependency_score > 15%. Les id sont stables pour la comparaison entre audits.
Données requises
- Crawl (raw.json) : obligatoire (microdata pour schema, URLs).
- robots.txt / llms.txt live : HTTP direct (sauf
--offline). - Contenu HTML des pages (WebFetch) : pour les
to_judgeAEO/JS. L'agent le récupère. - DataForSEO AI Optimization : pour 5D-5F. Non collecté →
collecte_a_brancher.
Contrat
Entrée : data/crawl/<date>/raw.json + robots/llms live. Sortie : findings/geo.json (facts + to_judge + findings). Voir references/process.md et seo-os/references/data-contract.md.
Sur Hermes
Profil-worker seo-geo, carte parents=[seo-collect], parallèle aux autres analyses. La couche agent (WebFetch des pages pour l'AEO) tourne dans le worker.