Pourquoi Google n'indexe-t-il pas mon site React ?
Presque toujours parce que la page reçue par un robot n'est pas celle que vous voyez. Une application React rendue dans le navigateur sert une coquille HTML presque vide et la remplit en JavaScript ; Google exécute bien ce JavaScript, mais lors d'un passage ultérieur et non au moment de l'exploration. Tout ce qui se décide au premier passage — page dupliquée ou non, URL canonique, version linguistique applicable — se décide sur cette coquille. Avant de changer quoi que ce soit, lisez donc le HTML brut que votre serveur renvoie réellement, et non la page que votre navigateur affiche.
La page reçue par un robot n'est pas la vôtre
Ouvrez votre site en production et choisissez afficher le code source, pas inspecter. Inspecter montre le DOM une fois votre JavaScript exécuté ; le code source montre les octets réellement envoyés par le serveur. Sur une application React rendue côté client, ces octets se résument le plus souvent à un titre, quelques balises link, un conteneur vide et un bundle de scripts. C'est ce document qu'un robot lit en premier, et sur un site récent ce peut être la seule version lue pendant un bon moment.
Google explique ouvertement traiter le JavaScript en étapes distinctes : il explore l'URL, met la page en file d'attente pour le rendu, puis indexe ce qui en revient — et ce rendu est différé plutôt qu'immédiat. Deux conséquences en découlent. La première est évidente : un contenu qui n'existe qu'une fois le bundle exécuté est indexé tard, quand il l'est. La seconde fait davantage de dégâts parce qu'elle ne se résout jamais d'elle-même. Certains signaux ne sont lus que dans cette première réponse, et aucun rendu ultérieur ne les rattrape.
La balise canonique en est l'exemple le plus net. Les consignes de Google précisent que l'élément canonique se place dans l'en-tête du document, et il en va de même pour les annotations hreflang qui relient les versions linguistiques. Une balise que votre framework injecte ensuite — dans le corps, ou après l'envoi de l'en-tête — est une balise absente au moment de la décision. Dans un navigateur la page paraît correcte, puisque le navigateur l'applique quand même. Elle arrive simplement trop tard pour le seul lecteur dont vous vouliez changer l'avis.
Savoir ce que Google a réellement reçu
Comptez une vingtaine de minutes : cela tranche la question avant toute réécriture. Faites-le sur l'URL de production, pas sur une préversion.
- Lisez la réponse brute. Récupérez la page avec curl ou affichez le code source. Posez-lui deux questions : le texte sur lequel vous voulez vous positionner figure-t-il dans ce contenu, et la balise canonique se trouve-t-elle dans l'élément head plutôt que plus bas dans le document ? Si l'une des réponses est non, vous tenez le problème.
- Dans la Search Console, lisez la page explorée et non le test en direct. L'inspection d'URL montre les deux. Le test en direct est une récupération faite à l'instant ; le HTML exploré est ce qui a réellement été stocké la dernière fois. Quand les deux divergent, croyez la copie explorée — cette divergence est déjà le diagnostic.
- Demandez directement une page interne. Les routeurs côté client produisent parfois des chemins que le serveur ne sert pas. Ouvrez une page interne dans un onglet vierge, ou récupérez-la avec curl, et vérifiez qu'elle renvoie bien son propre contenu au lieu de rediriger vers l'accueil ou de renvoyer une page annonçant qu'il n'y a rien tout en signalant un succès.
- Vérifiez que vous servez un seul hôte, pas trois. Demandez la forme avec www, la forme sans www et la forme non chiffrée de votre domaine. Deux des trois devraient rediriger vers la troisième. Si plusieurs servent le site entier, vous avez publié le même site à deux adresses et laissé Google choisir.
La panne qui se cachait de nos propres tests
Nous publions AgentCeres — l'AI Growth Officer, sur agentceres.com — au-dessus d'un framework React, et nous avons perdu des mois d'indexation à cause d'une variante de ce problème que chacune de nos vérifications déclarait saine. L'histoire mérite d'être racontée en entier, car chaque étape a échoué d'une manière qui ressemblait à une réussite.
La Search Console signalait un large bloc de nos pages comme dupliquées sans URL canonique sélectionnée par l'utilisateur : elle n'avait trouvé aucune canonique digne de confiance et en avait choisi une elle-même. La balise était bien là. Elle se trouvait à une quarantaine de kilo-octets dans la réponse, parce que le framework diffuse les métadonnées en streaming sur toute page rendue dynamiquement, alors que l'élément head s'était refermé à environ un kilo-octet et demi du début. Tous les navigateurs l'appliquaient. Seul le premier passage d'exploration ne la voyait jamais.
Si ces pages étaient dynamiques, c'est à cause de la deuxième panne. Une douzaine de routes que nous croyions pré-rendues à la compilation avaient cessé de l'être sans prévenir : un composant d'en-tête partagé appelait un utilitaire de traduction qui lit les en-têtes de la requête, et lire un en-tête de requête suffit à rendre une page dynamique. Le tableau des routes de la compilation continuait pourtant de les afficher comme statiques. L'inventaire des fichiers HTML produits n'en contenait aucune. Le résumé et l'artefact se contredisaient, et nous lisions le résumé.
La troisième partie est celle à retenir. Les frameworks qui diffusent les métadonnées tiennent en général une liste de robots qui reçoivent l'ancien comportement bloquant, et le nôtre en fournissait une par défaut. Googlebot n'y figurait pas. L'outil d'inspection de Google — le robot derrière le bouton de test en direct — si. Le bouton sur lequel nous appuyions pour contrôler notre travail récupérait donc la bonne version à chaque fois, tandis que les explorations ordinaires continuaient de recevoir la mauvaise. Si votre outil de vérification est un cas particulier à l'intérieur de votre propre pile, ce n'est pas une vérification.
Deux notes de bas de page, peu coûteuses. Notre hôte en www servait le site entier sans redirection : Google l'avait indexé comme une seconde copie et rétrogradé l'adresse figurant dans notre sitemap ; deux lignes de middleware ont suffi. Et si le réglage par robot vous tente, rappelez-vous qu'un CDN placé devant votre origine met généralement en cache sans se soucier de qui a demandé : la variante qui atterrit dans le cache est celle que recevra le robot suivant. Derrière un CDN, traiter un robot à part n'est pas une règle sur laquelle s'appuyer.
Quoi changer, dans l'ordre qui rapporte
- Pré-rendez les pages que vous voulez voir trouvées. Pages marketing, documentation, tout ce qu'un inconnu pourrait rechercher : générez le HTML à la compilation. La sortie statique contourne tout le problème, puisque le premier passage contient déjà le contenu et les balises.
- Rendez côté serveur ce qui doit vraiment être dynamique. Une page qui dépend de la requête peut elle aussi renvoyer un HTML complet. Ce qui compte, c'est que la première réponse soit complète, pas qu'elle ait été calculée à l'avance.
- Gardez titre, description, canonique et balises de langue dans l'en-tête de cette première réponse. Si votre framework peut les différer, trouvez le réglage qui l'en empêche, puis confirmez la correction en lisant le HTML brut et non le DOM rendu. C'est l'étape que l'on croit avoir faite.
- Donnez à chaque page une vraie URL et un vrai lien vers elle. Les routes cachées derrière un fragment ou un gestionnaire de clic ne sont pas explorables. Les robots suivent les éléments d'ancrage dotés d'un href : une navigation faite de boutons est une navigation que Google ne peut pas parcourir.
- Choisissez un hôte et redirigez les autres. Soumettez ensuite un sitemap ne listant que la forme retenue, pour que vos propres déclarations ne se contredisent pas.
Rien de tout cela n'est une stratégie de référencement. C'en est la condition préalable, et cela vaut la peine d'y consacrer un après-midi précisément pour ne plus jamais y penser. Une fois vos pages réellement lues, les questions qui décident de leur rendement sont pourquoi une page tout à fait correcte ne reçoit toujours aucun trafic et d'où viennent réellement les premiers visiteurs. Et si vous préférez ne pas gérer cette chaîne du tout, un générateur de site statique doté d'un éditeur adossé à Git évite la question du rendu par construction, puisque ce qu'il déploie est déjà du HTML fini.
FAQ
- Google indexe-t-il seulement les sites en JavaScript ?
- Oui. Googlebot exécute le JavaScript et indexe ce que la page devient, mais il le fait lors d'un passage différé et non au moment de l'exploration : tout ce qui n'existe qu'après votre bundle est donc indexé plus tard et moins sûrement que le contenu déjà présent dans le HTML. Les éléments lus uniquement dans cette première réponse — dont la balise canonique et les annotations hreflang — ne sont pas rattrapés par le rendu. Voyez le rendu côté client comme un délai assorti d'un risque, non comme un blocage absolu.
- Faut-il du rendu côté serveur pour corriger cela ?
- En général non. Le pré-rendu statique suffit pour les pages qu'un inconnu chercherait, et il est plus simple et moins coûteux à exploiter que le rendu serveur. Réservez ce dernier aux pages dont le contenu dépend vraiment de qui les demande. La règle qui compte n'est pas la technique retenue mais le fait que la première réponse soit déjà complète : une page pré-rendue et une page rendue côté serveur y satisfont, une page rendue côté client non.
- Le test en direct de la Search Console semble parfait : pourquoi la page n'est-elle pas indexée ?
- Parce que le test en direct est une récupération et un rendu effectués à la demande, et que votre pile peut lui servir une réponse différente de celle qu'obtient une exploration ordinaire — la nôtre le faisait, la liste par défaut des robots recevant des métadonnées bloquantes incluant l'outil d'inspection de Google mais pas Googlebot. Lisez plutôt le HTML exploré et stocké dans ce même rapport. Quand les deux divergent, c'est la copie explorée qui est indexée, et le test en direct vous parle d'une page servie à personne d'autre.
Want this done for you?
AgentCeres is a managed AI marketing team — specialists draft the work, you approve what ships. 14-day free trial, from $39/month.