Vous avez 12 000 pages dans votre sitemap, mais Search Console en affiche 4 200 indexées. Les 7 800 restantes sont réparties entre "Discovered – currently not indexed", "Crawled – currently not indexed" et une poignée de statuts plus exotiques. Ce n'est pas un bug de Google. C'est un diagnostic à mener.
Les raisons pour lesquelles Google refuse d'indexer une page forment un arbre de décision à plusieurs niveaux : accès technique, directives explicites, rendu, qualité perçue, et budget de crawl. Chaque nœud de cet arbre a ses propres outils de diagnostic et ses propres solutions. Voici la méthode complète.
Niveau 1 : les blocages d'accès pur — robots.txt et erreurs serveur
Avant même de parler d'indexation, il faut que Googlebot puisse atteindre la page. Deux causes triviales mais fréquentes : le fichier robots.txt bloque le crawl, ou le serveur retourne une erreur.
Blocage par robots.txt
Le rapport "Indexation des pages" de Search Console distingue explicitement "Blocked by robots.txt". Mais le piège n'est pas toujours dans les règles que vous avez écrites — c'est souvent dans celles héritées d'un environnement de staging, d'une migration, ou d'un outil de déploiement qui a laissé une règle traînante.
Cas classique : une migration de Shopify vers une stack custom. L'ancien robots.txt servi par Shopify interdisait le crawl de /collections/* avec des paramètres spécifiques. Le nouveau serveur reprend un fichier robots.txt copié-collé sans nettoyage. Résultat : 3 000 pages de catégories devenues invisibles.
Vérification immédiate avec l'outil de test de Search Console, ou en CLI :
# Télécharger et inspecter le robots.txt tel que Googlebot le voit
curl -A "Googlebot" https://www.votresite.fr/robots.txt
# Vérifier qu'une URL spécifique n'est pas bloquée
# (utiliser l'outil de test robots.txt de Search Console
# ou un parser local)
pip install robotexclusionrulesparser
python3 -c "
import robotexclusionrulesparser as rerp
r = rerp.RobotExclusionRulesParser()
r.fetch('https://www.votresite.fr/robots.txt')
print(r.is_allowed('Googlebot', '/catalogue/chaussures-running/'))
"
Le point subtil : robots.txt empêche le crawl, pas l'indexation. Si Google connaît l'URL par un lien externe ou un sitemap, il peut l'indexer sans la crawler — vous verrez alors une page indexée sans snippet, avec la mention "Aucune information disponible pour cette page". Pour réellement empêcher l'indexation, il faut une directive noindex — mais celle-ci nécessite que la page soit crawlée. C'est un paradoxe documenté par Google dans les guidelines sur robots.txt.
Pour aller plus loin sur la syntaxe et les erreurs courantes de ce fichier, consultez le guide complet robots.txt.
Erreurs serveur (5xx) et timeouts
Un Googlebot qui reçoit des 503 répétés va espacer ses visites, puis abandonner. Les 5xx intermittents sont les plus vicieux : votre monitoring Uptime dit 99,5 % de disponibilité, mais ces 0,5 % tombent systématiquement sur les pics de crawl, quand Googlebot envoie 15 requêtes/seconde sur votre catalogue.
Diagnostic dans les logs serveur :
# Extraire les requêtes Googlebot qui ont reçu un 5xx
# dans les logs Nginx (format combined)
awk '(/Googlebot/ && / 50[0-9] /)' /var/log/nginx/access.log \
| awk '{print $1, $4, $7, $9}' \
| sort -t'[' -k2 \
| head -50
Si vous constatez des clusters de 5xx sur des plages horaires précises, vérifiez la corrélation avec le rapport "Statistiques sur l'exploration" de Search Console. Un taux de réponse serveur moyen supérieur à 500 ms est déjà un signal d'alerte — Google documente que la vitesse du serveur influence directement le volume de crawl accordé.
Niveau 2 : les directives d'indexation contradictoires
La page est accessible, Googlebot la crawle, mais une directive lui dit de ne pas l'indexer. Le diagnostic ici est un jeu de détective : les directives peuvent venir de multiples sources, et elles se contredisent parfois.
Les sources de noindex
Une directive noindex peut être présente dans :
- La balise
<meta name="robots" content="noindex">dans le<head> - L'en-tête HTTP
X-Robots-Tag: noindex - Une combinaison des deux
L'en-tête HTTP est souvent le coupable oublié. Un reverse proxy Nginx ou un CDN peut injecter un X-Robots-Tag sans que le développeur frontend ne le sache.
# Configuration Nginx qui injecte un noindex sur tout /staging/
# Problème : après une migration, le block a été copié
# vers la config de production
location /catalogue/archive/ {
add_header X-Robots-Tag "noindex, nofollow" always;
proxy_pass http://backend:3000;
}
Vérification rapide :
# Inspecter les en-têtes HTTP d'une URL spécifique
curl -sI -A "Googlebot" https://www.votresite.fr/catalogue/archive/soldes-2024/ \
| grep -i "x-robots-tag"
Pour un audit complet des directives noindex, nofollow et de leurs interactions, l'article sur meta robots et leurs variantes couvre tous les cas de figure.
Le piège du canonical qui pointe ailleurs
Une page avec un <link rel="canonical"> pointant vers une autre URL ne sera pas indexée à son URL propre. Google traitera la page courante comme un duplicat et consolidera les signaux vers l'URL canonique déclarée.
Le scénario le plus fréquent : un système de filtres sur un e-commerce qui génère des URLs paramétrées (/chaussures?color=rouge&size=42). Le CMS injecte un canonical vers /chaussures sur toutes les variantes. Si c'est volontaire, parfait. Si les pages filtrées ont un contenu unique et un potentiel de trafic long-tail, vous venez de sacrifier des milliers de pages indexables.
Vérifiez dans Search Console avec l'outil "Inspection de l'URL" : le champ "Canonical déclaré par l'utilisateur" vs "Canonical sélectionné par Google" révèle les désaccords. Quand Google ignore votre canonical, c'est qu'il a détecté une incohérence — contenu identique avec un canonical vers une URL qui retourne un 404, boucles de canonicals, ou canonical vers un domaine différent.
Le guide sur les canonical URLs détaille les patterns corrects et les erreurs qui déclenchent un rejet par Google.
Niveau 3 : le rendu JavaScript — la cause n°1 des problèmes fantômes
C'est ici que les diagnostics deviennent complexes. La page retourne un 200, aucun noindex, un canonical correct — mais le contenu vu par Googlebot n'est pas celui que vous voyez dans votre navigateur.
Le modèle de rendu en deux phases de Google
Google crawle d'abord le HTML brut (phase 1), puis place la page dans une file d'attente pour le rendu JavaScript (phase 2). La documentation officielle sur le rendu JavaScript confirme que ce délai peut aller de quelques secondes à plusieurs jours.
Entre les deux phases, si votre HTML initial ne contient pas le contenu principal, Google voit une page vide — ou pire, une page avec uniquement le shell de votre application React/Vue/Angular. Cette page vide peut être classée comme "thin content" et ne jamais recevoir de priorité pour la phase de rendu.
Diagnostic concret : comparez le HTML initial et le DOM après rendu.
// Script Node.js pour comparer le HTML brut vs le DOM rendu
// Utilise puppeteer (ce que Googlebot utilise via Chromium)
const puppeteer = require('puppeteer');
const https = require('https');
async function compareRender(url) {
// Phase 1 : HTML brut (ce que Googlebot voit initialement)
const rawHtml = await new Promise((resolve, reject) => {
https.get(url, (res) => {
let data = '';
res.on('data', chunk => data += chunk);
res.on('end', () => resolve(data));
}).on('error', reject);
});
// Phase 2 : DOM après exécution JavaScript
const browser = await puppeteer.launch({
args: ['--no-sandbox'],
headless: 'new'
});
const page = await browser.newPage();
await page.setUserAgent(
'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) ' +
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 ' +
'Mobile Safari/537.36 (compatible; Googlebot/2.1; ' +
'+http://www.google.com/bot.html)'
);
await page.goto(url, { waitUntil: 'networkidle0', timeout: 30000 });
const renderedHtml = await page.content();
await browser.close();
// Comparaison basique : le contenu principal est-il dans le HTML brut ?
const h1InRaw = (rawHtml.match(/<h1[^>]*>(.*?)<\/h1>/i) || [])[1];
const h1InRendered = (renderedHtml.match(/<h1[^>]*>(.*?)<\/h1>/i) || [])[1];
console.log(`URL: ${url}`);
console.log(`H1 dans HTML brut: ${h1InRaw || 'ABSENT'}`);
console.log(`H1 après rendu JS: ${h1InRendered || 'ABSENT'}`);
console.log(`Title dans HTML brut: ${
(rawHtml.match(/<title>(.*?)<\/title>/i) || [])[1] || 'ABSENT'
}`);
console.log(`Longueur HTML brut: ${rawHtml.length} chars`);
console.log(`Longueur après rendu: ${renderedHtml.length} chars`);
if (!h1InRaw && h1InRendered) {
console.log('⚠ PROBLÈME : le contenu principal dépend du JS');
}
}
compareRender('https://www.votresite.fr/produit/chaussure-trail-x500');
Si le H1 est absent du HTML brut mais présent après rendu, vous dépendez entièrement de la phase 2 de Google. Pour un site de 15 000 pages produit, cela signifie que Google doit exécuter 15 000 rendus JavaScript — un coût de crawl budget massif.
Le scénario concret : migration SPA vers SSR
Un e-commerce mode de 18 000 pages, initialement en React SPA (Create React App), migre vers Next.js avec SSR. Avant la migration : 6 200 pages indexées sur 18 000. Le reste bloqué en "Discovered – currently not indexed" depuis 8 mois.
Après la migration SSR, le HTML servi contient directement le contenu produit, les meta descriptions, les données structurées. En 6 semaines : 14 800 pages indexées. Trafic organique : +340 % sur les pages produit long-tail. Les 3 200 pages restantes non indexées correspondent à des variantes de produits avec contenu quasi-identique — un problème de qualité, plus de rendu.
Le point d'attention pendant une telle migration : assurez-vous que les anciennes URLs retournent des 301 propres vers les nouvelles, et que le sitemap XML est mis à jour le jour même de la bascule. Un sitemap contenant des URLs qui 301 ralentit considérablement la redécouverte.
Les ressources bloquées qui cassent le rendu
Même avec du SSR, si Googlebot ne peut pas charger vos fichiers CSS/JS critiques (bloqués par robots.txt, servis depuis un CDN qui bloque les bots, ou en timeout), le rendu sera incomplet. L'outil "Inspection de l'URL" de Search Console inclut un onglet "Ressources chargées" qui liste les ressources bloquées ou en erreur.
Le piège courant : un CDN tiers qui rate-limite les requêtes venant d'IP Google. Vos polices web hébergées sur un sous-domaine cdn.votresite.fr avec un robots.txt qui bloque tout. Ou un script tiers de personnalisation (A/B testing, recommandation produit) qui échoue silencieusement et empêche le rendu du contenu principal.
Google a d'ailleurs mis à jour sa documentation pour clarifier que les resource hints sont ignorés par le crawler — les preconnect, prefetch et preload n'ont aucun effet sur la façon dont Googlebot charge les ressources.
Niveau 4 : la qualité perçue — le filtre invisible
Vous avez tout vérifié : accès OK, pas de noindex, canonical correct, rendu complet. Pourtant, Search Console affiche "Crawled – currently not indexed". Google a vu la page, l'a comprise, et a décidé qu'elle ne méritait pas d'être dans l'index.
"Crawled – currently not indexed" vs "Discovered – currently not indexed"
Ces deux statuts reflètent des problèmes très différents :
"Discovered – currently not indexed" : Google connaît l'URL (via sitemap, lien interne, etc.) mais ne l'a pas encore crawlée. Causes probables : crawl budget insuffisant, priorité trop basse, serveur trop lent. C'est un problème d'accès.
"Crawled – currently not indexed" : Google a crawlé la page et a choisi de ne pas l'indexer. C'est un jugement de qualité. La page est considérée comme ayant une valeur ajoutée insuffisante pour l'index.
Les critères de qualité qui déclenchent un rejet
Google ne documente pas explicitement les seuils, mais l'expérience sur des centaines de sites fait émerger des patterns :
Contenu thin ou dupliqué : une fiche produit de 50 mots, identique à 200 autres fiches avec uniquement le nom de la couleur qui change. Google en indexe une ou deux et écarte le reste. Ce n'est pas un bug — c'est une décision éditoriale algorithmique.
Pages de pagination profondes : /catalogue/chaussures?page=47 sur un site qui a 3 produits par page. Google juge (à raison) que la valeur marginale de la page 47 est proche de zéro.
Pages générées automatiquement sans contenu unique : tags WordPress générés automatiquement, pages de résultats de recherche interne indexables, pages de combinaisons de filtres. Un site e-commerce avec 200 marques × 50 tailles × 30 couleurs peut générer 300 000 URLs de filtres. Google n'en indexera qu'une infime fraction.
Signal de liens internes faible : une page orpheline, ou accessible uniquement via un lien dans le footer enterré à 8 clics de la homepage, envoie un signal de faible importance au crawler.
Diagnostic avec Screaming Frog
Pour identifier les pages à faible valeur ajoutée qui risquent d'être rejetées :
# Avec Screaming Frog en mode CLI (licence payante requise)
# Exporter les pages avec contenu court + faible profondeur de lien
ScreamingFrogSEOSpiderCli \
--crawl "https://www.votresite.fr" \
--headless \
--output-folder "/tmp/audit-indexation" \
--export-tabs "Internal:HTML" \
--config "/path/to/config.seospiderconfig"
# Ensuite, filtrer en Python/pandas :
# - Word count < 100
# - Crawl depth > 4
# - Inlinks < 2
# Ce sont vos candidates au "Crawled – not indexed"
Croisez cette liste avec les données de Search Console (export du rapport d'indexation) pour confirmer quelles pages sont effectivement rejetées. Si 80 % de vos pages "Crawled – not indexed" ont moins de 100 mots uniques, la solution n'est pas technique — elle est éditoriale.
Niveau 5 : le crawl budget — quand la taille devient un problème
Pour un site de 500 pages, le crawl budget est un non-sujet. Google crawlera tout en quelques heures. Pour un site de 50 000 pages avec des facettes, des paginations et des versions linguistiques, c'est un facteur déterminant.
Le crawl budget se décompose en deux composantes documentées par Google : le crawl rate limit (combien de requêtes par seconde votre serveur peut encaisser sans dégrader l'expérience utilisateur) et le crawl demand (à quel point Google juge vos pages dignes d'être crawlées).
Calculer votre ratio d'efficacité de crawl
Récupérez les données du rapport "Statistiques sur l'exploration" de Search Console :
- Nombre total de requêtes de crawl sur 90 jours
- Nombre d'URLs uniques crawlées
- Taille totale de votre site (URLs dans le sitemap + URLs découvertes)
Si Google crawle 45 000 requêtes sur 90 jours mais que 60 % de ces requêtes vont vers des URLs de filtres/facettes que vous ne souhaitez pas indexer, vous gaspillez votre crawl budget. Le ratio d'efficacité = URLs indexables crawlées / Total de requêtes de crawl. Un ratio inférieur à 50 % indique un problème sérieux de crawl waste.
Réduire le crawl waste
La solution passe par une combinaison de :
- Blocage des URLs non indexables dans robots.txt (facettes, tri, recherche interne)
- Suppression de ces URLs du maillage interne (pas de lien cliquable = pas de découverte)
- Nettoyage du sitemap : n'inclure que les URLs que vous souhaitez réellement voir indexées
Un sitemap contenant 40 000 URLs dont 25 000 sont en noindex ou en redirection 301 est un signal négatif. Google l'utilise comme indicateur de la fiabilité de vos signaux : si votre sitemap est pollué, vos autres directives sont considérées avec plus de scepticisme.
Niveau 6 : les signaux internationaux mal configurés
Pour les sites multilingues, les problèmes de hreflang sont une cause fréquente de non-indexation — ou plus exactement, d'indexation de la mauvaise version linguistique.
Un hreflang mal configuré (code langue incorrect, URLs en erreur, annotations non réciproques) peut amener Google à considérer vos versions comme des duplicats plutôt que des alternatives linguistiques. Résultat : une seule version est indexée, les autres sont consolidées.
L'article sur les erreurs hreflang courantes couvre les patterns de configuration corrects. Le point spécifique à l'indexation : si votre version /fr/ et votre version /en/ ont des hreflang qui ne pointent pas mutuellement l'une vers l'autre, Google peut traiter /fr/ comme un duplicat de /en/ et ne pas l'indexer.
Méthode de diagnostic systématique : l'arbre de décision
Quand vous constatez qu'une page n'est pas indexée, suivez cet arbre dans l'ordre :
Étape 1 — Inspection de l'URL dans Search Console. Quel statut exact ? Chaque statut pointe vers une catégorie de cause différente.
Étape 2 — Si "Blocked by robots.txt" : vérifiez robots.txt (y compris les X-Robots-Tag HTTP). Si le blocage est intentionnel, rien à corriger.
Étape 3 — Si "Noindex detected" : recherchez la directive dans la source HTML ET dans les en-têtes HTTP. N'oubliez pas les en-têtes injectés par le CDN ou le reverse proxy.
Étape 4 — Si "Alternate page with proper canonical" : vérifiez votre implémentation canonical. La page est-elle réellement un duplicat ? Si non, corrigez le canonical pour qu'il pointe vers lui-même.
Étape 5 — Si "Discovered – currently not indexed" : c'est un problème de crawl budget ou de vitesse serveur. Vérifiez le temps de réponse serveur dans les stats de crawl, améliorez le maillage interne vers ces pages, nettoyez le sitemap.
Étape 6 — Si "Crawled – currently not indexed" : c'est un jugement de qualité. Évaluez le contenu, le maillage interne, le ratio de contenu unique. Enrichissez la page ou consolidez-la avec d'autres pages similaires.
Étape 7 — Vérification du rendu JS : utilisez le test en live de l'inspection d'URL, onglet "HTML affiché". Comparez avec le contenu attendu. Si le contenu est absent, c'est un problème de rendu côté client.
Ce diagnostic prend 5 minutes par page. Sur un site de 15 000 pages avec 8 000 non indexées, vous ne pouvez pas le faire manuellement. Des outils comme Screaming Frog (pour le crawl en masse), l'API Search Console (pour extraire les statuts d'indexation en batch), et un outil de monitoring comme SEOGard (pour détecter les régressions d'indexation dès qu'elles apparaissent — une page indexée qui passe soudainement en "noindex" après un déploiement) sont indispensables pour traiter le problème à l'échelle.
Le cas des meta descriptions et du contenu enrichi
Un point souvent négligé : même quand Google indexe une page, la qualité des meta données influence la rétention dans l'index à long terme. Une page indexée mais qui ne génère aucun clic parce que sa meta description est vide ou incohérente finit par perdre sa position, puis potentiellement par être désindexée.
De même, les pages qui ont des problèmes de Core Web Vitals sévères — un LCP à 8 secondes, un CLS qui fait sauter le layout — sont indexées mais classées tellement bas qu'elles sont fonctionnellement invisibles. L'indexation sans le classement ne vaut rien.
Synthèse
Les problèmes d'indexation ne sont jamais une cause unique. C'est une cascade de filtres — accès, directives, rendu, qualité, budget — et votre page doit passer chaque filtre pour atteindre l'index. Commencez toujours par le statut exact dans Search Console, remontez l'arbre de décision, et corrigez le premier blocage identifié avant de chercher plus loin. Sur les sites de grande taille, un monitoring continu qui détecte les changements de statut d'indexation au fil des déploiements — comme celui offert par SEOGard — transforme un diagnostic réactif en prévention systématique.