Développeur Drupal vérifiant la sortie JSON-LD dans les outils de développement du navigateur à côté d'un formulaire d'édition produit - métaphore du markup Schema.org piloté par les champs avec Metatag.

JSON-LD dans Drupal: comment générer des données structurées à partir des champs avec Schema.org Metatag

La façon la plus sûre d'ajouter du JSON-LD à Drupal est de mapper les properties Schema.org sur les champs de contenu existants. Configurez le mapping une fois par content type avec Metatag et Schema.org Metatag. Les rédacteurs mettent à jour le produit, l'article ou le service comme d'habitude, tandis que Drupal génère le JSON-LD à partir des mêmes valeurs visibles sur la page.

Le JSON-LD dans Drupal fonctionne le mieux quand les données structurées proviennent du même modèle de champs que la page visible. Ce modèle évite une seconde copie cachée des prix, noms et disponibilités. Il donne aussi à l'équipe de développement une configuration à exporter, relire et tester. Lisez aussi : Schema.org et métadonnées dans Drupal - la vue d'ensemble avant de mapper des bundles individuels avec Schema.org Metatag.

C'est mieux que de demander aux rédacteurs de maintenir une seconde copie cachée des faits. La configuration est simple. La partie difficile consiste à décider quels champs font autorité, à gérer les valeurs vides et à empêcher qu'un nouveau content type arrive en production sans mapping. Le SEO technique dépend aussi d'un markup qui correspond à ce que voit le visiteur, pas seulement d'une syntaxe qui passe un validateur.

Dans cet article :

Pourquoi le JSON-LD écrit à la main dérive-t-il du contenu de la page ?

Supposons qu'une page produit affiche un prix de EUR 249. Le template lit cette valeur depuis field_price, mais quelqu'un a saisi le même nombre manuellement dans un bloc JSON-LD.

L'équipe commerciale change le prix en EUR 269. La page visible se met à jour. Le markup caché, non.

La page fait alors deux affirmations sur le même produit. La validation syntaxique peut encore réussir, car les deux valeurs sont des nombres valides. Le problème, c'est l'exactitude.

Les consignes Google sur les données structurées indiquent que le markup doit décrire le contenu visible pour le lecteur. Un nom, un prix ou une disponibilité dans le JSON-LD doivent donc provenir de la même source que la valeur visible. La même règle s'applique quand le texte dans les images cache des faits aux moteurs et aux fetchers IA - si le fait n'est pas dans le HTML, les données structurées ne peuvent pas le remplacer de façon fiable.

Drupal a déjà cette source : les champs.

Schema.org Metatag étend le module Metatag. Il définit des groupes pour des types comme Article, Product, Service, Organization et WebSite, puis rend les properties configurées sous forme de script application/ld+json dans le head. Les tokens relient ces properties aux champs d'entité.

Une modification peut mettre à jour les deux sorties.

Quels sous-modules Schema.org Metatag faut-il activer ?

Schema.org Metatag 3.0.4 prend en charge Drupal 9, 10 et 11. Le module de base requiert Metatag et PHP 8 ou plus récent. Installez le package avec Composer :

composer require 'drupal/schema_metatag:^3.0'

Activez le module de base et les sous-modules qui correspondent aux pages que vous allez marquer. Pour un catalogue produit :

drush en schema_metatag schema_product schema_organization schema_web_site -y
drush cr

N'activez pas automatiquement chaque sous-module. Chacun ajoute un autre groupe de paramètres et un autre type que l'équipe peut se sentir obligée de configurer. Commencez par les pages qui contiennent des données utiles et maintenues.

Un premier passage sensé :

  • schema_web_site et schema_organization pour l'identité site-wide,
  • schema_article pour les articles et actualités,
  • schema_product pour les vraies pages produit,
  • schema_service pour les pages service quand les properties décrivent du contenu visible,
  • le support breadcrumb du module là où le site affiche déjà des fil d'Ariane.

