Un site React ou Next.js peut être magnifique à l'écran et pourtant quasiment invisible pour Google. Le problème ne se voit pas en le visitant normalement : il faut regarder ce que le serveur envoie avant que le JavaScript s'exécute. Voici pourquoi ça arrive, comment le vérifier en moins d'une minute avant de vendre une refonte, et ce qui corrige vraiment le problème.
Pourquoi un site 100 % JavaScript peut être invisible pour Google
Un site classique (HTML/PHP/WordPress) renvoie une page déjà complète dès la première requête : le texte, les liens, la structure sont là. Un site en React pur (sans couche de rendu serveur ajoutée) fonctionne différemment : le serveur renvoie une coquille HTML quasiment vide, et c'est le JavaScript, exécuté ensuite dans le navigateur, qui construit tout le contenu visible. Cette technique s'appelle le rendu côté client (CSR).
Google gère ce cas, mais pas instantanément. D'après la documentation officielle de Google Search Central sur les bases du JavaScript SEO, l'exploration d'une page passe par trois étapes séparées : le robot récupère d'abord le HTML brut, la page est ensuite mise en file d'attente pour être rendue dans un navigateur (Chromium headless) qui exécute le JavaScript, et c'est seulement le résultat de ce rendu qui est indexé. Le rendu n'est pas immédiat : il dépend des ressources que Google alloue à ce moment-là, ce qui crée un décalage entre la publication d'une page et sa vraie indexation. Sur un site qui change souvent (annonces, offres, actus), ce délai peut suffire à rater une fenêtre de visibilité.
Le guide Rendering on the Web de web.dev tranche d'ailleurs sans ambiguïté sur le sujet : le rendu serveur (SSR) et la génération statique (SSG) livrent une meilleure performance de chargement qu'un rendu 100 % client pour un site orienté contenu, ce qui veut dire que le choix le plus sûr pour le SEO est aussi, la plupart du temps, le plus rapide pour l'utilisateur.
Comment détecter un shell JavaScript en 30 secondes
Pas besoin d'outil payant pour vérifier si un site pose ce problème. Deux méthodes gratuites, à faire dans cet ordre :
- Afficher le code source brut (clic droit > Afficher le code source de la page, ou
Ctrl+U). C'est exactement ce qu'un robot voit avant exécution du JavaScript. Si le<body>est quasiment vide, avec juste une<div id="root">ou<div id="__next">et une poignée de balises<script>, c'est un shell côté client. - Comparer avec l'onglet Éléments de l'inspecteur (
F12), qui montre le DOM une fois le JavaScript exécuté. Si le contenu visible à l'écran n'existe que là, et jamais dans le code source brut, la différence entre les deux confirme le diagnostic.
Un repère simple : un shell vide typique contient moins de 3 liens <a> et moins de 500 caractères de texte lisible dans le HTML brut, alors que le rendu final peut afficher des dizaines de liens et plusieurs milliers de caractères. Ce n'est pas propre à React : ça touche tout site construit avec un framework JavaScript sans couche de rendu serveur (Vue, Angular, ou un site Wix/Framer mal configuré), mais React et ses générateurs de projet historiques (Create React App, un simple build Vite) restent les cas les plus fréquents rencontrés côté freelances, parce que beaucoup de portfolios et vitrines sont montés vite avec ces outils, sans jamais ajouter Next.js ou une autre couche par-dessus.
Les solutions : SSR, SSG et prérendu
La bonne nouvelle, c'est que le problème se résout au niveau du framework, pas en réécrivant le site de zéro.
Passer par Next.js (ou un framework équivalent avec rendu serveur). Depuis l'App Router de Next.js 13+, les pages sont des composants serveur par défaut : le HTML complet est généré côté serveur avant d'être envoyé au navigateur, sans configuration supplémentaire à ajouter (documentation officielle Next.js, Server and Client Components). Migrer un projet React pur vers Next.js reste le chemin le plus direct pour un freelance qui veut garder l'écosystème React sans hériter du problème d'indexation.
Génération statique (SSG) quand le contenu ne change pas à chaque visite (site vitrine, portfolio, page catalogue peu mouvante) : les pages sont pré-générées en HTML au moment du build, livrées telles quelles, sans aucun calcul serveur au moment de la requête. C'est souvent l'option la plus rapide et la plus simple à héberger pour ce type de site.
Rendu dynamique ou prérendu ponctuel, en dernier recours, si une refonte complète vers un framework SSR n'est pas envisageable dans le budget du client à court terme : un service externe génère une version HTML statique de chaque page pour les robots, pendant que les visiteurs humains gardent la version React classique. C'est une rustine, pas une solution durable, mais elle peut dépanner le temps de planifier une vraie migration.
Un piège plus discret : le formulaire de contact invisible
Un site n'a pas besoin d'être un shell complet pour cacher un problème JavaScript. Cas fréquent : une page de contact avec du texte, une mise en page normale, tout semble en ordre, mais le formulaire lui-même (les balises <form>, <input>, <textarea>) n'existe que dans le DOM rendu, injecté par un script après coup. Le reste de l'audit d'un tel site paraît sain, ce qui rend ce cas plus insidieux qu'un shell complet : rien n'alerte au premier coup d'œil, sauf à vérifier spécifiquement cette page.
Sur les audits qu'on lance chez Citylead, ce cas revient régulièrement sur des sites qui utilisent un composant de formulaire tiers chargé en différé pour des raisons de performance, sans que personne n'ait vérifié l'impact sur la lecture du code source brut.
Ce que l'audit Citylead repère automatiquement
Le moteur d'audit de Citylead applique exactement le repère décrit plus haut sur le HTML brut de chaque site analysé : moins de 3 liens et moins de 500 caractères de texte visible suffisent à signaler un shell côté client, et un audit sur un tel site est marqué comme partiel plutôt que noté comme si le contenu manquant était un vrai manque du site (un shell invisible pour un robot n'est pas la même chose qu'un site mal fait). Le même repère sert aussi à isoler, page de contact par page de contact, les formulaires probablement injectés en JavaScript, un signal distinct qui n'apparaît nulle part dans un audit SEO générique.
Pour aller plus loin sans deviner, l'audit propose un rendu optionnel de la page via une clé scrape.do fournie par l'utilisateur (BYOK) : la page est alors chargée dans un vrai navigateur headless, le JavaScript s'exécute, et l'audit se relance sur le contenu réellement affiché plutôt que sur le shell vide. De quoi trancher en quelques secondes, avant un premier appel avec le prospect, si son site React est un problème SEO réel ou un site déjà bien configuré derrière une façade qui semblait suspecte.