2026年7月24日

2026年7月24日

WordPressにパンくずリストを実装する方法

はじめに

「ユーザーが今サイトのどこにいるか分かりやすくしたい」「Googleの検索結果にパンくずを表示させてCTRを上げたい」——パンくずリストはUXとSEOの両方を改善する重要なナビゲーション要素です。

症状・原因

WordPressにはパンくずリストの標準機能がないため、プラグインまたはカスタムコードで実装が必要です。さらに構造化データ(JSON-LD)を追加することでGoogle検索結果にリッチリザルトとして表示されます。

解決手順

ステップ1:Yoast SEOのパンくずリスト機能を使う

// Yoast SEOのパンくずリスト有効化
// Yoast SEO → 設定 → 高度な設定 → パンくずリスト → 有効化

// テンプレートに出力(header.phpやsingle.phpなどに追加)
<?php if ( function_exists( 'yoast_breadcrumb' ) ) {
    yoast_breadcrumb(
        '<nav class="breadcrumb" aria-label="パンくずリスト">',
        '</nav>'
    );
} ?>
【Yoast SEOパンくずリストの設定】

Yoast SEO → 設定 → 高度な設定 → パンくずリスト:

区切り文字:        › (または / や »)
ホームのアンカー:   ホーム
ブログのアンカー:   ブログ
最後のパンくずに現在のページを表示: ✅
パンくずリストの各ページにタグを表示: ☐

ステップ2:プラグインなしで手動実装する

// functions.php: カスタムパンくずリスト関数
function my_breadcrumb() {
    $separator   = ' <span class="breadcrumb-sep" aria-hidden="true">›</span> ';
    $home_url    = home_url( '/' );
    $home_text   = 'ホーム';
    $breadcrumbs = [];

    // ホーム
    $breadcrumbs[] = '<a href="' . esc_url( $home_url ) . '">' . esc_html( $home_text ) . '</a>';

    if ( is_singular() ) {
        $post_type = get_post_type();

        // カスタム投稿タイプのアーカイブリンク
        if ( 'post' !== $post_type && 'page' !== $post_type ) {
            $pt_obj = get_post_type_object( $post_type );
            if ( $pt_obj && $pt_obj->has_archive ) {
                $breadcrumbs[] = '<a href="' . esc_url( get_post_type_archive_link( $post_type ) ) . '">'
                               . esc_html( $pt_obj->labels->name ) . '</a>';
            }
        }

        // 投稿の場合はカテゴリーを表示
        if ( 'post' === $post_type ) {
            $categories = get_the_category();
            if ( $categories ) {
                $cat = $categories[0];
                // 親カテゴリーがある場合は親→子の順で表示
                $ancestors = get_ancestors( $cat->term_id, 'category' );
                foreach ( array_reverse( $ancestors ) as $ancestor_id ) {
                    $ancestor = get_category( $ancestor_id );
                    $breadcrumbs[] = '<a href="' . esc_url( get_category_link( $ancestor_id ) ) . '">'
                                   . esc_html( $ancestor->name ) . '</a>';
                }
                $breadcrumbs[] = '<a href="' . esc_url( get_category_link( $cat->term_id ) ) . '">'
                               . esc_html( $cat->name ) . '</a>';
            }
        }

        // 固定ページの場合は親ページを表示
        if ( 'page' === $post_type ) {
            $ancestors = get_post_ancestors( get_the_ID() );
            foreach ( array_reverse( $ancestors ) as $ancestor_id ) {
                $breadcrumbs[] = '<a href="' . esc_url( get_permalink( $ancestor_id ) ) . '">'
                               . esc_html( get_the_title( $ancestor_id ) ) . '</a>';
            }
        }

        // 現在のページ(リンクなし)
        $breadcrumbs[] = '<span class="breadcrumb-current" aria-current="page">'
                       . esc_html( get_the_title() ) . '</span>';

    } elseif ( is_category() || is_tag() || is_tax() ) {
        $term = get_queried_object();
        if ( $term->parent ) {
            $parent = get_term( $term->parent, $term->taxonomy );
            $breadcrumbs[] = '<a href="' . esc_url( get_term_link( $parent ) ) . '">'
                           . esc_html( $parent->name ) . '</a>';
        }
        $breadcrumbs[] = '<span class="breadcrumb-current" aria-current="page">'
                       . esc_html( $term->name ) . '</span>';

    } elseif ( is_archive() ) {
        if ( is_post_type_archive() ) {
            $breadcrumbs[] = '<span class="breadcrumb-current" aria-current="page">'
                           . esc_html( post_type_archive_title( '', false ) ) . '</span>';
        } elseif ( is_date() ) {
            $breadcrumbs[] = '<span class="breadcrumb-current" aria-current="page">'
                           . esc_html( get_the_date( 'Y年n月' ) ) . '</span>';
        }

    } elseif ( is_search() ) {
        $breadcrumbs[] = '<span class="breadcrumb-current" aria-current="page">'
                       . '「' . esc_html( get_search_query() ) . '」の検索結果</span>';
    }

    echo '<nav class="breadcrumb" aria-label="パンくずリスト">';
    echo '<ol class="breadcrumb-list">';
    foreach ( $breadcrumbs as $i => $crumb ) {
        $is_last = ( $i === count( $breadcrumbs ) - 1 );
        echo '<li class="breadcrumb-item' . ( $is_last ? ' current' : '' ) . '">';
        echo $crumb;
        if ( ! $is_last ) {
            echo $separator;
        }
        echo '</li>';
    }
    echo '</ol>';
    echo '</nav>';
}

