WordPressの重複ページ、低品質ページ対策を考える rel=”prev”,”next”,noindex,rel=”canonical”など

ここ数年Googleは検索結果向上のため、内容の薄いページや他からコピーしてきたページが多いなど低品質なサイトに対して、ペナルティを与えるようになっています。

通常のブログ運営においては、ペナルティを与えられることは無いにしても、重複ページが多い場合にはサイトの評価はさがってしまうそうです。
ウェブマスターツールにtitleやmeta descriptionの重複をチェックする機能があることからも、Googleが重複ページを気にしているのがわかります。

ブログの本来のパフォーマンスを発揮させるためにも、出来る限り重複コンテンツは無くした方がよいはずです。
一方で、私が使用しているテーマ、Stingerでは重複ページ対策も入っていて、無駄なページはインデックスされないようになっているのですが、ホーム、記事、カテゴリの1ページ目のみインデックスというのは若干過剰なのではと感じました。

WordPressで重複ページ対策として、何が出来て、何をするべきかを調べて実装したことをまとめてみました。

複数に分かれているページにはlink rel=”prev”, rel=”next”を使用

トップページやカテゴリページなど複数ページに分かれているページは、表示の都合上複数ページに分かれていますが、本質的には同一のページです。
2ページ目以降もできることならインデックスしてもらって評価の対象にしてもらいたいところです。
これらのページには、head内に<link rel=”prev” href=”…”/>、<link rel=”next” href=”…”>を記述することで、ページの関連性を検索エンジンに伝えることができます。

ひと続きになっているコンテンツを構成する個々の URL に rel=”next” と rel=”prev” を指定し、URL 間の関係性を Google に示す(このブログ記事で紹介している例です)。これによって Google はコンテンツのインデックス登録がより正確にできるようになり、最も関連性の高いページ(通常は最初のページ)をユーザーに表示するようになります。

WordPressでの実装

WordPressではデフォルトでrel=”prev”,”next”が挿入されるので、まずそれをremove_actionで取り除く必要があります。
wp_headアクションフックを使用すれば、テーマをいじらずにheadにタグを挿入できます。
function.phpに書くのもいいですが、こちらもテーマ依存なので私はプラグインを作成してそちらに記述しています。


remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 );

function link_rel_next_prev(){
    global $paged;
    if ( get_previous_posts_link() ){ ?>
<link rel="prev" href="<?php echo get_pagenum_link( $paged - 1 ) ?>" />
<?php }
    if ( get_next_posts_link() ){ ?>
<link rel="next" href="<?php echo get_pagenum_link( $paged +1 ) ?>" />
<?php }
}
add_action( 'wp_head', 'link_rel_next_prev' );

noidexは必要最小限に

重複ページや低品質なページの対策の一つとして、必要の無いページに<meta name=”robots” content=”noindex,follow” />を指定するという方法があります。
これを指定すると、検索エンジンはこのページのリンクはたどるものの、ページ自体はインデックスしなくなります。
ペナルティを受けないのならば、なるべく多くのページがインデックスされていた方が、検索エンジンのクローリングやサイト構造の把握が円滑に行われるのではないかと思っているので、noindexは必要最小限にしたほうがよいと考えています。

当サイトの方針

トップページ、記事ページ、カテゴリページ

全てindexさせます。

年月日別アーカイブページ

日別アーカイブページは、ほぼ1記事しか含まれないのでno indexです。
年月別アーカイブページは、トップページと同じ内容になりがちな、当年のアーカイブページや当年当月のアーカイブページのみno indexです。
月や年が変われば、indexさせます。

その他アーカイブページ

タグページ、投稿者別アーカイブなどは使用していないですが、何かの拍子にリンクができてしまったときのために、一応no indexです。

添付ファイル用のページ、検索ページ

no indexです。

複数ページに分かれているページ

上記のlink rel=”prev”,”next”で対応するので、indexさせます。

WordPressでの実装

上の方針を実装したのが以下になります。
こちらもwp_headアクションフックにて出力しています。

