Comment ça marche
Le problème : Coveo Atomic Commerce est une librairie purement client. Googlebot accède à la page catégorie, charge le HTML… mais ne voit aucun produit, parce que Atomic attend du JavaScript pour hydrater les produits. Résultat : BMR perd son indexation sur les PLP.
La solution (cette démo) : un Worker Cloudflare intercepte chaque page catégorie avant qu’elle ne parte au navigateur. Il fait le travail d’hydratation à la place de Atomic, et injecte une grille de produits prête-à-indexer directement dans le HTML.
- Le Worker intercepte l’URL de la catégorie (
/en/*/*.htmlou/fr/*/*.html). - Il demande un token Coveo à l’endpoint Magento existant de BMR (
/rest/V1/search/token). Aucune clé API exposée. - Il appelle l’API commerce Coveo (
/commerce/v2/listing) pour obtenir les 24 premiers produits de la catégorie. - En parallèle, il récupère le HTML original depuis Magento (www.bmr.ca).
- Il injecte la grille de produits + les données structurées
JSON-LD(ItemList, CollectionPage, BreadcrumbList) dans le HTML, à côté de la zone Atomic. - Il met en cache le résultat sur le réseau Cloudflare (10 min frais, 60 min stale-while-revalidate).
Googlebot, ChatGPT-User et Perplexity voient les 24 produits instantanément. Les utilisateurs humains voient la même chose jusqu’à ce que Atomic se connecte et reprenne le contrôle dans le navigateur.
Architecture
Un seul Worker, trois couches de cache, aucune modification chez BMR ni Coveo
Entrées : URL de catégorie BMR. Sorties : HTML Magento avec injection SSR (grille + JSON-LD) et en-têtes x-ssr-* pour l’observabilité.
Catégories de démo
6 catégories · EN + FR · 24 produits par page
Outdoor Furniture
Aménagements extérieursOutdoor Power Equipment
Équipements motorisésLandscaping
Aménagements paysagersRoofing
ToituresInterior Doors
Portes d’intérieurVérifier le SSR
Comparer ce que Googlebot voit
Cette démo — bmr-coveo.alya.ai
curl -sA "Googlebot/2.1" \
"https://bmr-coveo.alya.ai/en/tools/\
corded-and-cordless-power-tools.html" \
| grep -oE 'class="seo-product"' | wc -l
Production — www.bmr.ca
curl -sA "Googlebot/2.1" \
"https://www.bmr.ca/en/tools/\
corded-and-cordless-power-tools.html" \
| grep -oE 'class="seo-product"' | wc -l
Bascule démo — ce que Google voit aujourd’hui
Toutes les pages de démo ont un bouton « Voir sans notre solution »
Cliquez le bouton rouge en haut de n’importe quelle PLP de démo (ou ajoutez ?_demo=raw à l’URL) pour charger la même page sans injection SSR — c’est exactement le HTML que reçoit Googlebot sur www.bmr.ca aujourd’hui : zéro produit dans le HTML rendu.
Avec notre solution
URL standard — bmr-coveo.alya.ai/en/…
✓ Pagination
?p=N crawlable par Google✓ Facettes indexables (catégories, marques)
✓ JSON-LD ItemList + CollectionPage + Breadcrumbs
Sans notre solution (= www.bmr.ca aujourd’hui)
Ajoutez ?_demo=raw à n’importe quelle URL
✗ Pagination
#page=1 ignorée par Google✗ Aucune donnée structurée produit
✗ Atomic attend du JS que Googlebot n’exécute pas à temps
Repli (fallback) & robustesse
Le Worker ne renvoie jamais une page vide
Si Coveo n’a pas de listing configuration pour une URL (erreur LISTING_CONFIGURATION_NOT_FOUND) ou retourne 0 produit, le Worker cascade à travers 3 niveaux de repli :
1. commerce/v2/listing | Appel principal. Requiert que la catégorie soit enregistrée dans Coveo Merchandising Hub par Valtech. |
2. commerce/v2/search (repli) | Si le listing est manquant ou vide, le Worker dérive une requête à partir du slug de la catégorie et interroge l’API de recherche Coveo. Permet de couvrir les catégories pas encore configurées. |
| 3. Page empty-state | Si les deux premiers niveaux ne donnent aucun résultat, le Worker rend une page explicite « Aucun produit trouvé » avec liens vers la catégorie parente + la page d’accueil. Jamais de 404. |
| 4. Pass-through Magento | Si Coveo est complètement indisponible (timeout, 5xx), le Worker renvoie le HTML Magento non modifié — la page fonctionne comme aujourd’hui sur www.bmr.ca. |
Les en-têtes x-ssr-cache: BYPASS + x-ssr-error indiquent précisément quel niveau a été utilisé — facile à monitorer en production.
Contrôle du cache
Paramètres de requête pour debug + opérations
?_ssr=bypass | Force un rendu frais, ignore le cache L2. Utile pour tester une modification sans attendre le TTL de 10 min. |
?_ssr=purge | Purge l’entrée de cache pour l’URL courante et retourne un JSON de confirmation. Utilisable par les outils de CI après un déploiement de changement de prix. |
?_demo=raw | Bascule démo : retourne le HTML Magento brut, sans injection SSR (= vue Googlebot actuelle sur bmr.ca). |
?p=N | Sélectionne la page N de la pagination (cache séparé par page). |
En-têtes de réponse du Worker
x-ssr-cache | HIT | MISS | STALE | BYPASS | DEMO-RAW — état du cache L2 (HTML) |
x-ssr-source | render, fallback, ou demo-raw |
x-ssr-product-count | Nombre de produits injectés dans cette réponse |
x-ssr-render-ms | Temps de rendu edge — cible < 50 ms en cache, < 900 ms en miss |
x-ssr-locale | en ou fr détecté automatiquement par URL |
x-ssr-demo | Présent uniquement sur ?_demo=raw (vue Google sans SSR). |
x-ssr-error | Présent uniquement en cas d’erreur (timeout Coveo, config manquante). |