Schema.org contient bien plus de types que le module n'en expose. Google prend aussi en charge les rich results pour un ensemble plus petit que Schema.org ne le définit. Choisissez un type parce qu'il décrit la page et a un consommateur, pas parce qu'il figure dans une liste.

Comment configurer les defaults Metatag avant de mapper les properties ?

Allez à :

Configuration → Search and metadata → Metatag

Le chemin est :

/admin/config/search/metatag

Metatag combine les valeurs via une hiérarchie :

  1. Global defaults s'appliquent sur tout le site.
  2. Entity defaults s'appliquent à un type d'entité comme Content.
  3. Bundle defaults les remplacent pour un content type comme Product.
  4. Entity-level values peuvent remplacer les defaults quand un champ Metatag est attaché à un enregistrement individuel.

Le niveau bundle doit faire la majeure partie du travail. Un content type Product a besoin d'un mapping revu que tous les nodes produit héritent.

Évitez l'édition de schema au niveau entité, sauf si la page est une vraie exception. Cela demande aux rédacteurs de maintenir des métadonnées techniques qu'ils ne voient pas dans la conception normale de la page. Cela fait aussi se comporter différemment deux produits du même content type.

Les global defaults conviennent à une identité qui ne change pas par page, comme l'organisation éditrice. Les bundle defaults conviennent aux properties liées aux champs, comme le nom produit, la SKU et la description. Le même principe s'applique quand vous apprenez aux rédacteurs à travailler en composants plutôt qu'un long champ body - une source faisant autorité, plusieurs sorties.

Comment mapper les champs Drupal vers le JSON-LD Product ?

Supposons que le content type Drupal contienne ces champs :

Source DrupalType de champUsage visible
Node titleCore titletitre produit
field_summaryPlain text, longintroduction
field_skuPlain texttableau de spécifications
field_brandEntity referencedétails produit
field_imageRéférence media ou imageimage produit
field_priceDecimalbloc offre
field_currencyListbloc offre
field_availabilityListstatut stock
Canonical URLURL généréeidentité de page

Le mapping Schema.org doit lire ces mêmes valeurs :

Property Schema.orgSource DrupalToken ou paramètre typique
Product @typeconfiguration fixeProduct
Product @idURL canonique plus fragment[node:url:absolute]#product
Product nametitre du node[node:title]
Product descriptionchamp summary[node:field_summary]
Product urlURL canonique[node:url:absolute]
Product skuchamp SKU[node:field_sku]
Product brand.namenom de marque référencéetoken pour le label de field_brand
Product imagechamp image ou mediatoken d'URL d'image absolue
Offer pricechamp prix decimaltoken pour la valeur brute de field_price
Offer priceCurrencyvaleur de liste devisetoken pour la valeur stockée de field_currency
Offer availabilityvaleur de liste disponibilitéURL de statut Schema.org complète

Les chemins de tokens pour les entités référencées et les media dépendent de la structure des champs et des providers de tokens activés. Utilisez Browse available tokens dans le formulaire Metatag et inspectez le résultat sur une vraie page. Ne copiez pas un token media d'un autre projet en supposant que la chaîne de relation est identique.

Le principe de mapping de base est stable :

  • les noms viennent des champs nom,
  • les identifiants des champs identifiant,
  • les nombres des champs numériques,
  • les statuts contrôlés des valeurs machine stockées,
  • les URLs doivent résoudre vers des URLs publiques absolues,
  • les objets imbriqués comme Offer et Brand gardent leur propre @type.

Le JSON-LD piloté par les champs supporte aussi des modèles éditoriaux comme l'answer-first writing pour la recherche IA, où le texte visible et les métadonnées doivent décrire les mêmes faits.

Configurer les defaults Product

À /admin/config/search/metatag, ajoutez ou modifiez les defaults pour le content type Product. Ouvrez la section Schema.org: Product et définissez :

  • @type sur Product,
  • name sur le token titre du node,
  • description sur le token summary,
  • url sur l'URL absolue du node,
  • sku sur le champ SKU,
  • image sur l'URL publique de l'image,
  • brand comme objet Brand,
  • offers comme objet Offer alimenté par les champs prix.

