WordPress でアーカイブページに canonical タグを設定する

WordPress ではホームやシングルには canonical タグが自動で作られます。アーカイブページには作られません。アーカイブにも canonical を設定したい場合、どう書けばいいでしょうか。こうしました。

WordPress でアーカイブにも canonical を設定する

WordPressでアーカイブページにも canonical を設置する話ですが、正規URLにパラメータが含まれるようなタイプには当てはまりません。普通のURLである場合に限る話となります。

また、これが正しいやり方なのだと胸をはって言いません。自信ないんで。canonical の設置は重要かつ危険もありますので、無闇矢鱈とネットの情報を過信しないことが大切です。ではさくっと行きます。

header.php の <head></head> 内に書く

header.php の <head>タグ内に次のように書きましたが、これをコピペして使おうとは思わないでください。

<?php
  $uri = $_SERVER['REQUEST_URI'];
  if(strstr($uri,'?cx=')==false){
	if(!is_404() || !is_search() || !is_singular() || !is_home()|| !is_front_page( ) ){
		$home = esc_url(home_url());
		if (strpos($uri, '?')!==false){
		$url = strstr($uri, '?', true );
	} else {
		$url = $uri ;
	}
	$canonical = '<link rel="canonical" href="' . $home. $url.'">';
	echo $canonical;
    } 
  }
?>

いきなり特殊事情の if から始まります。これ何かというと、google custom search を除く措置です。なぜこれだけ飛び出してるかというと、他の条件と並列に「 ! is_search()」と書いていたんですが google search に効果なかったんで、慌てて付け足した形跡です。

条件を指定してその中で作る

その次の if からが普通の本番、google custom search が関係ない人はここからです。関係ない場合の例も書いておきますが、上のやつを適当に削って今書いただけなので過信してはいけません。

<?php
 $uri = $_SERVER['REQUEST_URI'];
 if(!is_404() || !is_search() || !is_singular() || !is_home()|| !is_front_page( ) ){
	$home = esc_url(home_url());
	if (strpos($uri, '?')!==false){
		$url = strstr($uri, '?', true );
	} else {
		$url = $uri ;
	}
	$canonical = '<link rel="canonical" href="' . $home. $url.'">'; 
	echo $canonical
 }
?>

もうひとつ別パターンも。こちらは、アーカイブでページネーションがあった場合、無視して1ページ目のURLを記述します。

if(!is_404() || !is_search() || get_post_type() !== 'person' || !is_singular( ) || !is_home()|| !is_front_page( ) ){
	$gpl = get_pagenum_link();
	if (strpos($gpl, '?')!==false){
		$cano1 = strstr($gpl, '?', true );
	} else {
		$cano1 = $gpl ;
	}
	$canonical = '<link rel="canonical" href="' . $cano1.'">';
	echo $canonical ;
}

条件

WordPress ではシングルページやホームに canonical を付けてくれます。これの邪魔をしません。アーカイブだけで発動させたいので、条件分岐します。

気軽に is_archive()  とやろうとしたんですが、除外すべき条件が複雑になり、それで上記のような否定の列挙となりました。404 を除外し、シングラーを除外し、ホーム・フロントページを除外します。これでいいのかどうか自信ないですが、しばらく目視でチェックしてみて問題なさそうなのでした。

現在ページのURLを取得する

canonical の書き方

条件が整ったので canonical を作ります。canonical の書き方はこうですね。

<link rel="canonical" href="URL">

これをどうやって作るかですが、手順は、1 URLを取得し、2 クエリ文字のパラメータ部分をばっさり切り落とします。

現在ページのURL

URLの取得方法に二つのパターンがあります。一つは $_SERVER[‘REQUEST_URI’] 、もう一つは get_pagenum_link() を使います。

$_SERVER[‘REQUEST_URI’]

$_SERVER[‘REQUEST_URI’] には現在アクセスしているページの URI が格納されています。ホスト名以下がクエリ文字も含めてしっかり取得できますので、ホスト名と組み合わせれば URL が完成します。

ホスト名は $_SERVER[‘HTTP_HOST’] で取得できますが、いちびってそんなの使わなくても現在のサイトを手書きしてOKです。このブログなら https://www.digitalboo.net/ です。home_url()を使っても良いでしょう。

訳註: いちびる = 格好を付ける、調子に乗る

get_pagenum_link()

