コンテンツへスキップ

hreflangタグの基礎 — 検索エンジンはどうやってJP/EN記事のペアを認識するか

日本語と英語の両方でサイトを運用していると、「同じ内容の記事が2つあるのに、検索エンジンはそれを別々のページとして扱ってしまうのでは」「日本語で検索した人に英語版が出てしまうのでは」という疑問が出てくる。この問題に対して、HTMLの <head> に書く hreflang という仕組みが用意されている。今回は、hreflangが何を伝えているのか、どんな書き方が必要なのか、そしてこのブログ(wpmm.jp/blog と en.wpmm.jp/blog)での実際の運用を例に整理する。

補足: hreflang は、検索エンジンに対して「このページには別の言語・地域向けの対応ページがある」と知らせるための属性である。ページの内容を翻訳するものではなく、あくまで「どのURLとどのURLが同じ内容の言語違いか」という対応関係を宣言するものにあたる。

hreflangが解決しようとしていること

言語違いのページが複数あるとき、検索エンジン側からは次のような判断が難しくなる。

  • どちらのページを、どの言語で検索した人に見せるべきか
  • 2つのページは別々の記事なのか、同じ内容の言語違いなのか
  • 似た内容の重複ページとして扱うべきかどうか

hreflangは、これらの判断材料をサイト運営側が明示するための仕組みである。検索エンジンはページの文章から言語を推測することもできるが、推測に任せるよりも、対応関係が明記されているほうが判断の根拠がはっきりする。

基本の書き方

記事ページの <head> に、次のような link タグを並べる。

<link rel="alternate" hreflang="ja"        href="https://wpmm.jp/blog/sample-article/" />
<link rel="alternate" hreflang="en"        href="https://en.wpmm.jp/blog/sample-article/" />
<link rel="alternate" hreflang="x-default" href="https://wpmm.jp/blog/sample-article/" />

見るべき要素は次の3つである。

要素 意味
rel="alternate" 「このページの別バージョン」を指す関係であることを示す
hreflang="ja" など そのURLが対象とする言語(必要なら地域も。en-US のように書ける)
href 対応するページのURL(絶対URLで書く)

x-default は特別な値で、「どの言語にも当てはまらない人に見せる既定のページ」を指す。言語を選ぶ入口ページや、主言語のページを指定するのが一般的である。

守るべき大事なルール: 相互参照(双方向)

hreflangで最も見落とされやすいのが、双方向で宣言する必要があるという点である。日本語ページが英語ページを指していても、英語ページ側が日本語ページを指し返していなければ、対応関係は成立しないものとして扱われうる。

したがって、日本語ページにも英語ページにも、上の3行と同じ内容を両方に置く。自分自身を指す行(日本語ページなら hreflang="ja" の行)も含めて、同じセットを両方のページに書くのが基本になる。

その他、実際に運用するうえで押さえておきたい点は次のとおりである。

  • URLはcanonicalと矛盾させない。canonical(正規URL)と、hreflangで指すURLが食い違うと、どちらを信じるべきか判断が割れる
  • 言語コードは ja・en のようにISO 639-1 の2文字コードで書く
  • 指す先のページが実際に存在し、正常に表示できること(404や別ページへのリダイレクトを指さない)

このブログでの実例: 同一slugでペアを作る

wpmm.jp/blog(日本語)と en.wpmm.jp/blog(英語)は、別々のWordPressサイトとして動いている。そのうえで、記事ごとに日本語版と英語版で同じslugを使う運用にしている。たとえば日本語版が https://wpmm.jp/blog/○○/ なら、英語版は https://en.wpmm.jp/blog/○○/ になる。

この運用の利点は、テーマ側のコードがとても単純になる点にある。現在のページのURLから /blog/ 以降のパス部分を取り出し、日本語側のベースURLと英語側のベースURLにそれぞれ付け直すだけで、対応するURLが組み立てられる。

// 説明用に簡略化した疑似コード
$jp_base = 'https://wpmm.jp/blog/';
$en_base = 'https://en.wpmm.jp/blog/';

// 現在ページのURLから「/blog/ 以降」を取り出す($rel)
$jp_url = $jp_base . $rel;
$en_url = $en_base . $rel;

echo '<link rel="alternate" hreflang="ja" href="' . esc_url($jp_url) . '" />';
echo '<link rel="alternate" hreflang="en" href="' . esc_url($en_url) . '" />';

記事ごとに「この日本語記事の英語版はどれか」という対応表を持つ必要がなく、slugを揃えておくだけでペアが機械的に決まる。前回の記事で扱った esc_url() を出力時に通している点も、ここで実際に使われている。

一方で、この方式には前提がある。日本語版と英語版でslugを完全に一致させることと、公開後にslugを変更しないことである。片方のslugだけが変わると、組み立てたURLが存在しないページを指してしまい、対応関係が崩れる。記事を公開する際にslugを慎重に決め、公開後は変更しないことにしている理由のひとつがここにある。

もう1つの実例として、このブログではカテゴリページなどの一覧ページでも同じ考え方で対応するURLを組み立てている。記事ページに限らず、「言語違いで同じ相対パスを持つ」という規則を全体で守ることで、全ページで一貫したペアが成り立つ。

出力後に確認するには

hreflangは目に見える表示を変えないため、書いたつもりでも抜けていることに気づきにくい。公開後に確認する方法はいくつかある。

  • ブラウザで対象ページのソースを表示し、hreflang を検索して、ja・en・x-default の3つが出力されているか、URLが正しいかを見る
  • 日本語ページと英語ページの両方で確認し、同じセットが出ているかを見る
  • curl などでHTMLを取得し、hreflang を含む行を抜き出して確認する

このブログでは、記事の公開後にSEO確認用のスクリプトで hreflang の出力を一覧し、ja・en・x-default のどれかが欠けていれば警告を出すようにしている。人間が目で見るよりも、欠落を機械的に拾うほうが見落としが少ないためである。

よくある落とし穴

  • 片方向だけの宣言: 日本語側にだけ書いて、英語側に書かない。前述のとおり相互参照が必要になる
  • canonicalとの食い違い: hreflangのURLとcanonicalのURLが別のものを指している
  • 相対URLで書く: hreflangのhrefは、原則として絶対URLで書く
  • 存在しないページを指す: 片方の言語の記事が未公開・削除済みなのに、対応するURLを出力し続ける。対応する記事が存在しない場合は、そのペアを宣言しない判断も必要になる
  • 言語コードの書き間違い: jp(正しくは ja)のように、国コードと言語コードを取り違える

特に日本語の ja は、国コードの jp と混同しやすい。hreflangの値は言語コードを使う点は、確認する価値がある。

まとめ

hreflangは、言語違いのページ同士の対応関係を、検索エンジンに向けて明示する仕組みである。ポイントは、rel="alternate" と言語コード、絶対URLの組み合わせで書くこと、そして日本語ページと英語ページの双方に同じセットを置くことにある。運用面では、slugを言語間で揃えておくと対応URLの組み立てが機械的になり、記事が増えても対応表を管理せずに済む。書いたあとは、両言語のページで出力を確認する習慣をつけておくとよい。

次回以降は、同じ <head> に置かれる別の情報(構造化データやOGPなど)についても取り上げる予定である。