BigCommerce : canonicals staging en prod, −38% trafic

Migration PrestaShop vers BigCommerce : les canonicals pointent encore vers le staging

Jeudi 14h. L'agence envoie un mail de félicitations : la migration PrestaShop 1.7 vers BigCommerce est live depuis 48 heures. Le checkout fonctionne. Les fiches produit s'affichent. Le client — une marque de cosmétiques bio française, 8 200 pages indexées, 140K visites organiques mensuelles — ouvre une bouteille. Personne ne regarde le code source. Trois semaines plus tard, le trafic organique a chuté de 38%. Google n'a pas pénalisé le site. Il a simplement obéi aux canonicals — qui pointaient vers staging-xyz.mybigcommerce.com.

Lundi matin, T+18 jours — le tableau de bord vire au rouge

Le responsable e-commerce ouvre GA4 le lundi à 9h12. Le week-end a fait 1 100 sessions organiques. La moyenne des six derniers week-ends était de 3 400. Il vérifie une seconde fois. Pas une erreur de filtre. Pas un problème de tracking.

Premier réflexe : la Search Console. L'onglet Performances montre une courbe descendante progressive qui a démarré cinq jours après la mise en prod. Pas un effondrement brutal — une érosion lente, 2 à 4% par jour. Le type de courbe que personne ne remarque en pleine période de migration, parce que tout le monde surveille les erreurs 404 et les redirections.

Le lead SEO de l'agence est alerté à 10h15. Il lance un crawl Screaming Frog sur le domaine de production www.cosmetiques-bio.fr (nom anonymisé). Les résultats tombent en 12 minutes : 7 843 pages crawlées, 7 841 contiennent une balise canonical. Jusque-là, normal. Sauf que 6 912 d'entre elles pointent vers staging-3f7a.mybigcommerce.com.

L'hypothèse initiale est un problème de cache CDN. BigCommerce utilise Akamai. Peut-être qu'une ancienne version HTML est servie depuis un edge node mal purgé. L'équipe ops invalide le cache global. Nouveau crawl à 11h40 : même résultat. 6 912 canonicals staging.

Deuxième hypothèse : un setting BigCommerce mal configuré dans le panneau admin. Le channel storefront affiche pourtant le bon domaine, www.cosmetiques-bio.fr. Le SSL est actif. Le domaine est vérifié.

À 14h, le lead SEO fait un curl direct sur une fiche produit :

curl -s https://www.cosmetiques-bio.fr/creme-hydratante-aloe-vera/ | grep -i 'canonical'

Le résultat :

<link rel="canonical" href="https://staging-3f7a.mybigcommerce.com/creme-hydratante-aloe-vera/" />

C'est net. Le HTML servi en production contient un hostname staging dans la balise canonical. Google reçoit cette instruction depuis 18 jours. Et Google obéit aux canonicals. Mécaniquement, il a commencé à considérer que l'URL canonique de chaque page est sur le staging — un domaine que Googlebot ne peut pas résoudre, puisqu'il est protégé par un basic auth et un robots.txt en Disallow: /.

Le résultat : Google déréférence progressivement les pages de production. Pas de pénalité manuelle. Pas de core update. Juste une directive canonical parfaitement respectée, qui pointe vers un trou noir.

Le moment où l'équipe comprend l'ampleur : un export Search Console montre que 4 200 pages ont vu leurs impressions tomber à zéro. Les positions moyennes sur les 50 requêtes principales sont passées de 6.2 à 23.8 en 18 jours.

Le bug : un hostname staging codé en dur dans les meta BigCommerce

Pour comprendre le problème, il faut revenir au fonctionnement des canonicals dans BigCommerce.

Comment BigCommerce génère les canonicals

BigCommerce utilise un système de thèmes basé sur Stencil. Le template de base — Cornerstone — inclut dans le <head> un helper Handlebars qui injecte automatiquement la balise canonical :

