TL;DRUn rich snippet ne s'obtient pas en cochant une case dans un plugin SEO : c'est le résultat direct de données structurées correctement écrites sur vos pages, que Google (et de plus en plus les moteurs IA génératifs) lit pour décider quoi afficher en plus du titre et de la meta description. Voici, avec le code exact que nous utilisons en production sur websource.fr, comment les mettre en place sans rien casser.

Agence web websource

Pourquoi le JSON-LD plutôt que les microdonnées#

Un rich snippet désigne tout résultat de recherche enrichi par rapport au simple triptyque titre/URL/description : étoiles de notation, question-réponse dépliable, date de publication, fil d'Ariane affiché à la place de l'URL... Deux syntaxes cohabitent dans la documentation schema.org : les microdonnées, qui s'écrivent directement dans les attributs HTML (itemscope, itemtype, itemprop) au milieu du contenu visible, et le JSON-LD, un unique bloc <script> séparé du HTML. Nous utilisons les deux sur websource.fr selon le cas, mais le JSON-LD reste notre premier choix dès que c'est possible.

La raison est pratique autant que technique : un attribut itemprop mal placé casse silencieusement tout le bloc englobant, et le retrouver dans une page HTML de plusieurs centaines de lignes prend du temps. Un bloc JSON-LD, lui, peut être copié, testé isolément dans le Rich Results Test de Google, et généré dynamiquement sans jamais toucher à la mise en page. Nous ne gardons des microdonnées que sur un seul type de contenu : le fil d'Ariane, où le balisage colle si naturellement à la structure de liens déjà présente qu'ajouter un bloc JSON-LD séparé aurait dupliqué l'information pour rien.

<nav aria-label="Fil d'ariane">
  <ol itemscope itemtype="https://schema.org/BreadcrumbList">
    <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
      <a itemprop="item" href="/"><span itemprop="name">Accueil</span></a>
      <meta itemprop="position" content="1">
    </li>
    <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
      <a itemprop="item" href="/blog"><span itemprop="name">Blog</span></a>
      <meta itemprop="position" content="2">
    </li>
    <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
      <span itemprop="name">Titre de la page courante</span>
      <meta itemprop="position" content="3">
    </li>
  </ol>
</nav>

Point d'attention qui piège presque tout le monde : la dernière miette du fil d'Ariane, celle de la page courante, ne doit jamais être un lien. Un itemprop="item" pointant vers l'URL de la page sur laquelle on se trouve déjà est redondant et Google Search Console le signale comme une erreur de validation.

L'entité Organization : la fondation de tous vos rich snippets#

Avant de balise une page en particulier, une entité Organization (ou LocalBusiness pour un commerce avec une adresse physique) doit exister quelque part sur le site, en général injectée dans toutes les pages depuis le gabarit global. C'est elle que les autres blocs JSON-LD viennent référencer par identifiant, plutôt que de la redéfinir à chaque fois.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "@id": "https://www.votresite.fr/#organization",
  "name": "Votre Entreprise",
  "url": "https://www.votresite.fr",
  "logo": "https://www.votresite.fr/images/logo.png",
  "telephone": "+33000000000",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "1 rue Exemple",
    "postalCode": "00000",
    "addressLocality": "Votre Ville",
    "addressCountry": "FR"
  },
  "sameAs": [
    "https://www.facebook.com/votreentreprise",
    "https://www.linkedin.com/company/votreentreprise"
  ]
}
</script>

L'astuce qui change tout une fois plusieurs blocs JSON-LD sur la même page (Organization, Person, Service, Article...) : donnez un "@id" stable à chaque entité (une URL suivie d'un fragment, comme #organization ci-dessus) et référencez-la ailleurs par { "@id": "https://www.votresite.fr/#organization" } plutôt que de recopier tous les champs. Un article de blog peut ainsi indiquer que son publisher est l'organisation sans jamais dupliquer son nom, son logo et son adresse – et le jour où l'adresse change, il n'y a qu'un seul endroit à corriger.

FAQPage : gagner de la place dans les résultats sans rien payer#

