Vous avez migré PrestaShop en headless, le front est rapide, l'UX est moderne — et pourtant le trafic organique chute. En architecture découplée, les problèmes d'indexation sont silencieux : aucune erreur visible, juste des pages qui disparaissent des SERP. Voici une méthode de diagnostic structurée et les solutions concrètes.
Les symptômes d'un problème d'indexation
Avant de plonger dans les outils, sachez reconnaître les signaux. En headless PrestaShop, un problème d'indexation se manifeste rarement par une erreur frontale :
- Baisse du nombre de pages indexées dans Search Console sans déindexation volontaire
- Augmentation des "Découvertes, actuellement non indexées" : Google connaît l'URL mais ne l'indexe pas
- Fiches produit absentes des résultats alors qu'elles s'affichent correctement dans le navigateur
- Décalage prix/stock dans les SERP : Google indexe une version périmée rendue côté client
Le piège du headless, c'est que tout fonctionne pour l'utilisateur humain. Le navigateur exécute le JavaScript, hydrate la page, affiche le contenu. Googlebot, lui, peut s'arrêter au HTML initial vide.
Étape 1 — Comparer HTML brut et HTML rendu
Le diagnostic fondamental : que voit un crawler qui n'exécute pas (ou tarde à exécuter) JavaScript ? Comparez les deux versions de la page.
# 1. HTML brut envoyé par le serveur (ce que Googlebot reçoit en premier)
curl -s -A "Googlebot" https://shop.example.com/produit/mon-produit \
| grep -E '<(title|h1)|"price"|product:price'
# Si title, h1 et prix sont absents → contenu CSR-only, problème critique
# Si tout est présent → le HTML initial est correct, chercher ailleurs
Croisez ce résultat avec l'outil Inspection d'URL de Google Search Console. La capture "Page rendue" et l'onglet "HTML" montrent exactement ce que Googlebot a stocké. Si le HTML rendu contient le contenu mais pas le HTML téléchargé, vous dépendez de la seconde vague de crawl — un délai de plusieurs jours, inacceptable pour un catalogue qui change quotidiennement.
Étape 2 — Auditer les directives d'indexation
En headless, les balises meta robots et canonical sont générées par le front (Next.js, Nuxt…), plus par PrestaShop. Une incohérence se glisse facilement entre l'API et le rendu.
# Vérifier les directives sur un échantillon de pages
for url in \
"https://shop.example.com/produit/produit-a" \
"https://shop.example.com/categorie/chaussures" \
"https://shop.example.com/categorie/chaussures?page=2"; do
echo "=== $url ==="
curl -s -A "Googlebot" "$url" \
| grep -iE 'rel="canonical"|name="robots"'
done
Les erreurs les plus fréquentes à traquer :
- Canonical pointant vers l'API au lieu de l'URL front (ex :
api.shop.comau lieu deshop.com) noindexhérité d'un environnement de staging et oublié en production- Canonical auto-référente cassée sur les pages paginées ou filtrées
- Trailing slash incohérent entre le canonical et l'URL réelle, générant des doublons
Dans Next.js App Router, centralisez la génération des metadata côté serveur pour garantir la cohérence :
// app/produit/[slug]/page.tsx
export async function generateMetadata({ params }): Promise<Metadata> {
const product = await getProductBySlug(params.slug);
if (!product || !product.active) {
return { robots: { index: false, follow: false } };
}
const canonicalUrl = `https://shop.example.com/produit/${product.link_rewrite}`;
return {
title: product.meta_title || product.name,
description: product.meta_description,
alternates: { canonical: canonicalUrl },
robots: { index: true, follow: true },
};
}
Étape 3 — Vérifier les codes HTTP
Un produit supprimé du catalogue PrestaShop doit renvoyer un vrai code HTTP — pas une page React affichant "produit introuvable" avec un statut 200. C'est l'erreur de soft 404 la plus courante en headless.
# Un produit désactivé doit répondre 404 ou 410, jamais 200
curl -s -o /dev/null -w "%{http_code}\n" \
https://shop.example.com/produit/produit-supprime
# 200 → soft 404, Google garde la page en index et gaspille du crawl budget
# 404/410 → comportement correct
// app/produit/[slug]/page.tsx
import { notFound } from 'next/navigation';
export default async function ProductPage({ params }) {
const product = await getProductBySlug(params.slug);
// Déclenche un vrai 404 HTTP, pas une page de contenu
if (!product || !product.active) {
notFound();
}
return <ProductDetail product={product} />;
}
Étape 4 — Synchroniser le sitemap avec le catalogue
En headless, le sitemap est souvent généré à part du catalogue PrestaShop. Résultat : il liste des produits désactivés ou oublie les nouveaux. Un sitemap désynchronisé envoie de mauvais signaux à Google.
La bonne pratique : générer le sitemap dynamiquement depuis la source de vérité (l'API PrestaShop), en ne listant que les produits actifs et indexables.
// app/sitemap.ts — généré à la demande, toujours à jour
import { MetadataRoute } from 'next';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const products = await fetchProducts({ active: true, indexable: true });
return products.map((product) => ({
url: `https://shop.example.com/produit/${product.link_rewrite}`,
lastModified: new Date(product.date_upd),
changeFrequency: 'weekly',
priority: 0.8,
}));
}
Pour les gros catalogues, segmentez le sitemap (un index + plusieurs fichiers de 50 000 URLs max) afin de faciliter le suivi de l'indexation par segment dans Search Console.
Étape 5 — Mettre en place un monitoring continu
Le diagnostic ponctuel ne suffit pas : un déploiement peut réintroduire un noindex ou casser le rendu serveur. Automatisez la surveillance des pages critiques.
#!/bin/bash
# monitor-indexation.sh — à lancer en CI ou en cron
URLS=(
"https://shop.example.com/produit/best-seller-1"
"https://shop.example.com/categorie/nouveautes"
)
for url in "${URLS[@]}"; do
html=$(curl -s -A "Googlebot" "$url")
# Le H1 doit être dans le HTML initial
echo "$html" | grep -q "<h1" || echo "ALERTE: H1 absent sur $url"
# Aucun noindex inattendu
echo "$html" | grep -qi 'name="robots"[^>]*noindex' \
&& echo "ALERTE: noindex détecté sur $url"
done
Complétez avec l'API Search Console (URL Inspection) pour récupérer programmatiquement le statut d'indexation réel de Google sur vos URLs prioritaires, et déclencher une alerte dès qu'une page passe en "non indexée".
Checklist de résolution
- Le HTML brut (curl Googlebot) contient titre, H1, description et prix sur les pages produit
- Les canonicals pointent vers l'URL front publique, jamais vers l'API ni le staging
- Aucun
noindexrésiduel hérité d'un environnement de test - Les produits supprimés/désactivés renvoient un 404 ou 410, pas un 200
- Le sitemap est généré depuis l'API et ne liste que des produits actifs
- Un monitoring automatisé vérifie le rendu serveur à chaque déploiement
- L'API Search Console alerte sur les passages en "non indexé"
Conclusion
En PrestaShop headless, l'indexation ne se règle pas une fois pour toutes : c'est un système à surveiller. La cause racine est presque toujours la même — un écart entre ce que voit l'utilisateur et ce que reçoit Googlebot. Le réflexe à ancrer : pour chaque page SEO-critique, le contenu, les directives et le bon code HTTP doivent être présents dans la réponse HTTP initiale du serveur, sans dépendre de JavaScript. Le reste n'est que de l'instrumentation pour détecter les régressions avant Google.
Votre front headless perd des positions sans explication ? Contactez-moi pour un diagnostic d'indexation de votre architecture découplée.