# Le SEO en headless WordPress : le défi que Yoast ne résout pas tout seul

> En headless, Yoast SEO ne peut plus injecter directement ses balises dans le HTML. Voici comment récupérer et exploiter ces données côté frontend.

- Auteur : Clément Hadrot
- Publié le : 2024-01-25
- Mis à jour le : 2024-01-25
- Catégorie : Headless &amp; API
- URL : https://wpmoderne.dev.wordpress-developpement.fr/headless/seo-headless-wordpress-defi-yoast/

## L’essentiel

- yoast_head_json expose les métadonnées SEO via l'API REST
- Le sitemap XML natif doit être adapté ou régénéré côté frontend
- Le balisage Schema.org doit être reconstruit manuellement côté frontend

Sur un WordPress classique, un plugin comme Yoast SEO fonctionne selon un principe simple : il s'accroche aux hooks de rendu du thème et injecte directement les balises meta, le balisage Schema.org et les liens canoniques dans le HTML généré. En architecture headless, ce mécanisme s'effondre purement et simplement : le thème WordPress n'affiche plus rien, tout le rendu se fait côté frontend, sur un domaine et une technologie totalement distincts.

Cela ne signifie pas que le SEO devient impossible en headless, loin de là. Mais cela signifie qu'aucune optimisation n'est plus automatique : chaque élément doit être explicitement récupéré depuis l'API et reconstruit côté frontend. C'est un chantier réel, souvent sous-estimé dans les plannings de projets headless.

## Récupérer les métadonnées Yoast via l'API REST

Depuis la version 14.2, Yoast SEO expose un champ `yoast_head_json` directement dans les réponses de l'API REST, à condition d'ajouter `_fields=yoast_head_json` ou de le récupérer avec l'ensemble de la réponse. Ce champ contient un objet structuré avec l'ensemble des métadonnées configurées dans l'interface Yoast : titre SEO, méta description, balises Open Graph, Twitter Card, et le balisage Schema.org généré.

```
fetch(
  'https://exemple.fr/wp-json/wp/v2/posts?slug=mon-article&_fields=yoast_head_json'
)
  .then( ( r ) => r.json() )
  .then( ( [ article ] ) => {
    console.log( article.yoast_head_json.title );
    console.log( article.yoast_head_json.description );
    console.log( article.yoast_head_json.schema );
  } );
```

Ce champ simplifie grandement le travail : plutôt que de reconstruire une logique de titre et de description à partir de zéro côté frontend, on récupère directement ce que l'équipe éditoriale a configuré dans Yoast, article par article.

## Injecter ces données dans generateMetadata

Sur un frontend Next.js App Router, l'intégration se fait naturellement dans la fonction `generateMetadata` :

```
export async function generateMetadata( { params } ) {
  const reponse = await fetch(
    `https://exemple.fr/wp-json/wp/v2/posts?slug=${params.slug}&_fields=yoast_head_json`
  );
  const [ article ] = await reponse.json();
  const yoast = article.yoast_head_json;

  return {
    title: yoast.title,
    description: yoast.description,
    openGraph: {
      title: yoast.og_title,
      description: yoast.og_description,
      images: yoast.og_image?.map( ( img ) => img.url ),
    },
  };
}
```

> L'essentiel à retenir : yoast_head_json expose les métadonnées SEO via l'API REST ; Le sitemap XML natif doit être adapté ou régénéré côté frontend ; Le balisage Schema.org doit être reconstruit manuellement côté frontend

## Le sitemap XML : natif, mais pas suffisant en headless

WordPress génère nativement un sitemap XML depuis la version 5.5, accessible à `/wp-sitemap.xml`. Problème : ce sitemap référence les URL du domaine WordPress lui-même, pas celles du frontend headless où le contenu est réellement consulté. Deux approches sont possibles :

- Régénérer un sitemap côté frontend, en récupérant la liste des articles via l'API et en construisant les URL avec le domaine du frontend
- Adapter le sitemap natif de WordPress avec un filtre pour qu'il pointe vers les bonnes URL, une solution plus fragile si la structure du frontend évolue

Dans la majorité des projets que nous accompagnons, la première approche l'emporte : un endpoint ou une route dédiée côté frontend, alimentée par l'API REST, garde le contrôle total sur la structure finale des URL exposées aux moteurs de recherche.

## Reconstruire le balisage Schema.org

Le champ `schema` présent dans `yoast_head_json` contient déjà un graphe JSON-LD structuré, prêt à être injecté tel quel dans une balise `script` de type `application/ld+json` côté frontend :

```
<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{ __html: JSON.stringify( yoast.schema ) }}
/>
```

C'est un des rares cas où le travail de reconstruction est minime : Yoast fait l'essentiel du travail de structuration, il ne reste plus qu'à transporter la donnée jusqu'au HTML final.

## Les redirections, un point souvent oublié

Les redirections configurées dans Yoast (module Redirections) s'appliquent au niveau du thème WordPress classique, pas au frontend headless. Sans traitement spécifique, une redirection créée dans Yoast n'a strictement aucun effet sur le site réellement visité. Il faut soit exposer ces redirections via un endpoint personnalisé consommé au build ou en edge middleware côté frontend, soit gérer les redirections directement dans la configuration du frontend (fichier `next.config.js` pour Next.js), en perdant alors l'interface de gestion familière aux équipes éditoriales.

> Le SEO headless n'est pas plus mauvais qu'un SEO WordPress classique, mais il est structurellement plus manuel. Chaque brique automatique du thème classique doit être rebâtie explicitement côté frontend, et ce travail doit être budgété dès le départ, pas ajouté en urgence après un audit SEO décevant.

## En résumé

Le SEO en headless WordPress reste tout à fait maîtrisable, à condition d'accepter qu'aucune brique n'est plus automatique. Le champ `yoast_head_json` de l'API REST couvre l'essentiel des métadonnées et du balisage Schema.org, mais le sitemap et les redirections demandent un travail de reconstruction explicite côté frontend. Anticiper ce chantier dès le cahier des charges évite les mauvaises surprises lors du premier audit de référencement post-lancement.