Le rich snippet FAQPage reste l'un des plus simples à mettre en œuvre et l'un des plus visibles : chaque question devient dépliable directement dans le résultat de recherche, avant même que l'internaute ait cliqué. La contrainte à respecter scrupuleusement : les questions et réponses balisées doivent être réellement visibles et lisibles sur la page, dans le même texte que celui du JSON-LD – un balisage FAQ sur des questions qui n'apparaissent nulle part dans le contenu visible est un cas typique de balisage trompeur pour Google.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "Combien de temps avant qu'un rich snippet apparaisse ?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Il n'y a pas de délai garanti : cela dépend de la fréquence de crawl de la page et de l'éligibilité de son contenu, généralement de quelques jours à plusieurs semaines."
      }
    },
    {
      "@type": "Question",
      "name": "Un balisage FAQPage est-il payant ?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Non, il s'agit uniquement de code ajouté à la page : aucune fonctionnalité Google Ads ni abonnement n'est nécessaire."
      }
    }
  ]
}
</script>

Un point technique découvert en générant ce bloc dynamiquement depuis une base de données plutôt qu'à la main : le champ text d'une réponse doit être encodé en JSON correctement échappé (guillemets, retours à la ligne, apostrophes), jamais construit par concaténation de chaînes. La quasi-totalité des JSON-LD invalides que nous avons corrigés sur des sites clients venaient de ce point précis : un caractère mal échappé rend tout le bloc – pas seulement le champ concerné – illisible pour Google.

AggregateRating et Review : le signal de confiance le plus souvent absent#

C'est le rich snippet qui a le plus d'impact visuel dans les résultats (les étoiles jaunes sous le titre) et pourtant le plus rarement bien implémenté, pour une raison simple : il exige de vraies données, pas seulement du code. Un AggregateRating doit être calculé à partir d'avis réellement collectés – jamais une note inventée " pour donner confiance ".

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "name": "Votre Entreprise",
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.8",
    "reviewCount": "42",
    "bestRating": "5",
    "worstRating": "1"
  },
  "review": [
    {
      "@type": "Review",
      "author": { "@type": "Person", "name": "Prénom Nom" },
      "datePublished": "2026-06-12",
      "reviewBody": "Texte réel de l'avis client.",
      "reviewRating": {
        "@type": "Rating",
        "ratingValue": "5",
        "bestRating": "5"
      }
    }
  ]
}
</script>

Une règle de validation méconnue, qui invalide silencieusement une partie du balisage sur beaucoup de sites : un objet Review sans author.name est rejeté par Google. Sur un import d'avis en masse (export d'une fiche Google Business, par exemple), certains avis n'ont qu'un pseudonyme anonymisé ou aucun nom exploitable. La bonne pratique n'est pas de les exclure du calcul de la note moyenne – ils restent des avis réels, légitimes dans l'aggregateRating – mais de ne pas produire d'objet Review individuel pour eux dans le tableau review, faute d'un nom d'auteur affichable.

Le module PrestaShop gratuit qui automatise l'AggregateRating#

Sur les boutiques PrestaShop que nous exploitons, le constat était toujours le même : une fiche Google Business avec des dizaines d'avis 5 étoiles, mais strictement aucune trace de ces avis dans les données structurées du site marchand. Nous avons publié un module gratuit, Websource Google Reviews, qui comble ce manque sans rien inventer : vous importez vos vrais avis (copier-coller depuis votre fiche Google, ou format texte simple), le module génère une page publique /avis-clients et calcule un AggregateRating réel à partir de ces avis.

Le module ne modifie jamais les fichiers du thème : l'intégration au JSON-LD global de la boutique reste volontairement manuelle, chaque thème PrestaShop organisant ses données structurées différemment. Un appel de méthode statique suffit pour récupérer la note et le nombre d'avis :

{assign var="wsgrAggregate" value=WebsourceGooglereviews::getAggregate()}
{if $wsgrAggregate.count > 0}
,"aggregateRating": {
  "@type": "AggregateRating",
  "ratingValue": "{$wsgrAggregate.rating}",
  "bestRating": "{$wsgrAggregate.best}",
  "worstRating": "{$wsgrAggregate.worst}",
  "reviewCount": "{$wsgrAggregate.count}"
}
{/if}

Compatible PrestaShop 1.7 à 9.x, installation classique par zip depuis le back-office (Modules > Gestionnaire de modules > Importer un module). Le code source complet, le détail de l'import (export Google collé tel quel, format note|auteur|texte|date, ou ajout unitaire) et la licence d'usage libre non commercial sont sur le dépôt GitHub : Websource-fr/websourcegooglereviews.

Article et BlogPosting : baliser un contenu éditorial#

