2026年5月20日

2026年5月20日

WordPressのページネーションのSEO設定方法

はじめに

WordPressのアーカイブページや長い記事のページネーションは、SEO上の設定を誤ると評価が分散したり、重複コンテンツとみなされたりします。Googleが2011年に導入したrel="prev/next"は2019年に廃止されましたが、その後の正しい対応方法を理解することが重要です。

症状・原因

  • ページネーションのページ2以降がインデックスされすぎている(または全くされない)
  • /page/2/などのURLがカノニカル問題を起こしている
  • 無限スクロールを実装したがGoogleにコンテンツが認識されていない
  • ページネーションページの直帰率が高くパフォーマンスが悪い

解決手順

ステップ1:ページネーションのSEO現状を確認する

# ページネーションURLのインデックス状況を確認
# Googleで: site:example.com/page/

# ページネーションのカノニカルを確認
curl -s https://example.com/page/2/ | grep -i canonical

# robots.txt でページネーションがブロックされていないか
curl -s https://example.com/robots.txt | grep -i page

# WordPressのページネーション設定を確認
wp option get posts_per_page      # 1ページの投稿数
wp option get page_on_front       # フロントページ設定
wp option get page_for_posts      # 投稿一覧ページ

ステップ2:ページネーションのカノニカルURLを正しく設定する

// functions.php: ページネーションのカノニカルURL設定
// WordPress はデフォルトで各ページのカノニカルを自動設定する
// wp_head() を呼んでいれば基本的に正しく設定されている

// カノニカルの出力を確認(remove_action でプラグインの干渉を確認)
add_action('wp_head', function(): void {
    if (is_paged()) {
        // ページネーション時のカノニカルを手動で出力する場合
        $page    = get_query_var('paged') ?: 1;
        $base    = get_pagenum_link(1);
        $current = get_pagenum_link($page);

        // ページ1はベースURLをカノニカルに
        $canonical = ($page === 1) ? $base : $current;
        // ※ Yoast SEO などプラグインが出力する場合は重複するため削除する
    }
}, 1);

// Yoast SEO のカノニカル出力をカスタマイズ
add_filter('wpseo_canonical', function(string $canonical): string {
    if (is_paged()) {
        // ページネーションページはそのままのURLをカノニカルに(デフォルト動作)
        // page/1/ を / にリダイレクトする場合は自動的に処理される
    }
    return $canonical;
});

ステップ3:ページネーションページのnoindex設定を判断する

// functions.php: ページネーションのnoindex設定
// ※ SEO的にはページネーションをインデックスするのが基本
//   独自コンテンツのないページ2以降は状況次第

add_action('wp_head', function(): void {
    // アーカイブのページ2以降をnoindexにする場合
    // (コンテンツが薄い・独自性がない場合のみ推奨)
    if (is_paged() && (is_category() || is_tag() || is_archive())) {
        $page = get_query_var('paged');
        if ($page > 1) {
            // Yoast SEO を使っていない場合のみ出力
            if (!defined('WPSEO_VERSION')) {
                echo '<meta name="robots" content="noindex, follow">' . PHP_EOL;
            }
        }
    }

    // 記事内ページネーション(<!--nextpage-->)は基本インデックスOK
    // → 各ページに固有コンテンツがあるため
}, 1);

// Yoast SEO での設定:
// SEO → 検索の見え方 → アーカイブ → ページネーション → ページ設定
// 「最初のページ以外はインデックスしない」 をONにする方法もある

ステップ4:rel=”prev/next”の代替対応を実装する

// Googleは2019年に rel="prev/next" のサポートを廃止
// 代わりに:
// 1. 正しいカノニカルURL(各ページ固有のURL)
// 2. ページネーション付きのHTMLリンク
// 3. サイトマップへの全ページ記載

// functions.php: ページネーションリンクをSEOフレンドリーに

// WordPress デフォルトのページネーション出力を改善
add_filter('wp_link_pages_args', function(array $args): array {
    $args['before']    = '<nav class="page-links" aria-label="記事ページナビゲーション">';
    $args['after']     = '</nav>';
    $args['link_before'] = '<span>';
    $args['link_after']  = '</span>';
    return $args;
});

// アーカイブページのページネーション
// the_posts_pagination() の出力をカスタマイズ
add_filter('navigation_markup_template', function(string $template): string {
    // aria-label を追加してアクセシビリティ改善
    return str_replace(
        'class="navigation',
        'aria-label="ページナビゲーション" class="navigation',
        $template
    );
});

// サイトマップにページネーションを含める場合
add_filter('wp_sitemaps_posts_query_args', function(array $args): array {
    // ページネーションページはサイトマップには含めない(通常)
    return $args;
});

ステップ5:無限スクロールのSEO対応

// 無限スクロール実装時のSEO対応
// History API でURLを更新することでGoogleに各ページを認識させる

class InfiniteScroll {
    constructor() {
        this.page = 1;
        this.loading = false;
        this.maxPage = parseInt(document.body.dataset.maxPage || '1');
        this.observer = new IntersectionObserver(this.onIntersect.bind(this));

        const sentinel = document.querySelector('.load-more-sentinel');
        if (sentinel) this.observer.observe(sentinel);
    }

    async onIntersect(entries) {
        if (!entries[0].isIntersecting || this.loading) return;
        if (this.page >= this.maxPage) return;

        this.loading = true;
        this.page++;

        try {
            const url = `${window.location.pathname}page/${this.page}/`;
            const res = await fetch(url);
            const html = await res.text();

            // 新しいコンテンツを挿入
            const parser = new DOMParser();
            const doc = parser.parseFromString(html, 'text/html');
            const posts = doc.querySelectorAll('.post');
            const container = document.querySelector('.posts-container');

            posts.forEach(post => container.appendChild(post));

            // URLをHistoryAPIで更新(SEO・UX両立)
            history.pushState({ page: this.page }, '', url);

        } finally {
            this.loading = false;
        }
    }
}

new InfiniteScroll();
// functions.php: 最大ページ数をbodyに出力(JS用)
add_filter('body_class', function(array $classes): array {
    return $classes;
});

add_action('wp_head', function(): void {
    global $wp_query;
    $max_pages = $wp_query->max_num_pages ?? 1;
    echo '<script>document.body.dataset.maxPage = ' . (int)$max_pages . ';</script>' . PHP_EOL;
});

注意事項

  • rel="prev/next"は2019年にGoogleがサポートを廃止しました。出力しても無害ですが、SEO効果はありません
  • ページネーションを全てnoindexにすると、後半ページの記事がインデックスされなくなります。コンテンツへの導線として一部のページはインデックスさせておくことを推奨します
  • 無限スクロールはJavaScript無効環境やGooglebotが正しくレンダリングできない場合があります。

まとめ

ページネーションのSEO対応は①wp_head()が出力するカノニカルURLが各ページ固有のURLになっていることを確認、②コンテンツが薄いアーカイブの2ページ目以降は任意でnoindex設定、③rel="prev/next"は廃止済みのため不要、④無限スクロールはHistory APIでURLを更新してGoogleに各ページを認識させる、⑤サイトマップにはページネーションページを含めない、の順で設定します。

お気軽にご相談ください

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