# Données structurées JSON-LD : le modèle qui rend vos faits citables

> Le texte de votre page se prête à l'interprétation. Le JSON-LD, non : c'est le seul endroit où vos faits sont typés, reliés et non ambigus. Voici comment l'écrire pour qu'un modèle s'en serve — et les pièges qui l'annulent.

Publié le: 2026-08-20 · Mis à jour le: 2026-08-26 · 7 min de lecture
Source: https://indexonic.com/blog/donnees-structurees-json-ld-moteurs-de-reponse/

Un moteur de réponse lit votre page comme un humain pressé : il en tire du sens, avec une marge d'erreur. Il lit votre JSON-LD comme une base de données : sans marge d'erreur. C'est toute la valeur des données structurées à l'ère des assistants — non pas un bonus de classement, mais un moyen d'affirmer vos faits dans une forme qui ne peut pas être mal comprise.

## Un seul graphe, des identifiants stables

L'erreur la plus répandue n'est pas d'oublier le JSON-LD : c'est d'en avoir trois, posés par le thème, par une extension SEO et par un module d'avis, qui se contredisent. Un moteur qui rencontre deux noms d'entreprise différents sur la même page ne choisit pas : il se méfie.

Le patron qui règle ce problème s'appelle le graphe. Un seul bloc `<script type="application/ld+json">`, une clé `@graph`, et à l'intérieur chaque nœud porte un `@id` stable — une URL avec un fragment — auquel les autres nœuds font référence au lieu de dupliquer l'information.

*Le squelette : quatre nœuds, reliés par @id*

```
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@graph": [
    { "@type": "Organization",
      "@id": "https://exemple.ma/#organization",
      "name": "Atlas Cargo SARL",
      "url": "https://exemple.ma/" },

    { "@type": "WebSite",
      "@id": "https://exemple.ma/#website",
      "url": "https://exemple.ma/",
      "publisher": { "@id": "https://exemple.ma/#organization" },
      "inLanguage": "fr" },

    { "@type": "WebPage",
      "@id": "https://exemple.ma/tarifs#webpage",
      "url": "https://exemple.ma/tarifs",
      "isPartOf": { "@id": "https://exemple.ma/#website" },
      "about": { "@id": "https://exemple.ma/#organization" } },

    { "@type": "BreadcrumbList",
      "@id": "https://exemple.ma/tarifs#breadcrumb",
      "itemListElement": [
        { "@type": "ListItem", "position": 1, "name": "Accueil", "item": "https://exemple.ma/" },
        { "@type": "ListItem", "position": 2, "name": "Tarifs" }
      ] }
  ]
}
</script>
```

Trois propriétés de ce patron méritent d'être comprises plutôt que copiées. Les `@id` doivent être **stables dans le temps** : c'est ce qui permet de reconnaître la même entité d'une page à l'autre et d'une visite à la suivante. Les références remplacent la duplication : le nom de l'entreprise n'est écrit qu'une fois, donc il ne peut pas diverger. Et le dernier `ListItem` d'un fil d'Ariane n'a pas d'`item` : la page courante ne se lie pas à elle-même.

## Les types qui comptent vraiment

| Type | À quoi il sert | Propriétés à ne pas manquer |
| --- | --- | --- |
| Organization | Identifier l'entité | name, url, logo, sameAs, contactPoint |
| LocalBusiness | Commerce avec adresse physique | address, geo, openingHoursSpecification, telephone, areaServed, priceRange |
| Service / Product | Ce que vous vendez | name, description, provider, offers, areaServed |
| Offer | Le prix et sa validité | price, priceCurrency, availability, validThrough |
| FAQPage | Questions et réponses réelles | mainEntity, acceptedAnswer |
| Article / BlogPosting | Contenu éditorial | headline, datePublished, dateModified, author |
| BreadcrumbList | Position dans le site | itemListElement, position |

Une note sur `FAQPage`. Les résultats enrichis correspondants ont été fortement restreints par Google et ne s'affichent plus pour la plupart des sites. Le balisage reste néanmoins utile ici, pour une raison différente : il présente vos questions-réponses sous une forme déjà découpée, exactement le format qu'un moteur de réponse réutilise. Le rich result a disparu ; l'extractibilité, elle, est restée.

## La règle de cohérence — celle que presque tout le monde viole

Le balisage doit décrire ce que la page montre. Un prix affiché à 4 500 MAD et un `Offer` à 3 900, une adresse à Casablanca dans le pied de page et à Rabat dans le JSON-LD, des horaires d'ouverture qui ne correspondent à aucun texte visible : chacun de ces écarts transforme une aide en signal négatif. Google refuse les résultats enrichis pour du balisage non représentatif du contenu, et un modèle qui détecte une contradiction cesse simplement de vous traiter comme une source fiable.

> **Le cas le plus grave, vu chez nous** — Notre propre générateur a un temps produit un `sameAs` pointant vers un identifiant Wikidata déduit du nom de la marque — qui n'existait pas et répondait 404. Le fichier paraissait excellent et affirmait une fausseté vérifiable. Nous avons supprimé la fonctionnalité et imposé la règle suivante : plus aucune URL n'est publiée sans avoir été récupérée et avoir répondu 200.

Appliquez la même règle chez vous. `sameAs` ne doit contenir que des profils que vous contrôlez réellement et qui répondent : votre page LinkedIn, votre fiche d'entreprise, votre compte Instagram. Un profil inventé ou abandonné est pire qu'un tableau vide.

## Un exemple complet : commerce local marocain

*LocalBusiness — à adapter, sans rien inventer*