Pour un article de blog, le type BlogPosting (ou NewsArticle pour un contenu d'actualité au sens strict) permet à Google d'afficher la date de publication, l'auteur et l'image mise en avant directement dans les résultats, et sert de signal supplémentaire aux moteurs de réponse IA pour identifier qui a écrit quoi et quand.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "headline": "Titre de l'article",
  "url": "https://www.votresite.fr/mon-article",
  "image": "https://www.votresite.fr/uploads/mon-article.jpg",
  "datePublished": "2026-09-22T09:00:00+02:00",
  "dateModified": "2026-09-22T09:00:00+02:00",
  "author": {
    "@type": "Person",
    "name": "Prénom Nom",
    "jobTitle": "Rédacteur"
  },
  "publisher": { "@id": "https://www.votresite.fr/#organization" }
}
</script>

Deux champs sont trop souvent oubliés alors qu'ils sont gratuits à renseigner : dateModified, distinct de datePublished, qui indique à Google qu'un contenu ancien reste entretenu plutôt qu'abandonné ; et le @id du publisher, qui doit pointer vers la même entité Organization que le reste du site plutôt que de redéfinir une organisation " flottante " propre à chaque article – un piège classique quand plusieurs personnes ou plusieurs outils génèrent le JSON-LD sans se coordonner sur un identifiant commun.

Vérifier avant de mettre en production#

Un JSON-LD syntaxiquement valide n'est pas forcément un JSON-LD accepté par Google : les deux validations sont différentes et aucune des deux ne remplace l'autre.

  1. Valider la syntaxe JSON pure (un simple JSON.parse() dans la console du navigateur suffit, ou un linter JSON) pour écarter les erreurs d'échappement.
  2. Passer l'URL de la page dans le Rich Results Test de Google, qui indique précisément les champs obligatoires manquants pour chaque type de rich snippet.
  3. Vérifier dans Google Search Console, rubrique " Améliorations ", que le type de contenu structuré apparaît sans erreur ni avertissement une fois la page réindexée.
  4. Recouper chaque donnée balisée avec ce qui est réellement visible sur la page : un avis, une question de FAQ ou une note qui n'existent pas dans le contenu affiché constituent un balisage trompeur, sanctionnable par Google indépendamment de la validité technique du code.
  5. Revérifier après toute refonte de thème ou migration de CMS : un changement de gabarit casse plus souvent le JSON-LD qu'il ne le laisse intact, en particulier quand il était codé en dur dans un fichier de thème plutôt que généré dynamiquement.

Questions fréquentes#

Un rich snippet garantit-il une meilleure position dans Google ?#

Non. Les données structurées influencent l'affichage du résultat (étoiles, FAQ dépliable, date), pas le classement lui-même. L'effet indirect passe par un meilleur taux de clic, pas par un bonus de positionnement.

Peut-on utiliser plusieurs blocs JSON-LD sur la même page ?#

Oui, c'est même la pratique recommandée : un bloc par type d'entité (Organization, BreadcrumbList, Article...), reliés entre eux par leurs identifiants @id plutôt que fusionnés dans un unique bloc géant.

Le balisage FAQPage fonctionne-t-il sur n'importe quelle page ?#

Techniquement oui, mais Google réserve de plus en plus l'affichage de ce rich snippet aux sites gouvernementaux et de santé reconnus pour certaines requêtes sensibles ; sur la majorité des sites d'entreprise ou e-commerce, l'affichage reste possible dès lors que les questions et réponses sont réellement présentes sur la page.

Que se passe-t-il si le JSON-LD contient une erreur ?#

Dans la majorité des cas, Google ignore simplement le rich snippet concerné sans pénaliser le reste de la page – sauf en cas de contenu structuré manifestement trompeur (avis inventés, notes gonflées), qui peut entraîner une action manuelle sur l'ensemble du site.

Faut-il un module ou un plugin pour faire tout cela ?#

Non : le JSON-LD est du texte brut, injectable depuis n'importe quel gabarit (Twig, Smarty, Blade, PHP simple) sans dépendance externe. Un module comme Websource Google Reviews n'est utile que pour automatiser la collecte et le calcul d'une donnée précise – ici, les avis clients – pas pour le balisage en lui-même.

Article rédigé le 22/09/2026 par l'équipe Websource à partir des sources citées ci-dessus, sur la base des données structurées effectivement en production sur websource.fr, puis relu avant publication. Une information vous semble inexacte ou datée ? Signalez-le nous, nous corrigeons.