ページネーションのSEO (rel=”canonical”/”next”/”prev”)

ブログ記事や商品などの一覧を複数のページに分けてページネーション(ページ送り)を設置することがありますが、この場合にrel=”canonical”/”next”/”prev”をマークアップすることで閲覧ユーザーに加えて検索エンジンにも「続きものページ」であることを伝えることができます。今回はWordpressで構築したサイトにSEO関連プラグインを使用せずに実装する一手間について。
ページネーションの例
まずは設定完了後の内容です。下記のようにタイトルとディスクリプション、前後のページURLをheadタグ内にマークアップされるように設定します。現在表示しているページは「rel=”canonical”」を、前のページがある場合は「rel=”prev”」、後のページは「rel=”next”」をlinkタグに付けます。canonicalのURLを先頭ページに設定する方法がありますが、rel=”next”/”prev”をマークアップする場合はページ同士の関係性を検索エンジンに正確に伝えられないので素直に現在表示しているページのURLを設定します。

例)ブログ一覧の2ページ目

<title>(ページ名)2ページ目 | samplesite.com</title>
<meta name="description" content="(ページ名)2ページ目です。一覧の説明。">
...
<link rel="canonical" href="http://www.studiobusstop.com/blog/page/2/">
<link rel="prev" href="http://www.studiobusstop.com/busstop/blog/">
<link rel="next" href="http://www.studiobusstop.com/busstop/blog/page/3/">

設定の準備

今回は固定ページにサブループを設置し、テンプレートに直接コードを記述する方法です。function.phpに記述するのは記事後半のWordpressのデフォルト関数「remove_action」を使ったコードのみです。

使用するグローバル変数

$page(整数)

「固定ページ」「投稿ページ」の現在のページ番号を格納

$paged(整数)

「カテゴリーページ」「タグページ」の現在のページ番号を格納

$wp_query

メインループ(URLリクエストに応じて変化)のデータ一式を格納

独自に作成する変数

$my_query

サブループの記事データを格納

$max_num_pages

ループの総ページ数を格納

$canonical_url

現在のページURLを格納

$nextpage

次のページ番号を格納

使用するプロパティ

$wp_query->max_num_pages

メインループの総ページ数

$my_query->max_num_pages

サブループの総ページ数、$my_queryは独自変数。

サブループ(WP_Query)の設定

固定ページにサブループを表示する場合、下記のように記述しているものとします。

A.$pagedと$my_queryにデータを代入 / 例)サブループの投稿タイプが「post」の場合

<?php
    $paged = get_query_var('paged') ? get_query_var('paged') : 1;
    $args = array(
        'post_type' => array('post'),
        'paged' => $paged,
        'posts_per_page' => 12, /* 表示するページ数 */
        'order' => 'DESC' /* 並び順 */
    );
    $my_query = new WP_Query($args);
?>

総ページ数と次のページ、ページ初期値の設定

ループのデータを取得後、独自変数に代入します。$pagedへの代入は前述のサブループ設定で済ませているのでメインループのみとします。メインループの場合は$pagedの初期値が0なため、1ページ目用に「1」を代入するのが慣例なようです。個別記事分割の対応はこの場合、除きます。

B.$max_num_pagesと$nextpage、$pagedに数値を代入

<?php if(!is_single()) { ?>
<?php
    if ( !$max_num_pages )
        if( $my_query ){
            $max_num_pages = $my_query->max_num_pages;
        }else{
            $max_num_pages = $wp_query->max_num_pages;
        }
    if ( !$paged )
        if( !$my_query ){
            $paged = 1;
        }
        $nextpage = intval($paged) + 1;
?>
<?php } ?>

タイトルとディスクリプションを表示するコード

2ページ目以降のタイトルとディスクリプションに「○ページ目」であることも追記して内容の重複を防ぎます。

C.タイトルとディスクリプションを表示

<?php $page_num = $paged > 1 ? $paged."ページ目" : ""; ?>
<title><?php wp_title(); ?><?php echo $page_num; ?> | <?php bloginfo('name'); ?></title>
<meta name="description" content="<?php wp_title(); ?><?php echo $page_num; ?>です。一覧の説明。">

ちなみに、archive.phpをカテゴリ表示と併用する場合はcategory_description()を使って、下記のように記述できます。

// カスタム投稿ラベル名取得
<?php $post_type_label = esc_html(get_post_type_object(get_post_type())->label ); ?>
// タクソノミーターム情報取得
<?php
    $terms = get_the_terms($post->ID, 'タクソノミースラッグ');
    foreach($terms as $term1) :
        $term_name = $term1->name;
    endforeach;
