# Un fil d’Ariane sans extension, avec balisage Schema.org

> Un fil d'Ariane fait maison, qui gère pages, catégories, CPT et archives, et parle aux moteurs de recherche grâce à des données structurées BreadcrumbList.

- Auteur : Clément Hadrot
- Publié le : 2021-12-09
- Mis à jour le : 2021-12-09
- Catégorie : Tips
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tips/fil-ariane-schema-org/

## L’essentiel

- Une fonction unique gère pages, articles, CPT et archives
- Le JSON-LD BreadcrumbList aide à l'affichage enrichi
- Aucune extension SEO n'est nécessaire pour ce résultat

Beaucoup de sites installent une extension SEO complète pour la seule fonctionnalité de fil d'Ariane, alors qu'un fil d'Ariane maison, correctement architecturé, tient dans une centaine de lignes et couvre sans difficulté les pages, les articles, les catégories et les types de contenu personnalisés. L'avantage principal : un contrôle total sur la logique de hiérarchie, sans dépendre des réglages globaux d'une extension tierce.

Cet article ne traite pas des extensions SEO existantes, mais construit un fil d'Ariane complet à partir de zéro, terminé par des données structurées BreadcrumbList au format JSON-LD, format recommandé pour ce type de balisage.

## Structure générale de la fonction

La fonction principale distingue le contexte de la page en cours (page, article, archive de catégorie, archive de CPT) et construit un tableau associatif de segments, chacun avec un libellé et une URL, avant de le transformer en HTML.

```
function boutique_fil_ariane() {
    $segments = array(
        array( 'libelle' => 'Accueil', 'url' => home_url( '/' ) ),
    );

    if ( is_singular( 'post' ) ) {
        $categories = get_the_category();
        if ( ! empty( $categories ) ) {
            $segments[] = array(
                'libelle' => $categories[0]->name,
                'url'     => get_category_link( $categories[0] ),
            );
        }
        $segments[] = array( 'libelle' => get_the_title(), 'url' => '' );
    } elseif ( is_page() ) {
        $ancetres = array_reverse( get_post_ancestors( get_the_ID() ) );
        foreach ( $ancetres as $ancetre_id ) {
            $segments[] = array(
                'libelle' => get_the_title( $ancetre_id ),
                'url'     => get_permalink( $ancetre_id ),
            );
        }
        $segments[] = array( 'libelle' => get_the_title(), 'url' => '' );
    } elseif ( is_category() ) {
        $segments[] = array( 'libelle' => single_cat_title( '', false ), 'url' => '' );
    } elseif ( is_post_type_archive() ) {
        $segments[] = array( 'libelle' => post_type_archive_title( '', false ), 'url' => '' );
    }

    return $segments;
}
```

Sur les pages, `get_post_ancestors()` reconstruit toute la hiérarchie de pages parentes, dans l'ordre inversé pour partir de la racine. Sur les articles, seule la première catégorie assignée est retenue pour éviter un fil d'Ariane à embranchements multiples, qui perdrait vite sa lisibilité.

## Générer le HTML visible

> L'essentiel à retenir : Une fonction unique gère pages, articles, CPT et archives ; Le JSON-LD BreadcrumbList aide à l'affichage enrichi ; Aucune extension SEO n'est nécessaire pour ce résultat

```
function boutique_afficher_fil_ariane() {
    $segments = boutique_fil_ariane();
    echo '<nav aria-label="Fil d\'Ariane"><ol>';
    foreach ( $segments as $segment ) {
        echo '<li>';
        if ( $segment['url'] ) {
            echo '<a href="' . esc_url( $segment['url'] ) . '">' . esc_html( $segment['libelle'] ) . '</a>';
        } else {
            echo '<span aria-current="page">' . esc_html( $segment['libelle'] ) . '</span>';
        }
        echo '</li>';
    }
    echo '</ol></nav>';
}
```

L'attribut `aria-current="page"` sur le dernier segment, sans lien, respecte les recommandations d'accessibilité : il indique clairement au lecteur d'écran que ce segment correspond à la page actuellement affichée.

## Ajouter le balisage BreadcrumbList

Au-delà de l'affichage visuel, les moteurs de recherche comprennent un fil d'Ariane balisé en données structurées au format `BreadcrumbList` de Schema.org, ce qui peut se traduire par un affichage enrichi dans les résultats de recherche.

```
function boutique_donnees_structurees_fil_ariane() {
    $segments = boutique_fil_ariane();
    $items = array();

    foreach ( $segments as $position => $segment ) {
        $item = array(
            '@type'    => 'ListItem',
            'position' => $position + 1,
            'name'     => $segment['libelle'],
        );
        if ( $segment['url'] ) {
            $item['item'] = $segment['url'];
        }
        $items[] = $item;
    }

    $donnees = array(
        '@context'        => 'https://schema.org',
        '@type'            => 'BreadcrumbList',
        'itemListElement' => $items,
    );

    echo '<script type="application/ld+json">' . wp_json_encode( $donnees ) . '</script>';
}
add_action( 'wp_head', 'boutique_donnees_structurees_fil_ariane' );
```

## Cas particuliers à couvrir

- Pagination d'une archive : ajouter un segment « Page N » sans lien lorsque `get_query_var( 'paged' )` est supérieur à 1.
- Résultats de recherche : afficher « Résultats pour "…" » en dernier segment, avec `get_search_query()`.
- Page 404 : afficher simplement « Page introuvable » sans lien, en dernier segment.

> Je documente toujours cette fonction dans un fichier séparé, `inc/fil-ariane.php` : c'est l'un des rares morceaux de code qui survit intact d'un projet à l'autre, avec juste le nom des taxonomies à adapter.

## En résumé

Un fil d'Ariane maison, bâti sur une fonction unique qui distingue les contextes de page, couvre sans difficulté pages, articles, catégories et types de contenu personnalisés. Le balisage `BreadcrumbList` en JSON-LD complète l'affichage visuel pour offrir aux moteurs de recherche une lecture structurée de la hiérarchie du site, sans dépendre d'une extension SEO complète.
