Deux blocs <script type="application/ld+json"> de type Product sur la même page, avec des valeurs de prix légèrement différentes selon le moment de génération : c’est ce que remonte l’outil de test des résultats enrichis de Google sur une fiche produit WooCommerce équipée de Rank Math. La tentation est d’accuser l’extension SEO d’un bug, alors que le générateur concurrent tourne dans le cœur même de WooCommerce.
WooCommerce embarque depuis longtemps sa propre classe WC_Structured_Data, qui génère automatiquement un balisage Product sur chaque fiche produit, indépendamment de toute extension SEO installée. Rank Math, de son côté, propose un module WooCommerce dédié qui génère également ce balisage, avec des champs souvent plus complets (avis, disponibilité par variation, marque). Les deux tournent en parallèle si personne n’a désactivé l’un des deux.
Où se cache exactement le générateur natif de WooCommerce
Le balisage natif est injecté via le hook woocommerce_single_product_summary, à la priorité 60, par la méthode generate_product_data de la classe WC_Structured_Data. Ce comportement est actif par défaut sur n’importe quelle installation WooCommerce, sans configuration particulière — la plupart des développeurs l’ignorent simplement parce qu’il ne s’affiche nulle part dans l’interface d’administration.
Rank Math, lui, s’accroche à d’autres points d’ancrage (son propre système de schéma configurable depuis l’éditeur Gutenberg), et n’a aucun moyen de savoir que WooCommerce a déjà injecté un balisage concurrent sur la même page.
Diagnostic en trois vérifications
- Affichez le code source de la fiche produit et cherchez le nombre d’occurrences de
"@type": "Product"— s’il y en a deux, le conflit est confirmé. - Comparez les deux blocs : celui de WooCommerce est généralement plus minimal (nom, prix, disponibilité), celui de Rank Math plus riche (notation, marque, image en plusieurs tailles).
- Dans l’outil de test des résultats enrichis de Google, vérifiez si l’avertissement porte sur des champs dupliqués ou contradictoires entre les deux blocs.

Le correctif : désactiver le générateur natif, jamais le module Rank Math
La bonne pratique consiste à conserver le balisage de Rank Math, plus complet et directement configurable, et à retirer le générateur natif de WooCommerce via un remove_action ciblé, placé dans un plugin d’extension léger ou dans les fonctions du thème enfant :
add_action( 'wp', function () {
if ( class_exists( 'WC_Structured_Data' ) && function_exists( 'WC' ) ) {
remove_action(
'woocommerce_single_product_summary',
array( WC()->structured_data, 'generate_product_data' ),
60
);
}
} );
Ce retrait cible précisément l’affichage sur la fiche produit ; il ne touche pas les autres usages de WC_Structured_Data, comme le balisage BreadcrumbList ou WebSite, qui restent gérés séparément.
Alternative si Rank Math ne couvre pas WooCommerce
Sur les installations où le module WooCommerce de Rank Math n’est pas activé (certains forfaits ou configurations personnalisées), il vaut mieux laisser le générateur natif de WooCommerce actif plutôt que de se retrouver sans aucun balisage Product. Vérifiez l’activation du module dans Rank Math > Réglages généraux > WooCommerce avant de retirer quoi que ce soit côté WooCommerce.
Sur nos projets, la règle est de ne jamais empiler deux générateurs de structured data sur le même type d’entité : un seul plugin fait autorité sur le balisage
Product, documenté explicitement dans les notes techniques du site.
Vérifier après correction
Une fois le générateur natif retiré, revalidez la fiche produit avec l’outil de test de Google et videz le cache de page si le site en utilise un — un balisage JSON-LD mis en cache avant la correction peut continuer à s’afficher en double pendant plusieurs heures si les pages produit ne sont pas explicitement purgées.
En résumé
Le double balisage Schema.org sur une fiche produit WooCommerce vient rarement d’un bug de l’extension SEO installée : il vient de la coexistence, invisible dans l’administration, entre le générateur natif de WooCommerce et celui de Rank Math. Un remove_action ciblé sur generate_product_data suffit à trancher, sans toucher au reste du balisage structuré du site.