IABIG

Visibilité dans les IA · Mis à jour le 2026-10-25 · Version Markdown

Site React, Vue ou Angular invisible pour les IA - pourquoi et comment corriger

Pourquoi ChatGPT, Claude ou Perplexity peuvent ne pas voir un site rendu en JavaScript, comment le tester avec curl et quelles solutions SSR ou SSG appliquer.

Une application monopage (SPA) construite avec React, Vue ou Angular envoie souvent au navigateur un HTML presque vide, puis fabrique le contenu avec JavaScript. Un navigateur s'en accommode ; un robot qui se contente de télécharger le HTML ne voit qu'une coquille. Or la plupart des robots des services d'IA semblent fonctionner ainsi. Ce guide fait le point sur ce que l'on sait réellement de leur comportement, montre comment vérifier votre propre site en quelques minutes, puis détaille les corrections possibles avec Next.js, Nuxt et Astro.

Ce que les robots d'IA exécutent, d'après les sources disponibles

Point important : aucun fournisseur d'IA ne documente officiellement si ses robots exécutent ou non le JavaScript. Les pages officielles d'OpenAI (GPTBot, OAI-SearchBot, ChatGPT-User), d'Anthropic (ClaudeBot, Claude-SearchBot, Claude-User) et de Perplexity (PerplexityBot, Perplexity-User) décrivent le rôle de chaque robot et la façon de les contrôler, mais pas leur moteur de rendu. Ce que l'on sait vient donc d'observations.

La référence la plus citée est une analyse publiée par Vercel et MERJ en décembre 2024, fondée sur le trafic observé sur le réseau Vercel. Conclusion : aucun des grands robots d'IA étudiés n'exécutait le JavaScript. Ils téléchargent parfois des fichiers .js (11,5 % des requêtes pour les robots de ChatGPT, 23,8 % pour ClaudeBot), mais ne les exécutent pas.

Robot Exécute le JavaScript ? Nature de l'information
GPTBot, OAI-SearchBot, ChatGPT-User (OpenAI) Non observé Étude Vercel/MERJ, décembre 2024 ; rien dans la documentation OpenAI
ClaudeBot (Anthropic) Non observé Même étude ; rien dans la documentation Anthropic
Claude-SearchBot, Claude-User (Anthropic) Inconnu Pas de donnée publique identifiée, non documenté
PerplexityBot (Perplexity) Non observé Même étude ; rien dans la documentation Perplexity
Googlebot Oui Documentation Google : rendu par un Chromium sans interface
Bingbot Oui Annonce Bing de 2019 : rendu avec Microsoft Edge
Applebot Oui Observé dans l'étude Vercel/MERJ

Deux précisions. D'abord, l'étude date de fin 2024 ; le comportement d'un robot peut changer sans annonce. Ensuite, les fonctions d'IA de Google s'appuient sur l'index de Google Search, construit par Googlebot, qui exécute le JavaScript ; le jeton Google-Extended n'a pas de robot distinct. Google rappelle néanmoins que le rendu côté serveur ou le prérendu restent « une excellente idée », car « tous les robots ne peuvent pas exécuter JavaScript ».

Enfin, les agents qui pilotent un vrai navigateur exécutent le JavaScript comme n'importe quel navigateur. Mais ce n'est pas ce qui alimente l'index de recherche d'un assistant : pour être trouvé et cité, mieux vaut que le contenu soit dans le HTML initial.

Le symptôme typique

Voici ce que reçoit un robot qui ne fait pas de rendu, pour une application React créée avec un modèle de projet classique :

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="UTF-8" />
    <title>Mon entreprise</title>
    <script type="module" src="/assets/index-4f8a2c.js"></script>
  </head>
  <body>
    <div id="root"></div>
  </body>
</html>

Le titre est là, le reste non : ni texte, ni liens internes, ni coordonnées. Un robot qui s'arrête ici n'a rien à indexer ni à citer, et ne découvre pas les autres pages, puisque les liens n'existent qu'après exécution du script.

Tester soi-même

1. Avec curl. curl récupère le HTML sans exécuter de JavaScript, comme les robots décrits plus haut. Cherchez une phrase qui figure dans le contenu principal de la page :

# Le HTML brut contient-il la phrase attendue ?
curl -s https://www.example.com/tarifs | grep -c "Devis gratuit"

# Même test en se présentant avec le user-agent d'un robot d'IA
curl -s -A "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko); compatible; GPTBot/1.4; +https://openai.com/gptbot" \
  https://www.example.com/tarifs | grep -c "Devis gratuit"

# Combien de liens internes sont présents dans le HTML initial ?
curl -s https://www.example.com/ | grep -o '<a [^>]*href="/[^"]*"' | wc -l

Un résultat 0 sur une phrase visible à l'écran signifie que ce texte est ajouté par JavaScript. Le second test sert aussi à repérer un pare-feu qui traite différemment ce user-agent (code 403, page de défi). Il reste indicatif : il imite le nom du robot, pas son adresse IP.

2. Avec view-source:. Dans Chrome ou Firefox, tapez view-source:https://www.example.com/ dans la barre d'adresse. Vous voyez le HTML tel qu'il a été reçu, avant exécution des scripts. L'onglet « Éléments » des outils de développement, lui, montre le DOM après exécution : ne le confondez pas.