Le formulaire du module représente les properties complexes comme des inputs imbriqués. Utilisez ces contrôles plutôt que d'assembler une chaîne JSON dans un champ texte.

Enregistrez les defaults, videz les caches et ouvrez une page produit publiée. Le head doit contenir un script JSON-LD avec un objet Product dans son @graph.

Le résultat doit suivre cette forme :

{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@type": "Product",
      "@id": "https://www.example.com/products/aqua-4500#product",
      "name": "Aqua 4500",
      "description": "A submersible pump for continuous industrial use.",
      "url": "https://www.example.com/products/aqua-4500",
      "sku": "AQ-4500",
      "brand": {
        "@type": "Brand",
        "name": "AquaWorks"
      },
      "offers": {
        "@type": "Offer",
        "price": "269.00",
        "priceCurrency": "EUR",
        "availability": "https://schema.org/InStock"
      }
    }
  ]
}

Cette sortie est un exemple, pas un bloc à coller dans Drupal. Votre mapping doit la générer à partir de l'entité produit.

Comment exporter le mapping Schema.org Metatag en config Drupal ?

Une fois la sortie de page correcte, exportez la configuration Drupal :

drush cex -y
git diff -- config/sync

Les bundle defaults sont stockés comme entités de configuration Metatag default. Un mapping Product apparaît normalement dans un fichier nommé :

metatag.metatag_defaults.node__product.yml

La partie simple d'un fichier exporté a cette forme :

id: node__product
label: 'Content: Product'
tags:
  schema_product_type: Product
  schema_product_name: '[node:title]'
  schema_product_description: '[node:field_summary]'
  schema_product_id: '[node:url:absolute]#product'
  schema_product_url: '[node:url:absolute]'
  schema_product_sku: '[node:field_sku]'

Les valeurs complexes comme Offer sont sérialisées par le module et peuvent être plus difficiles à relire en YAML brut. Configurez-les via l'UI, exportez-les et commitez le résultat. N'éditez pas la valeur sérialisée à la main sans tester aussi la page rendue.

L'export de configuration compte, car un mapping est un comportement applicatif. Il doit passer par la revue de code et le déploiement avec le content type et les champs dont il dépend.

Que se passe-t-il quand les champs prix sont vides dans le JSON-LD ?

Les mappings de prix exposent rapidement les problèmes de modèle de contenu.

Le prix doit venir d'un champ decimal plutôt que d'une phrase formatée comme « À partir de 269 € ». La devise doit avoir sa propre valeur contrôlée. La disponibilité stocke une valeur machine qui mappe vers un statut Schema.org valide.

Décidez ce qui se passe quand aucun prix public n'existe. N'émettez pas :

{
  "@type": "Offer",
  "price": "",
  "priceCurrency": "EUR"
}

Une Offer incomplète peut être invalide ou trompeuse. Exigez soit les champs pour les produits qui publient une Offer, soit omettez l'Offer quand l'entreprise ne publie pas de prix.

C'est là qu'un simple mapping par token peut nécessiter un petit module custom. Une implémentation hook_metatags_alter() peut retirer un objet imbriqué quand ses champs source requis sont vides. Gardez la règle proche du modèle de contenu et couvrez-la par un test.

La même règle s'applique aux notes, dates et identifiants. Un token vide n'est pas une donnée structurée utile. Un repli doit avoir un sens métier, pas seulement faire taire un validateur.

Comment garder le JSON-LD multilingue aligné sur chaque page traduite ?

Les tokens se résolvent dans le contexte de l'entité rendue. Sur une URL traduite, le titre et la description traduits doivent alimenter le markup pour cette langue.

Vérifiez cela sur des pages proches de la production. Les entités référencées, les métadonnées media et les tokens custom ne suivent pas toujours la traduction comme les champs principaux du node.