ステップ3:CSSでパンくずリストをデザインする

/* パンくずリストのスタイル */
.breadcrumb {
    margin: 1rem 0;
    font-size: 0.875rem;
    color: #50575e;
}

.breadcrumb-list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    list-style: none;
    margin: 0;
    padding: 0;
    gap: 0;
}

.breadcrumb-item {
    display: flex;
    align-items: center;
}

.breadcrumb-item a {
    color: #2271b1;
    text-decoration: none;
}

.breadcrumb-item a:hover {
    text-decoration: underline;
}

.breadcrumb-sep {
    margin: 0 0.4rem;
    color: #a7aaad;
    font-size: 0.8rem;
}

.breadcrumb-current {
    color: #50575e;
    /* 長いタイトルを省略 */
    max-width: 200px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* モバイルでは現在地のみ表示するオプション */
@media (max-width: 600px) {
    .breadcrumb-item:not(.current):not(:nth-last-child(2)) {
        /* 中間のパンくずを省略 */
    }
}

ステップ4:JSON-LD構造化データを追加する

// functions.php: BreadcrumbList構造化データをJSON-LDで出力
add_action( 'wp_head', function() {
    if ( ! is_singular() && ! is_category() && ! is_tax() && ! is_archive() ) return;

    $items     = [];
    $position  = 1;

    // ホーム
    $items[] = [
        '@type'    => 'ListItem',
        'position' => $position++,
        'name'     => 'ホーム',
        'item'     => home_url( '/' ),
    ];

    if ( is_singular( 'post' ) ) {
        $cats = get_the_category();
        if ( $cats ) {
            $items[] = [
                '@type'    => 'ListItem',
                'position' => $position++,
                'name'     => $cats[0]->name,
                'item'     => get_category_link( $cats[0]->term_id ),
            ];
        }
        $items[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => get_the_title(),
            'item'     => get_permalink(),
        ];
    } elseif ( is_category() ) {
        $cat = get_queried_object();
        $items[] = [
            '@type'    => 'ListItem',
            'position' => $position++,
            'name'     => $cat->name,
            'item'     => get_category_link( $cat->term_id ),
        ];
    }

    if ( count( $items ) <= 1 ) return;

    $schema = [
        '@context'        => 'https://schema.org',
        '@type'           => 'BreadcrumbList',
        'itemListElement' => $items,
    ];

    echo '<script type="application/ld+json">'
       . wp_json_encode( $schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES )
       . '</script>' . "\n";
} );

ステップ5:テンプレートに組み込む

<?php
// single.php または header.php: パンくずリストを表示

// Yoast SEOを使う場合
if ( function_exists( 'yoast_breadcrumb' ) ) {
    yoast_breadcrumb( '<nav class="breadcrumb" aria-label="パンくずリスト">', '</nav>' );
}

// カスタム関数を使う場合
if ( function_exists( 'my_breadcrumb' ) && ! is_front_page() ) {
    my_breadcrumb();
}

// Breadcrumb NavXTプラグインを使う場合
if ( function_exists( 'bcn_display' ) ) {
    bcn_display();
}
?>

注意事項

  • パンくずリストの構造化データは、Yoast SEOやRankMathが自動で出力します。手動で追加する場合は重複しないよう注意してください。
  • aria-labelaria-current="page"を設定することでスクリーンリーダーのユーザーにも正確な情報を伝えられます。アクセシビリティ対応は必ず行ってください。
  • カテゴリーに親子関係がある場合、パンくずにすべての祖先カテゴリーを表示するとリンクが長くなります。get_ancestors()で祖先を取得して適切に表示してください。

まとめ

パンくずリストの実装は「Yoast SEO/RankMathで有効化して関数を呼び出す→プラグインなしの場合はカスタム関数で現在地・カテゴリー・親ページを構築→CSSでデザイン→JSON-LDでBreadcrumbList構造化データを出力→Googleリッチリザルトテストで確認」の流れで整備します。関連記事:WordPressにXMLサイトマップを設定してSEOを改善する方法WordPressのページネーションをカスタマイズする方法

お気軽にご相談ください

お見積りへ お問い合わせへ