function meta_robots(){
    $noindex = false;
    if(is_archive()){
        if(is_category())
            $noindex = false;
        else if(is_date()){
            if(is_day())
                $noindex = true;
            else if(is_month() && get_query_var('year')==date_i18n('Y') &&
                    get_query_var('monthnum')==date_i18n('m'))
                $noindex = true;
            else if(is_year() && get_query_var('year')==date_i18n('Y'))
                $noindex = true;
        }
        else
            $noindex = true;
    }
    else if(is_search())
        $noindex = true;
    else if(is_attachment())
        $noindex = true;
    if($noindex) { ?>
<meta name="robots" content="noindex,follow" />
<?php };
}
add_action( 'wp_head', 'meta_robots' );

複数のURLに対応するためlink rel=”canonical”

WordPressではURLによって記事を自動生成しているため、同一のページが別のURLで表示できることがあります。
例えば、子カテゴリを作成した場合、通常のURLは/category/{親カテゴリ}/{小カテゴリ}となりますが、/category/{小カテゴリ}でもアクセスできます。
またslugの大文字小文字に区別はないようで、/wordpress という記事には、/WordPress というURLでもアクセスできます。
これらは通常はアクセス出来るだけで、リンクやリダイレクトを間違わない限り検索エンジンに認識されることもないのですが、一旦認識されてしまうと重複コンテンツとなってしまいます。

また当サイトのように、無料ブログ等からリダイレクトをしていると、無料ブログで使用されているURLパラメータ(Seesaaブログからだと?from_pc,?from_spなど)がついていると、別のURLと見なされ、重複コンテンツとなります。
こちらはウェブマスターツールのURLパラメータでクローラーの動作を設定できますが、一度インデックスされてしまったページに関しては効果が薄いように思います。

これらのようなURLの違いによる重複ページは、301リダイレクトを全てに設定するのは大変なので、<link rel=”canonical” href=”” />でURLの正規化を行うのがよいようです。

WordPressでの実装

以下でホーム、記事、カテゴリ、タグ、年月日アーカイブにcanonicalを設定できます。
複数ページに分かれたページのcanonical urlを取得する方法がなさそうだったため、urlを生成しています。
そのため、パーマリンクを使っているサイトのみに対応するコードになっています。

WordPressは記事ページにのみデフォルトでcanonicalが付いているので、remove_actionで取り除いてあります。
こちらもwp_headアクションフックにて出力しています。

remove_action( 'wp_head', 'rel_canonical' );
function link_rel_canonical(){
    $url = '';
    if(is_home() || is_front_page())
        $url=get_home_url();
    else if(is_singular())
        $url=get_permalink();
    else if ( is_tax() || is_tag() || is_category()){
        $term = get_queried_object();
        $url = get_term_link($term);
    }
    else if(is_date()){
        if(is_day())
            $url=get_day_link(get_query_var('year'),get_query_var('monthnum'),get_query_var('day'));
        else if(is_month())
            $url=get_month_link(get_query_var('year'),get_query_var('monthnum'));
        else if(is_year())
            $url=get_year_link(get_query_var('year'));
    }
    if(!empty($url) && is_paged()){
        global $wp_rewrite;
        $url = user_trailingslashit( trailingslashit($url).trailingslashit($wp_rewrite->pagination_base).get_query_var('paged'));
    }
    if(!empty($url)) {?>
<link rel="canonical" href="<?php echo $url?>" />
<?php }
}
add_action( 'wp_head', 'link_rel_canonical' );

その他の個別記事への対策

以下は個別の記事に対する対策です。

内容の重複する記事は301リダイレクト

同じような内容の記事がある場合は、どちらかにまとめて301リダイレクトを設定します。

不必要な記事は削除、もしくはnoindex

内容の薄い記事などあまり必要ない記事がある場合は思い切って削除するか、noindexを指定します。

個別記事にmeta name=”robots”を指定する方法

以下のコードでmeta_robotsというカスタムフィールドからcontentの値を読み、head内に出力させます。

function load_meta_robots(){
    if(is_single() || is_page()){
        if($content= get_post_meta(get_the_ID(), 'meta_robots', false)){  ?>
 <meta name="robots" content="<?php echo $content[0]; ?>" />
 <?php }
    }
}
add_action('wp_head', 'load_meta_robots');

まとめ

以上で主要な重複ページ対策はカバーできていると思います。
これらの対策はブログ運営において、本質的なところではなく、あまり気にせず、質の高い記事を増やした方がよい、という意見もあるかと思います。
ただサイトのパフォーマンスを最大限に高めるためにも、やっておいて損はない対策かと思います。

モバイルバージョンを終了