get_pagenum_link() は、ページングされたページ番号リンクを取得するWordPress 関数ですが、パラメータに何も書かずにいるとデフォルトの「1」が適用されます。つまりページングを無視した大元のURLをゲットできます。

例えば archives/category/wordpress/page/3 というカテゴリーアーカイブ3ページのURLなら、archives/category/wordpress/ と、なります。

canonical は正規URLを宣言する行為ですから、実際の話アーカイブページをすべて1ページ目にしてしまうのは嘘ですよね。こういうことをやっていいのかどうかわかりませんが、かといってあまり意味のないページネーションされたアーカイブのページをいちいち正規宣言するのもどうかと思いまして。

このあたりの知見がないので判断できませんが、とにかくページングをしっかり取得して利用するか、ページングを無視したいのかという二種類の取得方法を書いておきました。

URL を小細工して canonical として設定する

URLからパラメータを取っ払う

さて何らかの手段により現在ページのURLをゲットできました。次はパラメータを取っ払う作業です。今回の最大目的こそパラメータを取っ払うことであると言っても過言ではない。力まなくていいですか。はい。

まず URL が「 ? 」を含んでいるかどうかで条件分岐しましょう。

if (strpos($uri, '?')!==false){ }

stropos() は指定文字列が現れる場所を見つけて整数を返すPHP関数です。ネットの物知り博士たちによりますと、この関数は整数を返すので正しく結果を得るため == を使ってきっちり書く必要があるとのことです。上の例では「ではないではないぞ!」と強く条件付けてます。いえいえ ! はそういう意味じゃないですよ💦 詳しくはネット賢人のブログやPHPのマニュアル をご覧ください。

これを経て、? の存在が確認されれば、次の式で「 ? 」より前の部分だけ採用します。

strstr($uri, '?', true );

strstr() は strpos と似ていますが、部分文字列を返してくれます。最後に true を付けると検索文字列「?」を含めず直前までを返します。つまり ? 以降のクエリ文字をすべて消し去ることができます。

以上、パラメータのクエリ文字列をすべて外すという小細工でした。冒頭で言ったように「パラメータを含む URL が重要でそれを canonical としたいのである」というような作りをしている人には相容れない話となります。

ということで大体これで今日のお話は終わりです。

この後、だらだらと話が続きますが気にしなくていいです。

canonical について

canonical タグは URL の正規化を宣言することでオリジナルのURLを明確にします。URLが異なってもどれが正規であるかを示すので、検索エンジンの重複判定を防ぐこともできます。

似たページじゃなく同じページ

重複と判定されることに関して「似たページ」という記述を見かけますが、「同じ内容でURLが異なる」と捉えた方が感覚的には近いです。例えば以下はどれも同じページが表示されますが、URLが異なります。

https://www.movieboo.org/28469/bajrangi-bhaijaan https://www.movieboo.org/28469/ https://www.movieboo.org/?p=28469

検索エンジンにとってアイデンティティの砦はURLですので、上記三つのURLは「この三人は同じ内容だな。丸パクリかクローン」と判断されます。もし canonical で一番目のURLを宣言していれば「三人かと思ったが一人だったようだ」と納得してくれます。

そんなわけで大事な canonical です。WordPress では自動で付けてくれますので気にしなくていいんです。ただし、自動で付けてくれるのはホームとシングルのみ。ここをどう判断するかは人によります。

アーカイブページの正規化

アーカイブページは、ソートを変えたりフィルタしたりと、その都度クエリ文字が変わりその分だけURLを無限に発行します。内容もクエリに応じて変化しますから「同じ」ではありませんが、まあ同じアーカイブです。これを以て「似たページ」という表現になりますね。ソートはもちろん、フィルタして内容が多少変わっても、アーカイブの根っこの目的というかページ内容は「別のページ」と言い切るほどではなく、同じと判断していいんじゃないかと思っています。が、これはサイトの作りや意図や目的によっていろいろあるでしょう。

で、パラメータを勝手に付けまくったロボットが暗躍したりもします。アーカイブページは無限に増え続けるURL発生装置でもあります。

アーカイブページでも正規化を果たすことで、canonical 以外のURLは一切インデックスされなくなり、面倒なパラメータ指定の重複対策が不要になります。