<!-- base.html dans le thème Stencil / Cornerstone -->
<head>
    {{#if page.canonical}}
        <link rel="canonical" href="{{page.canonical}}" />
    {{/if}}
    <!-- ... -->
</head>

La variable {{page.canonical}} est construite côté serveur par BigCommerce. Elle dépend d'un paramètre central : le Storefront URL défini dans le panneau d'administration, sous Settings → Storefront → URL.

En environnement staging, ce champ contient le sous-domaine provisoire attribué par BigCommerce : staging-3f7a.mybigcommerce.com. Lors du passage en production, l'équipe doit configurer le domaine personnalisé, ce qui met à jour ce paramètre.

Ce qui s'est passé

L'agence a suivi la procédure standard : configuration du domaine personnalisé dans BigCommerce, mise à jour DNS, vérification SSL. Le panneau admin affichait bien www.cosmetiques-bio.fr comme storefront URL.

Mais le thème Stencil avait été customisé. Un développeur front avait ajouté, six semaines avant la migration, un override dans le fichier config.json du thème pour gérer un problème de prévisualisation :

{
  "name": "Cornerstone-Custom",
  "version": "6.8.0",
  "settings": {
    "store_url": "https://staging-3f7a.mybigcommerce.com",
    "securePath": "https://staging-3f7a.mybigcommerce.com"
  }
}

Ce store_url dans le config.json du thème prend le dessus sur le paramètre global du panneau admin pour certains helpers Handlebars — dont {{page.canonical}}. C'est un comportement documenté nulle part de façon explicite dans la documentation Stencil de BigCommerce. Le paramètre global du dashboard est censé être la source de vérité. Mais quand un thème déclare un store_url dans son propre config.json, certains composants du moteur de rendu utilisent cette valeur locale en priorité.

Ce que voit le développeur vs ce que voit Googlebot

C'est le cœur du piège. Quand un développeur accède au site en production et inspecte la page dans Chrome DevTools, il voit :

  • L'URL dans la barre d'adresse : https://www.cosmetiques-bio.fr/creme-hydratante-aloe-vera/
  • Le contenu : correct
  • Le design : correct
  • Le certificat SSL : valide pour le domaine de production

Il faut ouvrir le code source (Ctrl+U, pas l'inspecteur DOM) ou faire un curl pour voir la balise canonical en dur. L'inspecteur DOM de Chrome affiche le DOM live, qui peut être modifié par du JavaScript côté client. Le code source brut montre le HTML servi par le serveur — celui que Googlebot indexe.

La vérification dans Search Console via l'outil "Inspection d'URL" confirme le problème. Quand on inspecte une page, l'onglet "HTML rendu" montre :

<link rel="canonical" href="https://staging-3f7a.mybigcommerce.com/creme-hydratante-aloe-vera/" />

Googlebot reçoit cet HTML. Il le respecte. Il considère que la version canonique de la page est sur le staging. Comme le staging est inaccessible (basic auth + robots.txt restrictif), Google ne peut pas crawler la version "canonique". Résultat : il supprime progressivement les pages de production de l'index.

Pourquoi les tests pré-lancement n'ont rien détecté

Trois raisons :

1. Le crawl de pré-lancement a été fait sur le staging. L'agence a crawlé staging-3f7a.mybigcommerce.com avec Screaming Frog avant la bascule DNS. Les canonicals pointaient vers staging-3f7a.mybigcommerce.com — cohérent avec l'URL crawlée. Aucune alerte.

2. Le crawl post-lancement n'a pas été fait. Le plan de migration prévoyait un crawl de vérification dans les 24 heures suivant la bascule. Il a été reporté à "la semaine prochaine" à cause d'un bug de paiement prioritaire. Cette semaine-là est devenue deux semaines. Le crawl n'a jamais eu lieu.

3. Personne n'a vérifié le view-source: en production. Les QA ont vérifié le rendu visuel, les fonctionnalités, le checkout, les redirections 301. Le HTML source n'a pas été inspecté. C'est un angle mort classique, et c'est exactement le même type de divergence SSR/navigateur qui frappe les migrations vers des frameworks headless ou les migrations entre routeurs Next.js.

L'ampleur du dégât côté Google

Un export Search Console sur la période J+1 à J+18 montre le mécanisme de déréférencement :

  • J+1 à J+5 : Googlebot crawle les pages de production, découvre les canonicals staging. Il signale les pages comme "Autre page avec balise canonique appropriée" dans le rapport de couverture. Pas d'alerte visible.
  • J+6 à J+12 : Les impressions commencent à chuter. Les pages sortent progressivement du top 100. −12% de clics par rapport à la baseline PrestaShop.
  • J+13 à J+18 : L'effondrement s'accélère. 4 200 pages ont zéro impression. Le trafic organique global est à −38%. Les requêtes brandées résistent (homepage toujours indexée, canonical correct par chance car la homepage utilise un template différent). Les requêtes non-brandées sont massacrées.

Le fix : corriger le config.json, purger, et attendre

Étape 1 — Corriger le thème Stencil

Le correctif est chirurgical. Dans le fichier config.json du thème, remplacer le hostname staging par le domaine de production :

{
  "name": "Cornerstone-Custom",
  "version": "6.8.1",
  "settings": {
    "store_url": "https://www.cosmetiques-bio.fr",
    "securePath": "https://www.cosmetiques-bio.fr"
  }
}

L'idéal serait de supprimer complètement ces champs pour laisser BigCommerce utiliser le paramètre global du dashboard. Mais l'équipe a préféré forcer la valeur correcte pour éviter toute ambiguïté, puis prévoir un nettoyage ultérieur.

Le thème est redéployé via Stencil CLI :

stencil bundle
# Upload du fichier .zip dans BigCommerce > Storefront > Themes
# Ou via l'API :
curl -X POST https://api.bigcommerce.com/stores/{store_hash}/v3/themes \
  -H "X-Auth-Token: {access_token}" \
  -H "Content-Type: application/json" \
  -d '{"file_url": "https://storage.internal/cornerstone-custom-6.8.1.zip"}'

Étape 2 — Vérification immédiate

Après déploiement, vérification sur cinq pages représentatives :

for url in \
  "https://www.cosmetiques-bio.fr/" \
  "https://www.cosmetiques-bio.fr/creme-hydratante-aloe-vera/" \
  "https://www.cosmetiques-bio.fr/serum-vitamine-c/" \
  "https://www.cosmetiques-bio.fr/categorie/soins-visage/" \
  "https://www.cosmetiques-bio.fr/blog/routine-matin/"; do
  echo "=== $url ==="
  curl -s "$url" | grep -i 'canonical'
done

Toutes les réponses montrent désormais le bon domaine. Un crawl Screaming Frog complet confirme : 7 843 pages crawlées, 7 841 canonicals corrects, 2 pages sans canonical (pages de panier et de checkout — normal).

Étape 3 — Purge du cache CDN

BigCommerce gère le cache Akamai automatiquement lors d'un redéploiement de thème. Mais l'équipe force une purge manuelle depuis le panneau admin (Server Settings → Cache) pour ne prendre aucun risque.

Étape 4 — Soumettre le sitemap et forcer le re-crawl

Le sitemap XML de BigCommerce (/xmlsitemap.php) est soumis à nouveau dans Search Console. L'outil "Inspection d'URL" est utilisé pour demander une réindexation manuelle des 20 pages les plus stratégiques (top 20 par trafic historique sur PrestaShop).

Étape 5 — Attendre

C'est la partie la plus douloureuse. Google ne réindexe pas 6 900 pages en un jour. La timeline observée :

  • J+0 à J+3 post-fix : Google recrawle environ 800 pages. Les canonicals corrects sont détectés. Les premières pages réapparaissent dans l'index.
  • J+4 à J+10 : 3 200 pages réindexées. Le trafic organique remonte à −22% vs baseline.
  • J+11 à J+21 : Réindexation quasi complète. 6 700 pages de retour. Trafic à −8%.
  • J+22 à J+35 : Stabilisation progressive. Le trafic retrouve 96% de la baseline. Les 4% restants correspondent à des pages longue traîne qui mettent plus de temps à récupérer leur position.

Au total : 35 jours entre le fix et la récupération quasi complète. Ajoutés aux 18 jours de dégât silencieux, ça fait 53 jours de perturbation SEO sur une migration qui aurait dû être transparente.

Les mesures préventives mises en place

L'agence a ajouté trois garde-fous à son process de migration :

1. Crawl post-bascule obligatoire dans les 4 heures. Pas "dans la semaine". Dans les 4 heures. Avec un check automatisé sur les canonicals :

# Script post-migration : vérifie que les canonicals ne contiennent pas "mybigcommerce.com"
screaming-frog-cli --crawl https://www.cosmetiques-bio.fr \
  --export-tabs "Canonicals" \
  --output /tmp/crawl-postmigration.csv

grep -c "mybigcommerce.com" /tmp/crawl-postmigration.csv
# Attendu : 0

2. Grep systématique du hostname staging dans le thème. Avant chaque déploiement de thème, un grep -r "mybigcommerce.com" . dans le répertoire du thème Stencil. Si ça matche, le déploiement est bloqué.

3. Alerte Search Console sur la couverture. L'équipe SEO surveille quotidiennement le rapport "Pages" de Search Console pendant les 30 jours post-migration. Toute augmentation du statut "Autre page avec balise canonique appropriée" déclenche une investigation immédiate. Ce type de surveillance systématique rejoint les principes décrits pour les audits pré-lancement en staging.

Ce qu'on en retient

Une migration e-commerce ne se valide pas dans un navigateur. Le rendu visuel peut être parfait pendant que le HTML source envoie Google dans un cul-de-sac. Les canonicals sont la directive SEO la plus silencieusement destructrice quand elles pointent au mauvais endroit : pas d'erreur 404, pas d'alerte rouge, juste une érosion lente que personne ne remarque jusqu'à ce qu'il soit trop tard.

Le piège spécifique à BigCommerce — un config.json de thème qui écrase le paramètre global du dashboard — est vicieux parce qu'il est invisible dans l'interface d'administration. Seul le code source du thème ou le HTML rendu le révèle.

Un monitoring continu type Seogard détecte ce type de divergence entre le domaine déclaré en canonical et le domaine réel en quelques heures — pas dix-huit jours. Mais même sans monitoring automatisé, un simple curl | grep canonical après chaque mise en production aurait suffi. Cinquante-trois jours de perturbation pour un champ JSON mal nettoyé. C'est le coût de ne pas vérifier ce que Google voit vraiment.

Articles connexes

Migration27 mai 2026

Migration Magento 2 → Shopify : 8 400 URLs sans 301

Récit d'une migration Magento 2 vers Shopify où 8 400 URLs produit n'ont jamais été redirigées. Diagnostic, impact SEO, fix complet.

Migration26 mai 2026

Migration Gatsby → Astro : RSS feed orphelin, 6 semaines

Un blog tech migre de Gatsby vers Astro. Le RSS feed change d'URL sans redirect. 6 semaines de silence. Récit, diagnostic et fix complet.

Migration26 mai 2026

WordPress vers Strapi headless : 4000 redirects .htaccess perdues

Migration JAMstack réussie côté dev, désastre SEO : 4000 redirections .htaccess oubliées, 60% de trafic perdu. Récit, diagnostic et fix complet.