```
{
  "@context": "https://schema.org",
  "@type": "LocalBusiness",
  "@id": "https://exemple.ma/#business",
  "name": "Atlas Cargo SARL",
  "description": "Transport et dédouanement entre Casablanca, Tanger Med et l'Europe.",
  "url": "https://exemple.ma/",
  "telephone": "+212522000000",
  "email": "contact@exemple.ma",
  "priceRange": "$$",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "45 boulevard Zerktouni",
    "addressLocality": "Casablanca",
    "postalCode": "20250",
    "addressCountry": "MA"
  },
  "geo": { "@type": "GeoCoordinates", "latitude": 33.589886, "longitude": -7.633076 },
  "areaServed": [
    { "@type": "City", "name": "Casablanca" },
    { "@type": "City", "name": "Tanger" },
    { "@type": "Country", "name": "Maroc" }
  ],
  "openingHoursSpecification": [
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday","Tuesday","Wednesday","Thursday","Friday"],
      "opens": "08:30", "closes": "18:00" },
    { "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Saturday", "opens": "09:00", "closes": "13:00" }
  ],
  "availableLanguage": ["ar", "fr", "en"],
  "sameAs": ["https://www.linkedin.com/company/exemple-ma"]
}
```

Quatre points qui font la différence dans un contexte marocain. Le téléphone s'écrit au format international, sans espaces : c'est ainsi qu'il est comparable d'une source à l'autre. `addressCountry` prend le code `MA`, pas le mot « Maroc ». `areaServed` mérite d'être explicite quand vous intervenez au-delà de votre ville — c'est la propriété qui répond à « qui fait ça à Tanger ? ». Et `availableLanguage` compte réellement ici : la question peut arriver en arabe, en français ou en anglais, et vous venez d'indiquer que vous répondez dans les trois.

## Le cas WordPress : trois sources, une seule vérité

Sur un site WordPress typique, le balisage vient de trois endroits à la fois : le thème en pose une partie, l'extension de référencement une autre, et un module d'avis ou de réservation ajoute la sienne. Personne ne l'a décidé, et personne ne le voit — jusqu'à l'audit. La marche à suivre est toujours la même : afficher la source de la page, chercher chaque occurrence de `application/ld+json`, et compter.

*Combien de blocs votre page publie-t-elle vraiment ?*

```
curl -sS https://votre-domaine.com/ | grep -c 'application/ld+json'
# Plus de 1 : identifiez qui pose quoi, gardez une seule source, désactivez les autres.
```

Ensuite, choisissez la source qui restera — le plus souvent l'extension de référencement, parce qu'elle survit au changement de thème — et coupez les autres dans leurs réglages. Si un module refuse de se taire, un filtre dans le thème enfant reste préférable à trois graphes contradictoires. Le but n'est pas d'avoir le balisage le plus riche : c'est d'avoir un seul balisage, exact.

## Ce qui invalide tout le bloc

- **Un JSON invalide.** Une virgule finale, un guillemet typographique collé par un traitement de texte, et le bloc entier est ignoré — silencieusement.
- **Des notes et avis inventés.** Un `aggregateRating` sans avis réels et visibles sur la page est une violation directe des règles, et l'infraction la plus facile à détecter automatiquement.
- **Des images qui répondent 404.** Un `logo` ou une `image` mort disqualifie le nœud qui les porte.
- **Des `@id` instables.** S'ils changent à chaque déploiement, l'entité est recréée à chaque visite et n'accumule jamais rien.
- **Plusieurs blocs concurrents.** Thème + extension SEO + module d'avis : trois sources, trois vérités. Consolidez en un seul graphe.
- **Du balisage sur du contenu absent de la page.** Une FAQ en JSON-LD dont les questions n'apparaissent nulle part visuellement est du balisage non représentatif.

## Valider, puis vérifier

Deux outils gratuits, deux fonctions différentes. [validator.schema.org](https://validator.schema.org/) contrôle la conformité au vocabulaire : types, propriétés, structure. [Le test des résultats enrichis](https://search.google.com/test/rich-results) répond à une autre question — Google peut-il en tirer un affichage particulier. Un balisage parfaitement valide peut n'ouvrir droit à aucun résultat enrichi ; ce n'est pas une erreur, les deux objectifs sont distincts.

Aucun des deux ne vérifie ce qui compte le plus : que vos affirmations soient vraies et cohérentes avec la page. Cette vérification-là reste humaine — ou automatisée avec une règle explicite, comme la nôtre : chaque URL publiée est récupérée avant publication, et une réponse autre que 200 empêche la publication du fichier.

> **Contrôle gratuit** — L'audit Indexonic extrait votre graphe, vérifie sa validité, teste chaque URL qu'il contient et signale les contradictions entre le balisage et le texte visible.


## Questions fréquentes

### JSON-LD, microdata ou RDFa ?
JSON-LD. C'est le format recommandé par Google, il vit dans un bloc séparé du HTML, donc il survit à une refonte graphique, et il se relit sans démêler le balisage de la mise en page.

### Le balisage FAQPage sert-il encore à quelque chose ?
Pour les résultats enrichis, presque plus : Google en a fortement restreint l'affichage. Pour les moteurs de réponse, oui : il livre vos questions-réponses déjà découpées, dans la forme exacte qu'un assistant réutilise.

### Faut-il baliser chaque page ?
Chaque page doit porter au minimum WebPage relié au WebSite et à l'Organization. Au-delà, on balise ce que la page contient réellement : un service sur la page service, un article sur un article. Le balisage sans contenu correspondant est une faute, pas un supplément.

### Où placer le bloc dans la page ?
Dans le , en un seul bloc. La position n'a pas d'effet technique, mais un bloc unique et central est ce qui empêche la réapparition de graphes concurrents.

---
Indexonic — https://indexonic.com · https://agent.indexonic.com