近年の検索エンジンはクエリ文字の判断能力も上がったから気にしなくて良いという話もあります。昔のgoogleはパラメータをどうするかユーザーが設定する仕組みまで用意していました。パラメータ違いの無限URLを巡回してインデックスするのかどうか、判断能力がまだなかった昔の話です。か?そうですか?本当に昔話でしょうか。

重複URLの警告
重複URL

ウェブマスターツールをふと思い出して久しぶりにアクセスしてみますと、サーチコンソールという名前に変わっていました。いやその話じゃなく。17万ページの重複を指摘されていました。

パラメータ違いの大量の重複
パラメータ付き大量アクセスがすべて重複として警告

中身を少し確認すると、謎のパラメータ違いのアーカイブページがひしめいていました。WordPress が caononical を付けてくれるシングルポストではこういうことは起きません。まるで耳だけお経を書き忘れて悪霊に引きちぎられた坊さんのように、caononical を付け忘れたアーカイブにだけ悪霊どもが無限パラメータをくっつけて襲いかかっているような形相です。

これを見て「アーカイブにも canonical いるんじゃないの?」と思ったことが今回のきっかけでした。robots.txt でちくちく拒否設定を書くより、アーカイブページそのものを canonical 設定してパラメータURLを一網打尽にしたほうが早いのではないかと。

全部不要論

それ以前にそもそも「アーカイブページなど robots.txt で全切りしておるわ」という人もおられます。そういう考えもあるでしょう。好みや目的によって変わります。

ネット情報の罠

自分はこっち方面の話に疎いので、canonical をどう書けばいいのかについて賢人たちの意見を見て回りました。見様見真似で書いては失敗を確認して慌てて消すという地道な作業を続けているうちに、出鱈目な話にも満ちていることに気づきます。

間違い

例えば、次のように設定すれば万事OKみたいなことを言う人がいましたが完全な間違いです。

<link rel="canonical" href="https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] .'">

REQUEST_URI を無条件に canonical に設定すればどうなるか。無限パラメータの増殖URLをすべて正規URLと宣言してしまいます。$_SERVER[‘REQUEST_URI’] は「?」以降のパラメータ部分もすべてひっくるめて取得しますからね。こんな設定してたらたいへんざますよ。

かといって、パラメータを含まない $_SERVER[‘SCRIPT_NAME’] を使うと、これまたたいへんなことになります。サイト内全ページの正規 URL がトップページただ一つになります。なぜかというと、WordPress が処理するのは、パーマリンクで設定したURLよりもっと根深い部分で、その世界では /?=ID のような扱い、クエリ命です。それを除外する’SCRIPT_NAME’を使っても何も得られません。

同じ意味で「get_pagenum_link()」を書いてそれでOKお仕舞い。という人もおられますが上記と同じくクエリ文字も全部含まれますから却下です。

傲慢

間違いではありませんが、無垢な一般人が真似したら禄なことにならないベテランならではの傲慢系意見も見かけます。曰く「WordPress が自動で作る canonical なんか消しちゃえ。そしてすべて、己の裁量だけで canonical を全ページに設置するのじゃ」と、こう来ます。functions.php で WordPress の仕事をキャンセルしてから改めて自分で作り上げるという話ですが、大抵はその「作り上げる」ことに関しては省略しながら流して書かれています。そりゃ当然そうなります。逐一全部書いていられません。環境もそれぞれ違うし。

でもまるで当然の前提が如く「functions.php に〜と書いてまず WP の canonical をキャンセルします」と始めますから、一般素人さんがうっかり真似したら火傷を負います。

珍しく他人にケチつけてますがこの話にはオチがあります。

というのも、沢山作ったサイトの中でわりと古めのメンテしていないものがあったので canonical 処理をついでに行っていると、どうしても上手く作れないんですよね。何をどう書いても駄目。おっかしいなあ。おっかしいなあ。と思ったら、何と functions.php に、Wordpress の仕事をキャンセルする一行が書かれていました。これ書いたアホは誰じゃ。と見渡すと、犯人は私しかおりません。そうです。ド素人の雑魚が昔意味もわからず他人の受け売りで WP 仕草を拒否し、その後自分で構築することに頓挫して放置して忘れていたのです。何をやらかすのかわからない危険な存在がカルト自民党とド素人の雑魚という自虐オチでありまして、こういうことにならないよう皆様くれぐれもお気をつけを。

 

このエントリーをはてなブックマークに追加

コメント

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください