@php $tone = fn ($v) => $v >= 85 ? 'text-emerald-400' : ($v >= 70 ? 'text-lime-400' : ($v >= 55 ? 'text-amber-400' : 'text-red-400')); $bar = fn ($v) => $v >= 85 ? 'bg-emerald-400' : ($v >= 70 ? 'bg-lime-400' : ($v >= 55 ? 'bg-amber-400' : 'bg-red-500')); // Conseil concret par critère GEO. $hint = [ 'contenu lisible sans JS (≥400 mots)' => 'Rendre le contenu clé côté serveur (SSR / pré-rendu / fallback HTML lisible) : les LLM lisent rarement le JavaScript.', 'contenu substantiel (≥600 mots)' => 'Étoffer le contenu texte (≥ 600 mots) : les IA citent les pages riches.', 'titre + description optimisés' => 'Titre clair + meta description de 120–160 caractères.', 'hiérarchie H1 + ≥2 H2' => 'Un seul H1 + au moins 2 sous-titres H2 pour structurer.', 'JSON-LD présent' => 'Ajouter des données structurées JSON-LD (schema.org).', 'entité (Org/LocalBiz)' => 'Déclarer Organization ou LocalBusiness (nom, adresse, téléphone, logo).', '≥ 3 types schema' => 'Décrire ≥ 3 types (ex. Organization + WebSite + BreadcrumbList).', 'schema Article/FAQ' => 'Structurer les contenus en Article / FAQPage (facilement citables).', 'llms.txt' => 'Publier un /llms.txt qui résume le site et guide les IA.', 'tous les bots IA autorisés' => 'Autoriser GPTBot, ClaudeBot, PerplexityBot, Google-Extended… dans robots.txt.', 'sameAs (réseaux)' => 'Lister tes profils (LinkedIn, X…) via "sameAs" dans le JSON-LD.', 'auteur + date visibles' => 'Afficher auteur + date de publication/màj (crédibilité pour la citation IA).', ]; $avg = count($sites) ? (int) round(collect($sites)->avg(fn ($s) => $s['geo']['score'] ?? 0)) : null; // Regroupement des critères GEO en 3 axes → barres de progression. $cats = [ 'Contenu' => ['contenu lisible sans JS (≥400 mots)', 'contenu substantiel (≥600 mots)', 'titre + description optimisés', 'hiérarchie H1 + ≥2 H2'], 'Données structurées' => ['JSON-LD présent', 'entité (Org/LocalBiz)', '≥ 3 types schema', 'schema Article/FAQ'], 'Accès & citation IA' => ['llms.txt', 'tous les bots IA autorisés', 'sameAs (réseaux)', 'auteur + date visibles'], ]; $catScore = function (array $checks, array $labels) { $s = 0; $g = 0; foreach ($checks as $c) { if (in_array($c['label'], $labels, true)) { $s += $c['w']; if ($c['ok']) $g += $c['w']; } } return $s ? (int) round($g / $s * 100) : 0; }; @endphp
HubPilotage
@include('partials.nav', ['active' => 'geo'])
@if($avg !== null)GEO moyen {{ $avg }}/100@endif Déconnexion

GEO·IA - visibilité dans les moteurs IA

Optimisation pour les moteurs génératifs (ChatGPT, Perplexity, Gemini, Google AI…). Ce qui compte : un contenu lisible sans JavaScript, des données structurées qui décrivent ton entité, un llms.txt, et des bots IA autorisés.

@if(count($sites))
Trier Filtrer
@endif @if(! count($sites))
Pas encore de données GEO. Lance un audit (page SEO → « ↻ Tout auditer ») depuis le hub local - les résultats se synchronisent ici.
@else
@foreach($sites as $s) @php $g = $s['geo']; @endphp
{{ $g['score'] }}/100
rendu {{ $g['render']==='JS' ? 'JavaScript' : 'HTML' }}
@if($g['render']==='JS')
⚠ Site rendu par JavaScript : les IA lisent surtout le HTML brut. Priorité n°1 : servir le contenu clé côté serveur (SSR / pré-rendu / fallback HTML).
@endif {{-- Barres de progression par axe GEO --}}
@foreach($cats as $catName => $labels) @php $v = $catScore($g['checks'], $labels); @endphp
{{ $catName }}
{{ $v }}
@endforeach
Bots IA : {{ $g['ai_allowed'] }}/{{ $g['ai_total'] }}
@endforeach
{{-- Popup détail des critères --}} @endif
@php $geoData = collect($sites)->mapWithKeys(fn ($s) => [$s['key'] => [ 'name' => $s['name'], 'url' => $s['url'], 'score' => $s['geo']['score'] ?? 0, 'spa' => ($s['geo']['render'] ?? '') === 'JS', 'fail' => collect($s['geo']['checks'] ?? [])->where('ok', false)->pluck('label')->values()->all(), 'checks' => array_map(fn ($c) => ['label' => $c['label'], 'ok' => $c['ok']], $s['geo']['checks'] ?? []), ]])->all(); @endphp