Sur un site associatif que je maintiens depuis plusieurs années, l’extension SEO en place générait correctement le balisage Article pour les billets de blog, mais ne proposait rien pour les événements ponctuels que l’association organisait. Plutôt que de chercher une deuxième extension spécialisée pour une poignée de pages par an, quelques lignes de PHP accrochées à wp_head ont réglé le problème en une après-midi.
Cette situation revient souvent : les extensions SEO généralistes couvrent très bien les cas fréquents (article, produit e-commerce basique, organisation), mais laissent de côté des types de contenu Schema.org plus spécifiques, propres à un secteur d’activité. Savoir injecter soi-même du JSON-LD reste alors un outil précieux, à condition de le faire proprement.
Pourquoi JSON-LD plutôt que microdonnées
Schema.org peut se coder de plusieurs façons : microdonnées intégrées directement dans les attributs HTML, RDFa, ou JSON-LD, un bloc de script séparé du balisage visuel. Google recommande explicitement JSON-LD depuis plusieurs années, notamment parce qu’il découple totalement les données structurées de l’affichage : on peut modifier le gabarit HTML sans casser le balisage, et inversement.
Techniquement, un bloc JSON-LD est un simple <script> avec un type MIME particulier, contenant un objet JSON respectant le vocabulaire Schema.org :
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Event",
"name": "Assemblée générale annuelle",
"startDate": "2021-09-18T18:00"
}
</script>
Construire le tableau en PHP plutôt que la chaîne

La tentation la plus courante, et la plus risquée, consiste à construire cette chaîne JSON directement avec des concaténations de chaînes PHP. C’est une source fréquente d’erreurs de syntaxe difficiles à repérer (guillemets non échappés, virgules en trop) et de failles de sécurité si une donnée utilisateur n’est pas correctement échappée. La bonne pratique consiste à construire un tableau PHP classique, puis à laisser wp_json_encode() s’occuper de l’encodage :
add_action( 'wp_head', function() {
if ( ! is_singular( 'evenement' ) ) {
return;
}
$donnees = array(
'@context' => 'https://schema.org',
'@type' => 'Event',
'name' => get_the_title(),
'startDate' => get_post_meta( get_the_ID(), 'date_debut', true ),
'location' => array(
'@type' => 'Place',
'name' => get_post_meta( get_the_ID(), 'lieu', true ),
),
);
printf(
'<script type="application/ld+json">%s</script>' . "\n",
wp_json_encode( $donnees, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE )
);
} );
wp_json_encode() est le wrapper WordPress autour de json_encode(), préféré car il applique automatiquement certains filtres et corrections d’encodage propres à WordPress. Les options JSON_UNESCAPED_SLASHES et JSON_UNESCAPED_UNICODE évitent d’obtenir un JSON truffé de \/ et de caractères Unicode échappés, ce qui reste parfaitement valide mais nettement moins lisible en cas de débogage.
Éviter les doublons avec l’extension SEO déjà en place
Si une extension SEO génère déjà un balisage Article ou Organization, il ne faut surtout pas dupliquer ce même type dans du code maison : deux blocs JSON-LD déclarant le même @type pour la même entité créent une ambiguïté que certains outils de validation signalent, et que les moteurs de recherche peuvent traiter de façon imprévisible. La bonne pratique consiste à limiter le code maison aux types que l’extension ne couvre pas du tout.
Une vérification rapide dans le code source de la page, en cherchant application/ld+json, permet de lister tous les blocs déjà présents avant d’en ajouter un nouveau.
Valider systématiquement
- Copier le contenu du bloc
scriptdans l’outil de test des résultats enrichis de Google. - Vérifier qu’aucune propriété requise du type Schema.org utilisé n’est manquante.
- Contrôler que les valeurs dynamiques (dates, prix, noms) sont bien échappées et ne cassent jamais la structure JSON, y compris quand elles contiennent des guillemets ou des apostrophes.
Un test simple mais souvent négligé consiste à renseigner volontairement une valeur contenant un guillemet double dans le champ concerné (un nom d’événement avec un titre entre guillemets, par exemple) pour vérifier que wp_json_encode() l’échappe correctement sans casser le script.
Le JSON-LD écrit à la main n’a de sens que pour les cas que l’extension SEO ne couvre pas. Dès qu’on commence à dupliquer ce qu’elle fait déjà, on ajoute de la complexité pour un bénéfice nul, voire négatif.
En résumé
Injecter du JSON-LD sur mesure via wp_head est une solution légère et fiable pour des types de contenu Schema.org que les extensions SEO généralistes ne couvrent pas. La clé technique tient en une phrase : construire un tableau PHP, jamais une chaîne concaténée à la main, et laisser wp_json_encode() gérer l’encodage et l’échappement. Une validation systématique avec l’outil de test officiel reste indispensable avant toute mise en production, quel que soit le niveau de confiance dans le code écrit.