Classifiez les properties avant de les configurer :

  • Traduisibles : nom, description et labels orientés public.
  • Généralement partagées : SKU, GTIN et identifiants techniques.
  • Spécifiques au marché : prix, devise, disponibilité et zone desservie.
  • Site-wide : identité de l'éditeur et profils officiels.

Une page produit en français ne doit pas émettre une description en anglais parce que la traduction française est vide. Décidez si la publication doit être bloquée, si la property doit être omise ou si une langue de repli documentée apparaît aussi visiblement sur la page.

Testez chaque URL de langue séparément. Réussir la validation en anglais ne dit rien sur le prix allemand ou les métadonnées d'image françaises.

Comment valider le JSON-LD sur les pages Drupal rendues ?

Enregistrer un token dans Drupal ne prouve pas que le JSON-LD résultant est correct. Les validateurs n'aident que si le markup sur la page live correspond aux champs que les rédacteurs maintiennent.

Utilisez trois niveaux de validation.

1. Parser la sortie

Ouvrez le code source de la page et trouvez :

<script type="application/ld+json">

Confirmez que le bloc est du JSON valide, que le type attendu existe et qu'un seul module possède chaque entité. Des objets Product en double depuis Schema.org Metatag et un template de thème peuvent diverger sans produire d'erreur de syntaxe.

2. Vérifier le vocabulaire

Utilisez le validateur Schema.org pour inspecter types et properties Schema.org.

Cela détecte l'imbrication mal formée, les properties mal orthographiées et les valeurs invalides. Cela ne prouve pas que Google utilise le type comme rich result. Pour des contrôles SEO au niveau CMS au-delà du markup, voir 10 fonctionnalités SEO qu'un CMS moderne devrait avoir et principales améliorations après un audit SEO Drupal.

3. Vérifier la fonctionnalité Google visée

Utilisez le Rich Results Test de Google pour les types pris en charge par Google Search. Consultez ensuite la documentation spécifique à la fonctionnalité pour les properties requises.

Un markup Schema.org valide et l'éligibilité aux rich results sont des tests différents. Un objet Service valide peut bien décrire la page même si Google ne fournit pas de rich result Service.

Après les contrôles techniques, comparez le résultat au contenu visible. Les validateurs ne peuvent pas décider si EUR 269 dans le markup entre en conflit avec EUR 249 dans le bloc offre. Une IA peut-elle vraiment lire votre site web ? montre pourquoi du HTML récupérable et des faits alignés comptent au-delà des rich results classiques.

Comment tester la couverture Schema.org en CI ?

Une équipe peut configurer correctement chaque content type existant et perdre quand même la couverture six mois plus tard. Quelqu'un ajoute une variante Product ou un bundle Resource sans ajouter de defaults Metatag.

Le contrôle CI le plus simple vérifie que les bundles publics sélectionnés ont le groupe schema attendu dans la configuration exportée.

<?php

declare(strict_types=1);

namespace Drupal\Tests\site_schema\Unit;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Yaml\Yaml;

final class SchemaDefaultsConfigTest extends TestCase {

  public function testPublicBundlesHaveSchemaDefaults(): void {
    $required = [
      'article' => ['schema_article_type', 'Article'],
      'product' => ['schema_product_type', 'Product'],
      'service' => ['schema_service_type', 'Service'],
    ];

    $configDirectory = dirname(DRUPAL_ROOT) . '/config/sync';

    foreach ($required as $bundle => [$tag, $expectedType]) {
      $path = sprintf(
        '%s/metatag.metatag_defaults.node__%s.yml',
        $configDirectory,
        $bundle,
      );

      self::assertFileExists(
        $path,
        sprintf('The %s bundle has no Metatag defaults.', $bundle),
      );

      $config = Yaml::parseFile($path);

      self::assertSame(
        $expectedType,
        $config['tags'][$tag] ?? null,
        sprintf('The %s bundle has no %s mapping.', $bundle, $tag),
      );
    }
  }

}

Adaptez le répertoire de configuration et la liste de bundles au projet. Exécutez le test dans le même job PHPUnit qui vérifie le code Drupal custom.

Ce test détecte l'absence. Il ne détecte pas un token prix incorrect.

Ajoutez un test fonctionnel par template à forte valeur. Créez ou chargez un produit représentatif, demandez son URL publique, décodez le script application/ld+json et vérifiez les valeurs critiques métier :

  • @type égal à Product,
  • name égal au titre du node,
  • sku égal à field_sku,
  • offers.price égal au champ prix brut,
  • offers.priceCurrency égal à la devise stockée,
  • le prix visible égal au prix généré.

Le module Schema.org Metatag utilise la même approche dans ses propres tests fonctionnels : charger une page rendue, trouver le script JSON-LD, le décoder et comparer la sortie. Pourquoi Drupal convient aux opérations de contenu structuré à grande échelle montre comment configuration, champs et gouvernance gardent ces contrôles utiles quand le site grandit.

Comment construire une file d'attente éditoriale pour la revue des données structurées ?

Les bundle defaults doivent couvrir les pages normales. La revue humaine doit cibler les données source manquantes ou exceptionnelles.

Créez une View administrative pour le contenu Product avec des colonnes pour :

  • titre,
  • statut de publication,
  • SKU,
  • prix,
  • devise,
  • disponibilité,
  • image,
  • statut de traduction,
  • date de dernière modification,
  • flag « Schema review required ».

Ajoutez des filtres exposés pour les champs requis vides et le flag de revue. Donnez à la View un nom clair comme Structured data review queue.

Le flag booléen est utile quand un enregistrement ne peut pas suivre le mapping bundle, par exemple un produit avec plusieurs offres indépendantes ou une page représentant une famille de produits plutôt qu'une SKU. Cet enregistrement a besoin d'une décision de modélisation, pas d'une zone de texte JSON-LD manuelle.

Si les rédacteurs peuvent saisir des overrides Metatag au niveau entité, incluez ces enregistrements dans un audit séparé. Les overrides sont des exceptions et doivent rester rares. Quand les specs doivent aussi soutenir la recherche acheteur assistée par IA, recommandation IA pour les fournisseurs : faits pour la shortlist explique pourquoi les valeurs de champs publiées comptent au-delà des extraits de recherche.

Comment intégrer le mapping JSON-LD au workflow du content type ?

Ajouter un content type public change plus que le formulaire d'édition. Utilisez une courte checklist definition of done :

  1. Choisissez le type Schema.org principal de la page.
  2. Identifiez les champs qui fournissent ses properties utiles.
  3. Configurez les bundle defaults avec des tokens.
  4. Exportez et relisez la configuration.
  5. Testez un enregistrement complet et un avec des champs optionnels manquants.
  6. Testez chaque langue publiée.
  7. Ajoutez le bundle au test de couverture de configuration.
  8. Ajoutez les champs source requis à la View de revue éditoriale.
  9. Confirmez que le thème ou un autre module ne génère pas d'entité en double.

Répétez la revue quand un champ change de nom, de type ou de propriétaire. Un mapping peut rester présent tout en pointant vers un token qui ne résout plus rien.

Besoin de mappings JSON-LD alignés sur votre contenu Drupal ?

Nous implémentons la configuration Schema.org Metatag, les mappings champ-vers-token et les contrôles automatisés sur des plateformes Drupal où pages produit, articles et contenu multilingue doivent rester alignés entre texte visible et markup de données structurées. Le même modèle soutient les sites B2B qui publient des specs structurées pour la recherche acheteur et les shortlists assistées par IA.

Si votre site Drupal a besoin de JSON-LD maintenu à partir des champs de contenu plutôt que de blocs écrits à la main, notre équipe peut configurer les bundle defaults, les exporter en code et relier la validation à votre workflow éditorial. Visitez notre page agence Drupal pour voir comment nous construisons et maintenons des plateformes Drupal pour les organisations à fort volume de contenu.