Démo Index Web Marketing · 2026-04-23

BMR × Coveo × Cloudflare

Récupération du référencement naturel des pages catégorie BMR en rendant côté-serveur les produits Coveo Atomic Commerce — sans cloaking, sans modifier Magento ni Coveo. Un seul fichier, un seul Worker.

48produits SSR par page
<50msTTFB en cache
4 niveauxde repli si Coveo échoue
0 cloakingmême HTML pour bots et humains

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.

  1. Le Worker intercepte l’URL de la catégorie (/en/*/*.html ou /fr/*/*.html).
  2. Il demande un token Coveo à l’endpoint Magento existant de BMR (/rest/V1/search/token). Aucune clé API exposée.
  3. Il appelle l’API commerce Coveo (/commerce/v2/listing) pour obtenir les 24 premiers produits de la catégorie.
  4. En parallèle, il récupère le HTML original depuis Magento (www.bmr.ca).
  5. 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.
  6. 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

Googlebot / User HTTP GET Cloudflare Worker bmr-coveo.alya.ai 1. Cache edge (HTML 10 min) 2. Cache KV (token 50 min) 3. Injection SSR — 24 produits 4. JSON-LD · ItemList · Breadcrumbs ~870 ms au render · <50 ms en cache BMR Magento www.bmr.ca · coque HTML + jeton Coveo Commerce API /commerce/v2/listing Top 24 par catégorie

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

Vé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
→ 24 produits indexables

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
→ 0 produit · Atomic ne s’hydrate pas pour le bot

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/…

✓ 48 produits injectés dans le HTML
✓ 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

✗ 0 produit dans le HTML rendu
✗ 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/listingAppel 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-stateSi 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 MagentoSi 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=bypassForce un rendu frais, ignore le cache L2. Utile pour tester une modification sans attendre le TTL de 10 min.
?_ssr=purgePurge 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=rawBascule démo : retourne le HTML Magento brut, sans injection SSR (= vue Googlebot actuelle sur bmr.ca).
?p=NSélectionne la page N de la pagination (cache séparé par page).

En-têtes de réponse du Worker

x-ssr-cacheHIT | MISS | STALE | BYPASS | DEMO-RAW — état du cache L2 (HTML)
x-ssr-sourcerender, fallback, ou demo-raw
x-ssr-product-countNombre de produits injectés dans cette réponse
x-ssr-render-msTemps de rendu edge — cible < 50 ms en cache, < 900 ms en miss
x-ssr-localeen ou fr détecté automatiquement par URL
x-ssr-demoPrésent uniquement sur ?_demo=raw (vue Google sans SSR).
x-ssr-errorPrésent uniquement en cas d’erreur (timeout Coveo, config manquante).