?>
<title><?php if (is_tax("タクソノミースラッグ")){ echo $term_name." | "; } ?><?php echo $post_type_label; ?><?php echo $page_num; ?> | <?php bloginfo('name'); ?></title>
<meta name="description" content="<?php echo $post_type_label; ?><?php if (is_tax("タクソノミースラッグ")){ echo "[".$term_name."]"; } ?><?php echo $page_num; ?>です。<?php if ("" != category_description()) : ?><?php echo trim(strip_tags(category_description())); ?><?php else: ?>アーカイブ表示用のテキスト<?php endif; ?>”>

展開後

// アーカイブ一覧1ページ目表示時
<title>カスタム投稿ラベル名 | samplesite.com</title>
<meta name="description" content="カスタム投稿ラベル名です。アーカイブ表示用のテキスト”>
// アーカイブ一覧2ページ目表示時
<title>カスタム投稿ラベル名2ページ目 | samplesite.com</title>
<meta name="description" content="カスタム投稿ラベル名2ページ目です。アーカイブ表示用のテキスト”>
// カテゴリ一覧1ページ目表示時
<title>タクソノミーターム名 | カスタム投稿ラベル名 | samplesite.com</title>
<meta name="description" content="カスタム投稿ラベル名[タクソノミーターム名]です。タームの「説明」”>
// カテゴリ一覧2ページ目表示時
<title>タクソノミーターム名 | カスタム投稿ラベル名2ページ目 | samplesite.com</title>
<meta name="description" content="カスタム投稿ラベル名[タクソノミーターム名]2ページ目です。タームの「説明」”>

rel=”canonical”/”next”/”prev”を表示するコード

「rel=”canonical/next”/”prev”」をマークアップします。表示判定に「is_singular()」を使用すると固定ページ内サブループの際に意図した動作をしないので今回は「is_single()」で。

D.rel=”canonical”/”next”/”prev”を表示

<?php
    if (is_home()) {
        $canonical_url = get_bloginfo('url');
    } elseif (is_category()) {
        $canonical_url=get_category_link(get_query_var('cat'));
        if ( $paged >= 2) {
            $canonical_url = $canonical_url.'page/'.max( $paged, $page ).'/';
        }
    } elseif (is_archive()) {
        $canonical_url=$cat_url;
        if ( $paged >= 2) {
            $canonical_url = $canonical_url.'page/'.max( $paged, $page ).'/';
        }
    } elseif (is_page() || is_single()) {
        $canonical_url = get_permalink();
        if ( $paged >= 2 || $page >= 2) {
            $canonical_url = $canonical_url.'page/'.max( $paged, $page ).'/'; }
    } elseif(is_404()) {
        $canonical_url = get_bloginfo('url')."/404";
    } else {
        $canonical_url = get_bloginfo('url');
    }
?>
<link rel="canonical" href="<?php echo $canonical_url; ?>">
<?php if(!is_home()) { ?>
    <?php if ( !is_single() && $paged > 1  ){ ?>
        <link rel="prev" href="<?php echo previous_posts( false ); ?>">
    <?php } if ( !is_single() && ( $nextpage <= $max_num_pages ) ){ ?>
        <link rel="next" href="<?php echo next_posts( $max_num_pages, false ); ?>">
    <?php } ?>
<?php } ?>

function.php

デフォルトでマークアップされる、rel=”canonical/next”/”prev”の設定を解除しておきます。

<?php
// デフォルト設定のrel="canonical"の自動挿入を停止する
remove_action('wp_head', 'rel_canonical');
// 個別記事へのrel="next"、rel="prev"の自動挿入を停止する
remove_action('wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );
?>

head内にマークアップ

category.phpやarchive(-xxxx).php、サブループ表示をする固定ページテンプレートのheadタグ内に上述のBとC、Dのコードを記述します。固定ページ内サブループの場合はAのサブループの設定を済ませた状態でBとC、Dのコードを記述します。

// 個別記事以外
<head>
    <meta charset="utf-8">
    <?php if(is_page('サブループ表示をする固定ページスラッグ')) { ?>
    A.$pagedと$my_queryにデータを代入するコード
    <?php } ?>
    B.$max_num_pagesと$nextpage、$pagedに数値を代入するコード
    C.タイトルとディスクリプションを表示するコード
    ...
    D.rel="canonical"/"next"/"prev"を表示するコード
</head>

期待される効果

  • 重複する内容のマークアップによる検索エンジンからのペナルティー回避。
  • 検索エンジンがクロールしやすくなる。
  • Google Analyticsでコンテンツグルーピングが可能になる。

さいごに

SEO関連のプラグインは便利ですが、意図していないことをされる場合があるので、今回はこのようなコード記述による方法を記事として残すことにしました。この件については以上です。

参考

Author

  • Shinichi Kuroda - 黒田晋一
  • 香川県高松市 - Takamatsu-shi, Kagawa, Japan.
  • Mail - info@studiobusstop.com