[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fvcpobncjIJ4ANkWaC_MxbM1SmGXLZ0D2-yJzWIyO7Zo":3,"$fB82n6mnqCN_LdvB3rrarpF8HbHazHL4EwAxpIqWsh9E":25},{"_id":4,"slug":5,"__v":6,"author":7,"body":8,"canonical":9,"category":10,"createdAt":11,"date":12,"description":13,"htmlContent":14,"image":15,"imageAlt":15,"readingTime":16,"tags":17,"title":23,"updatedAt":24},"6a171570aa6b273b0cfd2531","migration-magento-2-vers-shopify-structure-url-non-redirigee-autorite-dispersee",0,"Equipe Seogard","# Migration Magento 2 vers Shopify : 8 400 URLs sans 301, l'autorité dispersée en silence\n\nJeudi 14h. L'agence envoie un Slack : \"Migration live, tout est clean.\" Le site e-commerce — cosmétiques bio, 8 400 fiches produit, 1,2 million de sessions organiques par an — tourne désormais sur Shopify. Le checkout fonctionne. Le thème est pixel-perfect. Les équipes trinquent.\n\nTrois semaines plus tard, le trafic organique a chuté de 34 %. Personne n'a touché au site. Les backlinks construits depuis quatre ans pointent tous dans le vide.\n\n## Lundi T+18 jours — \"C'est juste la migration, ça va revenir\"\n\nLe Head of Acquisition ouvre Google Analytics le lundi matin. Le dashboard hebdomadaire affiche 22 000 sessions organiques contre 33 500 la semaine précédente. Premier réflexe : la saisonnalité. On est début mars, les ventes de soins d'hiver ralentissent. Il classe l'alerte mentalement et passe à autre chose.\n\nMercredi, le SEO manager tire les données Search Console sur 28 jours. Les clics sont passés de 9 800/jour à 6 100/jour. Les impressions tiennent — elles ont même légèrement augmenté sur certaines requêtes. Mais le CTR moyen s'est effondré de 3,2 % à 1,9 %. Quelque chose ne colle pas.\n\nIl filtre par page. Et là, le tableau se révèle.\n\nLes URLs les plus performantes — celles qui tiraient 60 % du trafic organique — sont toutes des URLs Magento. Format `/skincare/creme-hydratante-aloe-vera.html`. Aucune d'entre elles n'existe sur le nouveau site. Shopify a généré ses propres URLs : `/products/creme-hydratante-aloe-vera`. Pas de `.html`. Pas de catégorie dans le chemin. Un format totalement différent.\n\nIl tape une ancienne URL dans le navigateur. Réponse : 404. Page blanche Shopify, thème par défaut. Pas de redirection.\n\nIl en teste dix autres. Toutes en 404.\n\nÀ 16h, il lance un crawl Screaming Frog sur une liste exportée de 500 anciennes URLs Magento. Résultat : 487 renvoient un 404. Les 13 restantes — des pages catégorie — retournent un 301 vers la homepage. Pas vers la bonne catégorie. Vers la homepage.\n\nL'hypothèse initiale — \"Shopify gère les redirections automatiquement\" — vient de s'écrouler. L'agence n'a posé aucune table de redirections. Aucune. Sur 8 400 fiches produit, pas une seule 301. L'autorité construite sur quatre ans de content marketing, de backlinks DR 40+ obtenus via des guides beauté, de maillage interne soigné — tout ça pointe vers des 404.\n\nLe SEO manager envoie un message à l'agence : \"Est-ce qu'on a un fichier de mapping ancien URL → nouveau URL ?\" La réponse arrive vingt minutes plus tard : \"On pensait que Shopify le faisait automatiquement quand on importe les produits.\"\n\nIl n'en fait rien.\n\n## Le bug : Magento vs Shopify, deux logiques d'URL irréconciliables\n\nPour comprendre l'ampleur du dégât, il faut regarder comment chaque plateforme construit ses URLs.\n\n### La structure Magento 2\n\nMagento 2 permet une personnalisation fine des URL keys via le panneau admin et la table `url_rewrite` en base de données. Un produit dans la catégorie \"Skincare\" avec l'URL key `creme-hydratante-aloe-vera` produit :\n\n```\nhttps://example.com/skincare/creme-hydratante-aloe-vera.html\n```\n\nLe `.html` est un suffixe configurable dans `Stores > Configuration > Catalog > SEO`. La structure hiérarchique `/category/product.html` est le défaut Magento. Sur le site en question, ce format était actif depuis 2021. Google avait indexé 8 400 URLs dans ce format exact.\n\nLa table `url_rewrite` de Magento contenait également des redirections internes — anciennes URL keys vers nouvelles — accumulées sur quatre ans de modifications produit. Environ 1 200 entrées de type `custom` avec redirect type `301`.\n\n### La structure Shopify\n\nShopify impose un format non négociable pour les produits :\n\n```\nhttps://example.com/products/creme-hydratante-aloe-vera\n```\n\nPas de `.html`. Pas de catégorie dans le chemin. Le préfixe `/products/` est obligatoire et ne peut pas être modifié, même sur Shopify Plus. Les collections (équivalent des catégories) vivent sous `/collections/`, mais le produit lui-même est toujours sous `/products/`.\n\nVoici ce que Google voyait avant et après la migration :\n\n```html\n\u003C!-- Avant (Magento 2) — indexé, avec backlinks -->\n\u003Clink rel=\"canonical\" href=\"https://example.com/skincare/creme-hydratante-aloe-vera.html\" />\n\u003Ctitle>Crème Hydratante Aloe Vera | NomDuSite\u003C/title>\n\u003Cmeta name=\"description\" content=\"Crème hydratante bio à l'aloe vera...\" />\n\n\u003C!-- Après (Shopify) — même produit, URL différente -->\n\u003Clink rel=\"canonical\" href=\"https://example.com/products/creme-hydratante-aloe-vera\" />\n\u003Ctitle>Crème Hydratante Aloe Vera | NomDuSite\u003C/title>\n\u003Cmeta name=\"description\" content=\"Crème hydratante bio à l'aloe vera...\" />\n```\n\nLe contenu est identique. Les metas sont les mêmes. Mais l'URL a changé. Et sans 301 de l'ancienne vers la nouvelle, Google traite la nouvelle page comme une page inconnue — zero autorité, zero historique. L'ancienne URL, elle, accumule des soft 404 dans l'index.\n\n### Pourquoi l'import produit ne crée pas les redirections\n\nL'agence avait utilisé l'app Matrixify (anciennement Excelify) pour importer les produits Magento vers Shopify. L'import crée les produits avec leurs handles — la partie slug de l'URL. Mais il ne crée aucune redirection d'URL. Ce n'est pas un bug de Matrixify. C'est simplement hors périmètre.\n\nShopify dispose d'un système de redirections natif accessible via `Online Store > Navigation > URL Redirects`. Ce système accepte des imports CSV. Mais il faut le nourrir manuellement.\n\nL'agence n'avait pas extrait les URL keys Magento avant la migration. Pas de dump de la table `url_rewrite`. Pas de crawl pré-migration. Pas de fichier de mapping.\n\n### L'ampleur dans Search Console\n\nDix-neuf jours après la mise en production, voici ce que Search Console montrait dans le rapport de couverture :\n\n- **Pages indexées** : 3 200 (contre 9 100 avant migration)\n- **Erreurs 404** : 7 840 URLs avec le pattern `/[category]/[product].html`\n- **Pages avec redirection** : 47 (des pages CMS redirigées manuellement par l'agence)\n- **Pages explorées non indexées** : 2 300 nouvelles URLs `/products/` — Google les avait crawlées mais pas encore jugées dignes d'indexation faute de signaux d'autorité\n\nLe rapport de liens externes confirmait le désastre. Un check rapide via Ahrefs montrait 1 840 domaines référents pointant vers des URLs Magento. 94 % de ces backlinks tombaient désormais sur des 404. Le Domain Rating du site avait commencé à baisser — de DR 52 à DR 48 en trois semaines.\n\n### La redirection catégorie → homepage : le piège du soft redirect\n\nLes 13 pages catégorie qui retournaient un 301 pointaient toutes vers la homepage. L'agence avait posé des redirections wildcard dans le fichier de redirections Shopify :\n\n```\n/skincare,/\n/haircare,/\n/body-care,/\n```\n\nCe type de redirection est un signal négatif pour Google. [John Mueller l'a documenté](https://developers.google.com/search/docs/crawling-indexing/301-redirects) : une 301 vers la homepage quand la page de destination thématique existe est traitée comme un soft 404 par l'algorithme. Le PageRank transmis est quasi nul.\n\nLes catégories Shopify existaient pourtant : `/collections/skincare`, `/collections/haircare`, `/collections/body-care`. Personne n'avait fait le mapping.\n\n## Le fix : 8 400 redirections en 48 heures\n\n### Étape 1 — Extraction du mapping Magento\n\nLe SEO manager avait encore accès au back-office Magento sur un serveur de staging. Il a extrait la table `url_rewrite` via une requête SQL directe :\n\n```sql\nSELECT\n    request_path AS old_url,\n    CONCAT('/products/', REPLACE(\n        SUBSTRING_INDEX(request_path, '/', -1), '.html', ''\n    )) AS new_url\nFROM url_rewrite\nWHERE entity_type = 'product'\n    AND redirect_type = 0\n    AND store_id = 1\nGROUP BY request_path;\n```\n\nCette requête extrait les 8 400 URLs produit actives (pas les anciennes redirections internes) et reconstruit le nouveau chemin Shopify en retirant le préfixe catégorie et le suffixe `.html`.\n\nRésultat : un CSV de deux colonnes, `old_url` et `new_url`.\n\n### Étape 2 — Vérification que les handles Shopify existent\n\nAvant d'injecter 8 400 redirections, il faut s'assurer que chaque handle existe dans Shopify. Sinon, on redirige un 404 vers un autre 404.\n\nUn script Node.js rapide via l'API Shopify Admin :\n\n```javascript\nconst Shopify = require('shopify-api-node');\nconst fs = require('fs');\nconst csv = require('csv-parse/sync');\n\nconst shopify = new Shopify({\n  shopName: 'example-store',\n  apiKey: process.env.SHOPIFY_API_KEY,\n  password: process.env.SHOPIFY_API_PASSWORD,\n});\n\nconst mappings = csv.parse(fs.readFileSync('mapping.csv'), {\n  columns: true,\n});\n\n(async () => {\n  const missing = [];\n  for (const row of mappings) {\n    const handle = row.new_url.replace('/products/', '');\n    try {\n      await shopify.product.list({ handle, limit: 1 });\n    } catch (e) {\n      missing.push(row);\n    }\n  }\n  fs.writeFileSync('missing_handles.csv', JSON.stringify(missing, null, 2));\n  console.log(`${missing.length} handles introuvables sur Shopify`);\n})();\n```\n\nRésultat : 312 handles manquants. Des produits supprimés ou renommés pendant la migration. Ces 312 cas ont été redirigés vers la collection parente plutôt que vers la homepage.\n\n### Étape 3 — Import massif dans Shopify\n\nShopify accepte l'import CSV de redirections via l'admin (`Online Store > Navigation > URL Redirects > Import`). Format attendu :\n\n```csv\nRedirect from,Redirect to\n/skincare/creme-hydratante-aloe-vera.html,/products/creme-hydratante-aloe-vera\n/skincare/serum-vitamine-c.html,/products/serum-vitamine-c\n/haircare/shampoing-doux-avoine.html,/products/shampoing-doux-avoine\n```\n\nLe fichier final contenait 8 088 redirections produit exactes et 312 redirections vers les collections. Plus 47 redirections catégorie corrigées — `/skincare` vers `/collections/skincare` au lieu de `/`.\n\nL'import a été réalisé en trois lots (Shopify limite à 5 000 lignes par import CSV dans certains plans). Temps total : 25 minutes.\n\n### Étape 4 — Vérification post-déploiement\n\nUn crawl Screaming Frog sur la liste complète des anciennes URLs. Configuration : `Spider > Advanced > Always follow redirects OFF` pour voir les codes de statut intermédiaires.\n\n```bash\n# Vérification rapide via curl sur un échantillon de 50 URLs\ncat sample_old_urls.txt | xargs -I {} curl -o /dev/null -s -w \"%{http_code} %{redirect_url} {}\\n\" -L {}\n```\n\nRésultat : 8 400 URLs retournent un 301 vers la bonne destination. Zéro 404 restant sur les URLs connues.\n\n### Étape 5 — Forcer le re-crawl\n\nPour accélérer la prise en compte par Google :\n\n1. Soumission du nouveau sitemap Shopify dans Search Console\n2. Utilisation de l'API d'indexation pour les 200 pages les plus importantes (celles avec le plus de backlinks)\n3. Invalidation du rapport de couverture via \"Valider la correction\" sur les erreurs 404\n\n### Chronologie de récupération\n\n- **J+2 après le fix** : les 404 commencent à disparaître du rapport de couverture\n- **J+7** : 4 200 des anciennes URLs sont marquées \"redirigée\" dans Search Console\n- **J+14** : le trafic organique remonte à 7 800 sessions/jour (contre 6 100 au creux)\n- **J+28** : retour à 9 200 sessions/jour — 94 % du niveau pré-migration\n- **J+45** : stabilisation à 9 600 sessions/jour — légère progression grâce à la nouvelle vitesse Shopify (TTFB passé de 1,2s sous Magento à 380ms sous Shopify)\n\nLe Domain Rating a mis plus longtemps. Six semaines pour repasser de DR 48 à DR 51. Le DR 52 d'origine n'a été retrouvé qu'au bout de trois mois — le temps que les crawlers des outils tiers re-découvrent les redirections et réattribuent l'autorité.\n\nLe site n'a jamais récupéré 100 % de ses positions sur certaines requêtes longue traîne. Environ 340 pages produit avaient été désindexées pendant la fenêtre de 404 et n'ont jamais retrouvé leur position exacte. L'estimation de la perte nette sur le trimestre : 180 000 clics organiques.\n\n### Leçons opérationnelles\n\nL'équipe a mis en place trois garde-fous pour les futures migrations :\n\n1. **Crawl pré-migration obligatoire**. Un export Screaming Frog complet de toutes les URLs indexées, croisé avec les données Search Console, constitue le fichier de référence avant toute migration. Comme détaillé dans le récit d'une [migration WordPress vers headless Strapi](/blog/migration-wordpress-vers-headless-strapi-4000-redirections-htaccess-oubliees), l'absence de ce fichier est la cause racine de la majorité des pertes de redirections.\n\n2. **Validation des redirections en staging**. Shopify ne propose pas d'environnement de staging natif, mais les redirections peuvent être testées via l'API Admin avant la bascule DNS.\n\n3. **Monitoring post-migration quotidien pendant 30 jours**. Pas un check hebdomadaire. Un check quotidien des 404 dans Search Console, du nombre de pages indexées, et du trafic organique par landing page.\n\nLe parallèle avec les [migrations de framework front-end](/blog/migration-nuxt-2-vers-nuxt-3-200-pages-en-fallback-layout-pendant-6-semaines) est frappant : le pattern est toujours le même. Une équipe concentrée sur le fonctionnel pousse en production. Le rendu visuel est parfait. Les URLs, les metas, les redirections — tout ce que Google voit et que l'utilisateur ne voit pas — passent entre les mailles.\n\nEt quand l'environnement de staging n'est pas [stress-testé sous l'angle SEO](/blog/how-to-stress-test-a-staging-environment-to-surface-risks-pre-launch-ask-an-seo-via-sejournal-helenpollitt1), ces régressions restent invisibles jusqu'à ce que Search Console les remonte — avec trois semaines de retard.\n\n## Ce qu'on en retient\n\nUne migration de plateforme e-commerce n'est pas un projet front-end. C'est un projet d'infrastructure SEO. Chaque URL est un actif. Chaque backlink est un vote d'autorité. Quand 8 400 URLs changent de structure sans table de redirections, ce n'est pas un \"détail technique\" — c'est une perte de revenus mesurable.\n\nLe fix est trivial. Un export SQL, un CSV, un import Shopify. Trente minutes de travail. Le vrai coût, c'est les trois semaines pendant lesquelles personne ne regarde.\n\nUn monitoring continu type Seogard détecte ce type de 404 massif dès le premier crawl post-déploiement — pas dix-huit jours plus tard quand le trafic a déjà décroché.\n```","https://seogard.io/blog/migration-magento-2-vers-shopify-structure-url-non-redirigee-autorite-dispersee","Migration","2026-05-27T16:01:52.468Z","2026-05-27","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.","\u003Ch1>Migration Magento 2 vers Shopify : 8 400 URLs sans 301, l'autorité dispersée en silence\u003C/h1>\n\u003Cp>Jeudi 14h. L'agence envoie un Slack : \"Migration live, tout est clean.\" Le site e-commerce — cosmétiques bio, 8 400 fiches produit, 1,2 million de sessions organiques par an — tourne désormais sur Shopify. Le checkout fonctionne. Le thème est pixel-perfect. Les équipes trinquent.\u003C/p>\n\u003Cp>Trois semaines plus tard, le trafic organique a chuté de 34 %. Personne n'a touché au site. Les backlinks construits depuis quatre ans pointent tous dans le vide.\u003C/p>\n\u003Ch2>Lundi T+18 jours — \"C'est juste la migration, ça va revenir\"\u003C/h2>\n\u003Cp>Le Head of Acquisition ouvre Google Analytics le lundi matin. Le dashboard hebdomadaire affiche 22 000 sessions organiques contre 33 500 la semaine précédente. Premier réflexe : la saisonnalité. On est début mars, les ventes de soins d'hiver ralentissent. Il classe l'alerte mentalement et passe à autre chose.\u003C/p>\n\u003Cp>Mercredi, le SEO manager tire les données Search Console sur 28 jours. Les clics sont passés de 9 800/jour à 6 100/jour. Les impressions tiennent — elles ont même légèrement augmenté sur certaines requêtes. Mais le CTR moyen s'est effondré de 3,2 % à 1,9 %. Quelque chose ne colle pas.\u003C/p>\n\u003Cp>Il filtre par page. Et là, le tableau se révèle.\u003C/p>\n\u003Cp>Les URLs les plus performantes — celles qui tiraient 60 % du trafic organique — sont toutes des URLs Magento. Format \u003Ccode>/skincare/creme-hydratante-aloe-vera.html\u003C/code>. Aucune d'entre elles n'existe sur le nouveau site. Shopify a généré ses propres URLs : \u003Ccode>/products/creme-hydratante-aloe-vera\u003C/code>. Pas de \u003Ccode>.html\u003C/code>. Pas de catégorie dans le chemin. Un format totalement différent.\u003C/p>\n\u003Cp>Il tape une ancienne URL dans le navigateur. Réponse : 404. Page blanche Shopify, thème par défaut. Pas de redirection.\u003C/p>\n\u003Cp>Il en teste dix autres. Toutes en 404.\u003C/p>\n\u003Cp>À 16h, il lance un crawl Screaming Frog sur une liste exportée de 500 anciennes URLs Magento. Résultat : 487 renvoient un 404. Les 13 restantes — des pages catégorie — retournent un 301 vers la homepage. Pas vers la bonne catégorie. Vers la homepage.\u003C/p>\n\u003Cp>L'hypothèse initiale — \"Shopify gère les redirections automatiquement\" — vient de s'écrouler. L'agence n'a posé aucune table de redirections. Aucune. Sur 8 400 fiches produit, pas une seule 301. L'autorité construite sur quatre ans de content marketing, de backlinks DR 40+ obtenus via des guides beauté, de maillage interne soigné — tout ça pointe vers des 404.\u003C/p>\n\u003Cp>Le SEO manager envoie un message à l'agence : \"Est-ce qu'on a un fichier de mapping ancien URL → nouveau URL ?\" La réponse arrive vingt minutes plus tard : \"On pensait que Shopify le faisait automatiquement quand on importe les produits.\"\u003C/p>\n\u003Cp>Il n'en fait rien.\u003C/p>\n\u003Ch2>Le bug : Magento vs Shopify, deux logiques d'URL irréconciliables\u003C/h2>\n\u003Cp>Pour comprendre l'ampleur du dégât, il faut regarder comment chaque plateforme construit ses URLs.\u003C/p>\n\u003Ch3>La structure Magento 2\u003C/h3>\n\u003Cp>Magento 2 permet une personnalisation fine des URL keys via le panneau admin et la table \u003Ccode>url_rewrite\u003C/code> en base de données. Un produit dans la catégorie \"Skincare\" avec l'URL key \u003Ccode>creme-hydratante-aloe-vera\u003C/code> produit :\u003C/p>\n\u003Cpre>\u003Ccode>https://example.com/skincare/creme-hydratante-aloe-vera.html\n\u003C/code>\u003C/pre>\n\u003Cp>Le \u003Ccode>.html\u003C/code> est un suffixe configurable dans \u003Ccode>Stores > Configuration > Catalog > SEO\u003C/code>. La structure hiérarchique \u003Ccode>/category/product.html\u003C/code> est le défaut Magento. Sur le site en question, ce format était actif depuis 2021. Google avait indexé 8 400 URLs dans ce format exact.\u003C/p>\n\u003Cp>La table \u003Ccode>url_rewrite\u003C/code> de Magento contenait également des redirections internes — anciennes URL keys vers nouvelles — accumulées sur quatre ans de modifications produit. Environ 1 200 entrées de type \u003Ccode>custom\u003C/code> avec redirect type \u003Ccode>301\u003C/code>.\u003C/p>\n\u003Ch3>La structure Shopify\u003C/h3>\n\u003Cp>Shopify impose un format non négociable pour les produits :\u003C/p>\n\u003Cpre>\u003Ccode>https://example.com/products/creme-hydratante-aloe-vera\n\u003C/code>\u003C/pre>\n\u003Cp>Pas de \u003Ccode>.html\u003C/code>. Pas de catégorie dans le chemin. Le préfixe \u003Ccode>/products/\u003C/code> est obligatoire et ne peut pas être modifié, même sur Shopify Plus. Les collections (équivalent des catégories) vivent sous \u003Ccode>/collections/\u003C/code>, mais le produit lui-même est toujours sous \u003Ccode>/products/\u003C/code>.\u003C/p>\n\u003Cp>Voici ce que Google voyait avant et après la migration :\u003C/p>\n\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">&#x3C;!-- Avant (Magento 2) — indexé, avec backlinks -->\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">&#x3C;\u003C/span>\u003Cspan style=\"color:#85E89D\">link\u003C/span>\u003Cspan style=\"color:#B392F0\"> rel\u003C/span>\u003Cspan style=\"color:#E1E4E8\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"canonical\"\u003C/span>\u003Cspan style=\"color:#B392F0\"> href\u003C/span>\u003Cspan style=\"color:#E1E4E8\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"https://example.com/skincare/creme-hydratante-aloe-vera.html\"\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> />\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">&#x3C;\u003C/span>\u003Cspan style=\"color:#85E89D\">title\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>Crème Hydratante Aloe Vera | NomDuSite&#x3C;/\u003C/span>\u003Cspan style=\"color:#85E89D\">title\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">&#x3C;\u003C/span>\u003Cspan style=\"color:#85E89D\">meta\u003C/span>\u003Cspan style=\"color:#B392F0\"> name\u003C/span>\u003Cspan style=\"color:#E1E4E8\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"description\"\u003C/span>\u003Cspan style=\"color:#B392F0\"> content\u003C/span>\u003Cspan style=\"color:#E1E4E8\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"Crème hydratante bio à l'aloe vera...\"\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> />\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\">&#x3C;!-- Après (Shopify) — même produit, URL différente -->\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">&#x3C;\u003C/span>\u003Cspan style=\"color:#85E89D\">link\u003C/span>\u003Cspan style=\"color:#B392F0\"> rel\u003C/span>\u003Cspan style=\"color:#E1E4E8\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"canonical\"\u003C/span>\u003Cspan style=\"color:#B392F0\"> href\u003C/span>\u003Cspan style=\"color:#E1E4E8\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"https://example.com/products/creme-hydratante-aloe-vera\"\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> />\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">&#x3C;\u003C/span>\u003Cspan style=\"color:#85E89D\">title\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>Crème Hydratante Aloe Vera | NomDuSite&#x3C;/\u003C/span>\u003Cspan style=\"color:#85E89D\">title\u003C/span>\u003Cspan style=\"color:#E1E4E8\">>\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">&#x3C;\u003C/span>\u003Cspan style=\"color:#85E89D\">meta\u003C/span>\u003Cspan style=\"color:#B392F0\"> name\u003C/span>\u003Cspan style=\"color:#E1E4E8\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"description\"\u003C/span>\u003Cspan style=\"color:#B392F0\"> content\u003C/span>\u003Cspan style=\"color:#E1E4E8\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\">\"Crème hydratante bio à l'aloe vera...\"\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> />\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Le contenu est identique. Les metas sont les mêmes. Mais l'URL a changé. Et sans 301 de l'ancienne vers la nouvelle, Google traite la nouvelle page comme une page inconnue — zero autorité, zero historique. L'ancienne URL, elle, accumule des soft 404 dans l'index.\u003C/p>\n\u003Ch3>Pourquoi l'import produit ne crée pas les redirections\u003C/h3>\n\u003Cp>L'agence avait utilisé l'app Matrixify (anciennement Excelify) pour importer les produits Magento vers Shopify. L'import crée les produits avec leurs handles — la partie slug de l'URL. Mais il ne crée aucune redirection d'URL. Ce n'est pas un bug de Matrixify. C'est simplement hors périmètre.\u003C/p>\n\u003Cp>Shopify dispose d'un système de redirections natif accessible via \u003Ccode>Online Store > Navigation > URL Redirects\u003C/code>. Ce système accepte des imports CSV. Mais il faut le nourrir manuellement.\u003C/p>\n\u003Cp>L'agence n'avait pas extrait les URL keys Magento avant la migration. Pas de dump de la table \u003Ccode>url_rewrite\u003C/code>. Pas de crawl pré-migration. Pas de fichier de mapping.\u003C/p>\n\u003Ch3>L'ampleur dans Search Console\u003C/h3>\n\u003Cp>Dix-neuf jours après la mise en production, voici ce que Search Console montrait dans le rapport de couverture :\u003C/p>\n\u003Cul>\n\u003Cli>\u003Cstrong>Pages indexées\u003C/strong> : 3 200 (contre 9 100 avant migration)\u003C/li>\n\u003Cli>\u003Cstrong>Erreurs 404\u003C/strong> : 7 840 URLs avec le pattern \u003Ccode>/[category]/[product].html\u003C/code>\u003C/li>\n\u003Cli>\u003Cstrong>Pages avec redirection\u003C/strong> : 47 (des pages CMS redirigées manuellement par l'agence)\u003C/li>\n\u003Cli>\u003Cstrong>Pages explorées non indexées\u003C/strong> : 2 300 nouvelles URLs \u003Ccode>/products/\u003C/code> — Google les avait crawlées mais pas encore jugées dignes d'indexation faute de signaux d'autorité\u003C/li>\n\u003C/ul>\n\u003Cp>Le rapport de liens externes confirmait le désastre. Un check rapide via Ahrefs montrait 1 840 domaines référents pointant vers des URLs Magento. 94 % de ces backlinks tombaient désormais sur des 404. Le Domain Rating du site avait commencé à baisser — de DR 52 à DR 48 en trois semaines.\u003C/p>\n\u003Ch3>La redirection catégorie → homepage : le piège du soft redirect\u003C/h3>\n\u003Cp>Les 13 pages catégorie qui retournaient un 301 pointaient toutes vers la homepage. L'agence avait posé des redirections wildcard dans le fichier de redirections Shopify :\u003C/p>\n\u003Cpre>\u003Ccode>/skincare,/\n/haircare,/\n/body-care,/\n\u003C/code>\u003C/pre>\n\u003Cp>Ce type de redirection est un signal négatif pour Google. \u003Ca href=\"https://developers.google.com/search/docs/crawling-indexing/301-redirects\">John Mueller l'a documenté\u003C/a> : une 301 vers la homepage quand la page de destination thématique existe est traitée comme un soft 404 par l'algorithme. Le PageRank transmis est quasi nul.\u003C/p>\n\u003Cp>Les catégories Shopify existaient pourtant : \u003Ccode>/collections/skincare\u003C/code>, \u003Ccode>/collections/haircare\u003C/code>, \u003Ccode>/collections/body-care\u003C/code>. Personne n'avait fait le mapping.\u003C/p>\n\u003Ch2>Le fix : 8 400 redirections en 48 heures\u003C/h2>\n\u003Ch3>Étape 1 — Extraction du mapping Magento\u003C/h3>\n\u003Cp>Le SEO manager avait encore accès au back-office Magento sur un serveur de staging. Il a extrait la table \u003Ccode>url_rewrite\u003C/code> via une requête SQL directe :\u003C/p>\n\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">SELECT\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    request_path \u003C/span>\u003Cspan style=\"color:#F97583\">AS\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> old_url,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#79B8FF\">    CONCAT\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'/products/'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">REPLACE\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">        SUBSTRING_INDEX(request_path, \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'/'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#F97583\">-\u003C/span>\u003Cspan style=\"color:#79B8FF\">1\u003C/span>\u003Cspan style=\"color:#E1E4E8\">), \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'.html'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#9ECBFF\">''\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    )) \u003C/span>\u003Cspan style=\"color:#F97583\">AS\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> new_url\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">FROM\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> url_rewrite\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">WHERE\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> entity_type \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> 'product'\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    AND\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> redirect_type \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 0\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    AND\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> store_id \u003C/span>\u003Cspan style=\"color:#F97583\">=\u003C/span>\u003Cspan style=\"color:#79B8FF\"> 1\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">GROUP BY\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> request_path;\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Cette requête extrait les 8 400 URLs produit actives (pas les anciennes redirections internes) et reconstruit le nouveau chemin Shopify en retirant le préfixe catégorie et le suffixe \u003Ccode>.html\u003C/code>.\u003C/p>\n\u003Cp>Résultat : un CSV de deux colonnes, \u003Ccode>old_url\u003C/code> et \u003Ccode>new_url\u003C/code>.\u003C/p>\n\u003Ch3>Étape 2 — Vérification que les handles Shopify existent\u003C/h3>\n\u003Cp>Avant d'injecter 8 400 redirections, il faut s'assurer que chaque handle existe dans Shopify. Sinon, on redirige un 404 vers un autre 404.\u003C/p>\n\u003Cp>Un script Node.js rapide via l'API Shopify Admin :\u003C/p>\n\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> Shopify\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#B392F0\"> require\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'shopify-api-node'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> fs\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#B392F0\"> require\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'fs'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> csv\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#B392F0\"> require\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'csv-parse/sync'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> shopify\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#F97583\"> new\u003C/span>\u003Cspan style=\"color:#B392F0\"> Shopify\u003C/span>\u003Cspan style=\"color:#E1E4E8\">({\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">  shopName: \u003C/span>\u003Cspan style=\"color:#9ECBFF\">'example-store'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">  apiKey: process.env.\u003C/span>\u003Cspan style=\"color:#79B8FF\">SHOPIFY_API_KEY\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">  password: process.env.\u003C/span>\u003Cspan style=\"color:#79B8FF\">SHOPIFY_API_PASSWORD\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">});\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> mappings\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> csv.\u003C/span>\u003Cspan style=\"color:#B392F0\">parse\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(fs.\u003C/span>\u003Cspan style=\"color:#B392F0\">readFileSync\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'mapping.csv'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">), {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">  columns: \u003C/span>\u003Cspan style=\"color:#79B8FF\">true\u003C/span>\u003Cspan style=\"color:#E1E4E8\">,\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">});\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#F97583\">async\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> () \u003C/span>\u003Cspan style=\"color:#F97583\">=>\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">  const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> missing\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> [];\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">  for\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> (\u003C/span>\u003Cspan style=\"color:#F97583\">const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> row\u003C/span>\u003Cspan style=\"color:#F97583\"> of\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> mappings) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    const\u003C/span>\u003Cspan style=\"color:#79B8FF\"> handle\u003C/span>\u003Cspan style=\"color:#F97583\"> =\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> row.new_url.\u003C/span>\u003Cspan style=\"color:#B392F0\">replace\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'/products/'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#9ECBFF\">''\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">    try\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#F97583\">      await\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> shopify.product.\u003C/span>\u003Cspan style=\"color:#B392F0\">list\u003C/span>\u003Cspan style=\"color:#E1E4E8\">({ handle, limit: \u003C/span>\u003Cspan style=\"color:#79B8FF\">1\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> });\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    } \u003C/span>\u003Cspan style=\"color:#F97583\">catch\u003C/span>\u003Cspan style=\"color:#E1E4E8\"> (e) {\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">      missing.\u003C/span>\u003Cspan style=\"color:#B392F0\">push\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(row);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">    }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">  }\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">  fs.\u003C/span>\u003Cspan style=\"color:#B392F0\">writeFileSync\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">'missing_handles.csv'\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">JSON\u003C/span>\u003Cspan style=\"color:#E1E4E8\">.\u003C/span>\u003Cspan style=\"color:#B392F0\">stringify\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(missing, \u003C/span>\u003Cspan style=\"color:#79B8FF\">null\u003C/span>\u003Cspan style=\"color:#E1E4E8\">, \u003C/span>\u003Cspan style=\"color:#79B8FF\">2\u003C/span>\u003Cspan style=\"color:#E1E4E8\">));\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">  console.\u003C/span>\u003Cspan style=\"color:#B392F0\">log\u003C/span>\u003Cspan style=\"color:#E1E4E8\">(\u003C/span>\u003Cspan style=\"color:#9ECBFF\">`${\u003C/span>\u003Cspan style=\"color:#E1E4E8\">missing\u003C/span>\u003Cspan style=\"color:#9ECBFF\">.\u003C/span>\u003Cspan style=\"color:#79B8FF\">length\u003C/span>\u003Cspan style=\"color:#9ECBFF\">} handles introuvables sur Shopify`\u003C/span>\u003Cspan style=\"color:#E1E4E8\">);\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">})();\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Résultat : 312 handles manquants. Des produits supprimés ou renommés pendant la migration. Ces 312 cas ont été redirigés vers la collection parente plutôt que vers la homepage.\u003C/p>\n\u003Ch3>Étape 3 — Import massif dans Shopify\u003C/h3>\n\u003Cp>Shopify accepte l'import CSV de redirections via l'admin (\u003Ccode>Online Store > Navigation > URL Redirects > Import\u003C/code>). Format attendu :\u003C/p>\n\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">Redirect from,\u003C/span>\u003Cspan style=\"color:#F97583\">Redirect to\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">/skincare/creme-hydratante-aloe-vera.html,\u003C/span>\u003Cspan style=\"color:#F97583\">/products/creme-hydratante-aloe-vera\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">/skincare/serum-vitamine-c.html,\u003C/span>\u003Cspan style=\"color:#F97583\">/products/serum-vitamine-c\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#E1E4E8\">/haircare/shampoing-doux-avoine.html,\u003C/span>\u003Cspan style=\"color:#F97583\">/products/shampoing-doux-avoine\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Le fichier final contenait 8 088 redirections produit exactes et 312 redirections vers les collections. Plus 47 redirections catégorie corrigées — \u003Ccode>/skincare\u003C/code> vers \u003Ccode>/collections/skincare\u003C/code> au lieu de \u003Ccode>/\u003C/code>.\u003C/p>\n\u003Cp>L'import a été réalisé en trois lots (Shopify limite à 5 000 lignes par import CSV dans certains plans). Temps total : 25 minutes.\u003C/p>\n\u003Ch3>Étape 4 — Vérification post-déploiement\u003C/h3>\n\u003Cp>Un crawl Screaming Frog sur la liste complète des anciennes URLs. Configuration : \u003Ccode>Spider > Advanced > Always follow redirects OFF\u003C/code> pour voir les codes de statut intermédiaires.\u003C/p>\n\u003Cpre class=\"shiki github-dark\" style=\"background-color:#24292e;color:#e1e4e8\" tabindex=\"0\">\u003Ccode>\u003Cspan class=\"line\">\u003Cspan style=\"color:#6A737D\"># Vérification rapide via curl sur un échantillon de 50 URLs\u003C/span>\u003C/span>\n\u003Cspan class=\"line\">\u003Cspan style=\"color:#B392F0\">cat\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> sample_old_urls.txt\u003C/span>\u003Cspan style=\"color:#F97583\"> |\u003C/span>\u003Cspan style=\"color:#B392F0\"> xargs\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -I\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> {}\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> curl\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -o\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> /dev/null\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -s\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -w\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> \"%{http_code} %{redirect_url} {}\\n\"\u003C/span>\u003Cspan style=\"color:#79B8FF\"> -L\u003C/span>\u003Cspan style=\"color:#9ECBFF\"> {}\u003C/span>\u003C/span>\u003C/code>\u003C/pre>\n\u003Cp>Résultat : 8 400 URLs retournent un 301 vers la bonne destination. Zéro 404 restant sur les URLs connues.\u003C/p>\n\u003Ch3>Étape 5 — Forcer le re-crawl\u003C/h3>\n\u003Cp>Pour accélérer la prise en compte par Google :\u003C/p>\n\u003Col>\n\u003Cli>Soumission du nouveau sitemap Shopify dans Search Console\u003C/li>\n\u003Cli>Utilisation de l'API d'indexation pour les 200 pages les plus importantes (celles avec le plus de backlinks)\u003C/li>\n\u003Cli>Invalidation du rapport de couverture via \"Valider la correction\" sur les erreurs 404\u003C/li>\n\u003C/ol>\n\u003Ch3>Chronologie de récupération\u003C/h3>\n\u003Cul>\n\u003Cli>\u003Cstrong>J+2 après le fix\u003C/strong> : les 404 commencent à disparaître du rapport de couverture\u003C/li>\n\u003Cli>\u003Cstrong>J+7\u003C/strong> : 4 200 des anciennes URLs sont marquées \"redirigée\" dans Search Console\u003C/li>\n\u003Cli>\u003Cstrong>J+14\u003C/strong> : le trafic organique remonte à 7 800 sessions/jour (contre 6 100 au creux)\u003C/li>\n\u003Cli>\u003Cstrong>J+28\u003C/strong> : retour à 9 200 sessions/jour — 94 % du niveau pré-migration\u003C/li>\n\u003Cli>\u003Cstrong>J+45\u003C/strong> : stabilisation à 9 600 sessions/jour — légère progression grâce à la nouvelle vitesse Shopify (TTFB passé de 1,2s sous Magento à 380ms sous Shopify)\u003C/li>\n\u003C/ul>\n\u003Cp>Le Domain Rating a mis plus longtemps. Six semaines pour repasser de DR 48 à DR 51. Le DR 52 d'origine n'a été retrouvé qu'au bout de trois mois — le temps que les crawlers des outils tiers re-découvrent les redirections et réattribuent l'autorité.\u003C/p>\n\u003Cp>Le site n'a jamais récupéré 100 % de ses positions sur certaines requêtes longue traîne. Environ 340 pages produit avaient été désindexées pendant la fenêtre de 404 et n'ont jamais retrouvé leur position exacte. L'estimation de la perte nette sur le trimestre : 180 000 clics organiques.\u003C/p>\n\u003Ch3>Leçons opérationnelles\u003C/h3>\n\u003Cp>L'équipe a mis en place trois garde-fous pour les futures migrations :\u003C/p>\n\u003Col>\n\u003Cli>\n\u003Cp>\u003Cstrong>Crawl pré-migration obligatoire\u003C/strong>. Un export Screaming Frog complet de toutes les URLs indexées, croisé avec les données Search Console, constitue le fichier de référence avant toute migration. Comme détaillé dans le récit d'une \u003Ca href=\"/blog/migration-wordpress-vers-headless-strapi-4000-redirections-htaccess-oubliees\">migration WordPress vers headless Strapi\u003C/a>, l'absence de ce fichier est la cause racine de la majorité des pertes de redirections.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Validation des redirections en staging\u003C/strong>. Shopify ne propose pas d'environnement de staging natif, mais les redirections peuvent être testées via l'API Admin avant la bascule DNS.\u003C/p>\n\u003C/li>\n\u003Cli>\n\u003Cp>\u003Cstrong>Monitoring post-migration quotidien pendant 30 jours\u003C/strong>. Pas un check hebdomadaire. Un check quotidien des 404 dans Search Console, du nombre de pages indexées, et du trafic organique par landing page.\u003C/p>\n\u003C/li>\n\u003C/ol>\n\u003Cp>Le parallèle avec les \u003Ca href=\"/blog/migration-nuxt-2-vers-nuxt-3-200-pages-en-fallback-layout-pendant-6-semaines\">migrations de framework front-end\u003C/a> est frappant : le pattern est toujours le même. Une équipe concentrée sur le fonctionnel pousse en production. Le rendu visuel est parfait. Les URLs, les metas, les redirections — tout ce que Google voit et que l'utilisateur ne voit pas — passent entre les mailles.\u003C/p>\n\u003Cp>Et quand l'environnement de staging n'est pas \u003Ca href=\"/blog/how-to-stress-test-a-staging-environment-to-surface-risks-pre-launch-ask-an-seo-via-sejournal-helenpollitt1\">stress-testé sous l'angle SEO\u003C/a>, ces régressions restent invisibles jusqu'à ce que Search Console les remonte — avec trois semaines de retard.\u003C/p>\n\u003Ch2>Ce qu'on en retient\u003C/h2>\n\u003Cp>Une migration de plateforme e-commerce n'est pas un projet front-end. C'est un projet d'infrastructure SEO. Chaque URL est un actif. Chaque backlink est un vote d'autorité. Quand 8 400 URLs changent de structure sans table de redirections, ce n'est pas un \"détail technique\" — c'est une perte de revenus mesurable.\u003C/p>\n\u003Cp>Le fix est trivial. Un export SQL, un CSV, un import Shopify. Trente minutes de travail. Le vrai coût, c'est les trois semaines pendant lesquelles personne ne regarde.\u003C/p>\n\u003Cp>Un monitoring continu type Seogard détecte ce type de 404 massif dès le premier crawl post-déploiement — pas dix-huit jours plus tard quand le trafic a déjà décroché.\u003C/p>\n\u003Cpre>\u003Ccode>\u003C/code>\u003C/pre>",null,12,[18,19,20,21,22],"magento","shopify","migration","url structure","301","Migration Magento 2 → Shopify : 8 400 URLs sans 301","Wed May 27 2026 16:01:52 GMT+0000 (Coordinated Universal Time)",[26,40,53],{"_id":27,"slug":28,"__v":6,"author":7,"canonical":29,"category":10,"createdAt":30,"date":31,"description":32,"image":15,"imageAlt":15,"readingTime":33,"tags":34,"title":38,"updatedAt":39},"6a153757aa6b273b0c727dc2","migration-gatsby-vers-astro-rss-feed-orphelin-pendant-6-semaines","https://seogard.io/blog/migration-gatsby-vers-astro-rss-feed-orphelin-pendant-6-semaines","2026-05-26T06:01:59.887Z","2026-05-26","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.",11,[35,36,37,20],"gatsby","astro","rss","Migration Gatsby → Astro : RSS feed orphelin, 6 semaines","Tue May 26 2026 06:01:59 GMT+0000 (Coordinated Universal Time)",{"_id":41,"slug":42,"__v":6,"author":7,"canonical":43,"category":10,"createdAt":44,"date":31,"description":45,"image":15,"imageAlt":15,"readingTime":16,"tags":46,"title":51,"updatedAt":52},"6a15c401aa6b273b0ce69b93","migration-wordpress-vers-headless-strapi-4000-redirections-htaccess-oubliees","https://seogard.io/blog/migration-wordpress-vers-headless-strapi-4000-redirections-htaccess-oubliees","2026-05-26T16:02:09.891Z","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.",[47,48,49,22,50],"wordpress","strapi","jamstack","htaccess","WordPress vers Strapi headless : 4000 redirects .htaccess perdues","Tue May 26 2026 16:02:09 GMT+0000 (Coordinated Universal Time)",{"_id":54,"slug":55,"__v":6,"author":7,"canonical":56,"category":10,"createdAt":57,"date":58,"description":59,"image":15,"imageAlt":15,"readingTime":16,"tags":60,"title":66,"updatedAt":67},"6a141e10aa6b273b0c8a4eb7","react-17-vers-react-18-suspense-ssr-fait-crasher-next-head-en-streaming","https://seogard.io/blog/react-17-vers-react-18-suspense-ssr-fait-crasher-next-head-en-streaming","2026-05-25T10:01:52.337Z","2026-05-25","Migration React 17→18 : le streaming SSR réordonne les chunks et supprime les meta tags. Récit d'incident, diagnostic complet et patch Next.js.",[61,62,63,64,65],"react 18","suspense","ssr","next/head","streaming","React 18 Suspense SSR : next/head cassé par le streaming","Mon May 25 2026 10:01:52 GMT+0000 (Coordinated Universal Time)"]