Le SEO IA, parfois appelé GEO (generative engine optimization), consiste à rendre votre site lisible, citable et réutilisable par les moteurs de réponse IA : ChatGPT, Perplexity, Claude et les AI Overviews de Google. Le SEO classique vous positionne sur une page de résultats ; le SEO IA vous fait citer dans la réponse elle-même. Next.js est bien placé pour cela, car tout ce que les moteurs IA récompensent (HTML rendu côté serveur, données structurées, fichiers lisibles par machine) correspond à une fonctionnalité du framework. Voici l'intégration que nous appliquons, fichier par fichier.
Que lisent réellement les moteurs IA ?
Trois choses comptent plus que tout. D'abord, la plupart des crawlers IA n'exécutent pas JavaScript : GPTBot, ClaudeBot et PerplexityBot récupèrent le HTML brut d'une URL, donc un contenu qui n'apparaît qu'après un rendu côté client leur est quasiment invisible. Ensuite, les moteurs de réponse extraient des passages, pas des pages : une section qui s'ouvre sur une réponse directe et autonome est bien plus facile à citer qu'une section qui fait monter la sauce. Enfin, les affirmations sourcées et datées gagnent. L'étude GEO de Princeton (KDD 2024) a mesuré la visibilité dans les réponses des moteurs génératifs : ajouter des citations, des références et des statistiques l'augmentait de 30 à 40 % dans leur benchmark.
Google est l'exception à nommer : ses propres recommandations indiquent que les AI Overviews reposent sur le classement du moteur de recherche classique, n'exigent aucun balisage particulier et sont alimentées par l'indexation ordinaire de Googlebot. Pour Google, on optimise donc comme d'habitude ; le travail structurel ci-dessous vise les autres moteurs et ne coûte rien à Google.
Ouvrir robots.txt aux bons crawlers
Chaque moteur a son bot, et un bot bloqué ne peut pas vous citer. Avec l'App Router, cela tient dans un fichier, app/robots.ts :
import type { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{ userAgent: '*', allow: '/' },
// Moteurs de réponse IA : les autoriser rend la citation possible.
{ userAgent: ['OAI-SearchBot', 'ClaudeBot', 'PerplexityBot'], allow: '/' },
],
sitemap: 'https://www.example.com/sitemap.xml',
}
}
Mesurez le compromis avant d'ouvrir la porte : autoriser ces bots permet la citation, et pour certains la réutilisation de votre contenu. Un entre-deux courant consiste à autoriser les bots de recherche et de citation listés ci-dessus tout en bloquant les crawlers d'entraînement pur comme GPTBot ou CCBot. Notez que Google-Extended contrôle l'entraînement de Gemini, pas les AI Overviews : le bloquer ne vous retire pas des réponses IA de Google.
Servir un HTML complet
C'est ici que Next.js justifie son choix. Gardez la substance de chaque page dans des Server Components pour que le texte intégral parte dans la réponse HTML initiale, et prérendez en SSG ou ISR pour que la réponse soit rapide : les crawlers travaillent avec des timeouts, et une origine lente est échantillonnée, pas lue. L'erreur classique : cacher la moitié du contenu derrière des onglets ou accordéons gérés côté client. Un bot qui n'exécute pas JavaScript ne verra jamais le deuxième panneau. Si une section compte, sa place est dans le balisage rendu côté serveur.
Vous voulez que votre site soit la réponse quand une IA est interrogée sur votre marché ? Décrivez votre stack : diagnostic d'une page sous 48 h.
Recevoir mon diagnostic →Des données structurées que les moteurs savent parser
Le JSON-LD donne aux moteurs le qui, le quand et le quoi d'une page sans deviner. Dans un Server Component, construisez l'objet et injectez-le ; la seule subtilité est d'échapper le caractère < pour qu'une donnée utilisateur ne puisse pas sortir de la balise script :
const article = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
datePublished: post.publishedAt,
dateModified: post.updatedAt ?? post.publishedAt,
author: { '@type': 'Person', name: post.author },
}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(article).replace(/</g, '\u003c'),
}}
/>
Le champ qui rapporte le plus : dateModified. Les moteurs IA pondèrent fortement la fraîcheur, et un article qui déclare une date de révision passe devant son jumeau non daté dans la sélection des réponses.
Publier un llms.txt
llms.txt est une convention proposée : un fichier markdown à la racine du site qui donne aux systèmes IA une carte éditorialisée de ce qu'est le site et de ses pages clés. Son adoption par les moteurs reste inégale ; traitez-le comme un pari peu coûteux, pas comme un levier de classement. En Next.js, c'est un route handler, qui peut dériver des mêmes données que votre sitemap pour ne jamais se périmer :
// app/llms.txt/route.ts
export const dynamic = 'force-static'
export function GET() {
const lines = [
'# Example Studio',
'> Ingénierie web : Next.js, serverless AWS, sites bilingues.',
'',
'## Guides',
...posts.map((p) => `- [${p.title}](https://www.example.com/fr/blog/${p.slug})`),
]
return new Response(lines.join('\n'), {
headers: { 'Content-Type': 'text/plain; charset=utf-8' },
})
}
Écrire pour qu'un moteur puisse extraire la réponse
La structure, aucun fichier de configuration ne la fera à votre place. Formulez les H2 comme les gens formulent leurs questions. Ouvrez chaque section par une réponse de 40 à 60 mots qui supporte d'être citée seule. Préférez un tableau à trois paragraphes pour toute comparaison. Datez vos affirmations et nommez vos sources dans le corps du texte : les habitudes mesurées par l'étude GEO sont exactement celles qui rendent un passage digne d'être extrait.
La liste de contrôle
- Décider quels bots IA vous autorisez, et l'encoder dans app/robots.ts.
- Garder la substance des pages dans des Server Components ; prérendre en SSG ou ISR.
- Servir un JSON-LD Article avec datePublished et dateModified.
- Ajouter un route handler llms.txt dérivé de vos données de contenu.
- Ouvrir chaque section par une réponse autonome ; des tableaux pour les comparaisons.
- Citer ses sources et dater ses statistiques dans le texte.
- Revérifier avec un simple fetch HTTP : ce que vous y voyez est ce que voient les bots.