3. En désactivant JavaScript. Dans Chrome, ouvrez les outils de développement, puis le menu de commandes (Ctrl+Maj+P, ou Cmd+Maj+P sur macOS), tapez javascript, choisissez Disable JavaScript et rechargez la page. Le réglage ne vaut que pour cet onglet et tant que les outils restent ouverts. Ce que vous voyez alors est une bonne approximation de ce que lit un robot sans rendu.

Faites ces tests sur plusieurs types de pages (accueil, fiche produit, article, page de contact), car beaucoup de sites mélangent pages rendues côté serveur et parties chargées côté client.

Les solutions

Technique Principe Quand l'utiliser
Rendu côté serveur (SSR) Le serveur produit le HTML complet à chaque requête Contenu qui change souvent ou dépend de la requête
Génération statique (SSG) Le HTML est produit une fois, au moment de la construction Pages dont le contenu change peu : vitrine, blog, documentation
Régénération incrémentale (ISR, SWR) HTML statique mis en cache puis régénéré périodiquement Catalogues, contenus mis à jour plusieurs fois par jour
Prérendu d'une SPA Un outil exécute l'application au build et enregistre le HTML de chaque route SPA existante qu'on ne peut pas migrer
Rendu dynamique HTML prérendu servi aux robots seulement À éviter : Google le qualifie de contournement non recommandé

L'hydratation n'est pas une alternative mais le complément du SSR et du SSG : le navigateur reçoit un HTML déjà rempli, puis le JavaScript « s'attache » à ce HTML pour le rendre interactif. Le robot lit le HTML ; l'utilisateur obtient l'interactivité. C'est le fonctionnement par défaut de Next.js, Nuxt et Angular avec SSR.

La balise <noscript> ne s'affiche que si JavaScript est désactivé. Elle peut porter un message ou un lien de secours, mais ce n'est pas une solution pour le contenu principal : il faudrait dupliquer toute la page, et un contenu de noscript différent de ce que voit l'utilisateur relève du texte caché.

<noscript>
  <p>Ce simulateur nécessite JavaScript. Consultez la <a href="/tarifs">grille tarifaire</a>.</p>
</noscript>

Next.js

Avec l'App Router, les pages et les layouts sont des Server Components par défaut : leur contenu est rendu en HTML côté serveur ou au build. Le piège classique est de charger le contenu principal dans un composant client, après le montage :

// app/tarifs/page.js : à éviter pour un contenu à indexer
'use client'
import { useEffect, useState } from 'react'

export default function Tarifs() {
  const [offres, setOffres] = useState(null)
  useEffect(() => {
    fetch('/api/offres').then((r) => r.json()).then(setOffres)
  }, [])
  if (!offres) return <p>Chargement…</p>   // c'est tout ce que verra un robot
  return <ul>{offres.map((o) => <li key={o.id}>{o.nom}</li>)}</ul>
}
// app/tarifs/page.js : version rendue côté serveur
export default async function Tarifs() {
  const res = await fetch('https://api.example.com/offres')
  const offres = await res.json()
  return <ul>{offres.map((o) => <li key={o.id}>{o.nom}</li>)}</ul>
}

Autre point de vigilance : dynamic(() => import('...'), { ssr: false }) exclut le composant du prérendu. Réservez-le aux éléments non essentiels (carte interactive, widget de discussion). Pour un hébergement purement statique, output: 'export' dans next.config.js génère un fichier HTML par route au moment du next build.

// next.config.js
const nextConfig = { output: 'export' }
module.exports = nextConfig

Nuxt

Nuxt utilise par défaut le rendu universel : HTML produit côté serveur, puis hydratation. Le problème apparaît si quelqu'un a désactivé le SSR globalement avec ssr: false, ce qui transforme le site en SPA. Les routeRules permettent de choisir le mode de rendu route par route :

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },          // HTML généré au build
    '/blog/**': { isr: 3600 },         // généré à la demande, mis en cache 1 h
    '/admin/**': { ssr: false },       // rendu côté client uniquement
  },
})

Côté données, useFetch et useAsyncData s'exécutent pendant le rendu serveur ; un fetch placé dans onMounted ne s'exécute que dans le navigateur. Pour un hébergement statique, nuxt generate produit un fichier HTML par page.

Astro

Astro prérend par défaut toutes les pages en HTML statique au moment du build, et rend les composants React, Vue ou Svelte en HTML sans JavaScript côté client, sauf si on les marque avec une directive client:*. Le seul piège est client:only, qui saute le rendu serveur :

---
import Catalogue from '../components/Catalogue.jsx'
---
<!-- Rendu en HTML au build, puis hydraté : visible par les robots -->
<Catalogue client:load />

<!-- Rendu uniquement dans le navigateur : invisible sans JavaScript -->
<Catalogue client:only="react" />

Pour du rendu à la demande, ajoutez un adaptateur serveur et export const prerender = false sur les pages concernées.

React sans framework, Vue, Angular

Pour une SPA React existante, React Router en mode framework propose une option prerender dans react-router.config.ts qui génère le HTML des routes listées au build. Côté Vue, la voie documentée pour le rendu serveur est Nuxt. Angular intègre le SSR : ng new --ssr pour un nouveau projet, ng add @angular/ssr pour un projet existant, avec un choix de mode par route (RenderMode.Prerender, RenderMode.Server).

Liste de contrôle

Pour vérifier votre site, utilisez le scanner IABIG.

Sources

Vérifiez votre site en 10 secondes avec le scanner de visibilité IA ou le détecteur d'injection de prompt, gratuits.

À lire aussi