実践で学ぶ国際 SEO と hreflang
各市場で上位表示される多言語・多地域サイトを、正しい hreflang とともに公開する。
コンテンツが単一のオーディエンスだけに向けたものでなくなった瞬間、国際 SEO が必要になる。きっかけは大きく 2 つある。1 つ目は言語だ。サイトをドイツ語、日本語、スペイン語に翻訳したら、その翻訳をそれぞれの言語を読む人々に届けたい。2 つ目は地域だ。言語は同じでも市場が異なるケース、たとえば米国向けストアと英国向けストアがどちらも英語でありながら、価格・配送・スペル・法務文言が違う場合だ。実際には両方が同時に発生することも多い。米国向けの英語、英国向けの英語、ドイツ向けのドイツ語、オーストリア向けのドイツ語、といった具合に。
検索エンジンは、あなたの /de/produkt ページが /en/product のドイツ語版だと自動的には理解しない。推測に任せると判断を誤り、その代償は具体的だ。
- 間違った地域での順位付け。 米ドル価格のページが英国のユーザーに対して上位表示され、誤った通貨の決済画面に行き当たって離脱される。
- 自己カニバリゼーション。 ほぼ同一の英語ページ 2 つが同じクエリで競合する。Google はほぼランダムに片方を選び、シグナルが分散し、本来 1 ページにまとめた場合よりどちらも順位が下がる。
- 重複コンテンツによる希薄化。 翻訳されていない定型文や、ロケール間で共有されるテンプレートが、薄く反復的なコンテンツに見え、クラスタ全体の評価を引き下げる。
これを解決する仕組みが hreflang だ。これは検索エンジンに対して「この URL はこのページの X 言語・Y 地域版であり、ここにすべての兄弟ページがある」と伝える一連のアノテーションである。正しく実装すれば、各検索ユーザーをその人向けに作られたページへ振り分ける。間違えると—そして非常に間違えやすい—静かに何もしないか、最悪の場合クローラーを誤ったページに向けてしまう。本ガイドは実務者向けの内容だ。まず構造、次に実装、最後に何時間も溶かす失敗パターンを扱う。
URL 構造 — hreflang が乗る土台
どんなアノテーションよりも前に、ロケールを URL にどうマッピングするかを決める。この決定は後戻りが難しく(サイト上のすべての URL が変わる)、慎重に検討すべきだ。実用的なパターンは 3 つある。
| 方式 | 例 | SEO の評価(オーソリティ) | Google への地域シグナル | コストとセットアップ | 運用保守 |
|---|---|---|---|---|---|
| ccTLD(国別コードトップレベルドメイン) | example.de、example.co.uk | 分散 — 各ドメインがゼロからオーソリティを積み上げる | 最強 — .de は紛れもないドイツのシグナル | 高 — 多数のドメインを取得・防衛し、ホスティングと証明書も別 | 高 — ドメインごとに独立した SEO 資産 |
| サブディレクトリ | example.com/de/、example.com/en-gb/ | 集約 — すべてのロケールが 1 ドメインのオーソリティを共有 | 中 — hreflang とコンテンツで設定 | 低 — ドメイン 1 つ、証明書 1 つ、デプロイ 1 つ | 低 — 単一コードベース、単一資産 |
| サブドメイン | de.example.com、uk.example.com | ほぼ分散 — Google はサブドメインを半ば別物として扱う | 中 | 中 — サブドメインごとに DNS と証明書 | 中 |
ほとんどのサイトへの推奨はサブディレクトリ。 メインドメインが既に獲得したオーソリティを各ロケールが継承でき、各市場をゼロから登らせずに済む。運用も最も安価で、リポジトリ 1 つ、デプロイパイプライン 1 つ、TLS 証明書 1 つ、監視対象 1 つで足りる。そして静的サイトジェネレーターが自然に生み出すのもまさにこの形だ。
ccTLD は、地域シグナルがコストに見合うケースに限るべきだ。各国で独立にオーソリティを築けるリソースを持つ大規模ブランド、ローカルな信頼が決定的に重要な業界(金融、ヘルスケア、行政関連)、あるいは規制当局が事実上ローカルドメインを要求する場合などである。サブドメインは中間的な選択肢で、通常は SEO 上の理由ではなくインフラ上の理由(地域ごとに別スタック)で選ばれる。Google はサブドメインを問題なく扱えると明言しているが、実際にはオーソリティの集約はサブディレクトリほどきれいにはいかない。
💡 提示: ロケールのセグメントはパスの先頭に置く—
/blog/de/postではなく/de/blog/post。トップレベルのプレフィックスは曖昧さがなく、ルーティングも容易で、ロケール固有のロジック(通貨、言語ヘッダー)をルーティングツリーの 1 つの分岐に集約できる。
🧑💻 開発者視点: どれを選ぶにせよ、コード内でロケールを単一の信頼できる情報源(single source of truth)にすること—
locale -> { hreflang, currency, path prefix }をマッピングする設定オブジェクト 1 つにまとめる。他のすべてのシステム(サイトマップ、hreflang タグ、言語スイッチャー、アナリティクス)はその 1 か所から読み取るべきだ。fr-CAを追加する日に編集するファイルが、7 つではなく 1 つで済むように。
hreflang の実装 — 3 つの配信方法
hreflang は同じデータを、3 つのチャネルのいずれかで配信する。ページごとに主たる方法を1 つ選ぶこと。同じ URL で複数を混在させると矛盾を招く。以下のすべてに優先する譲れないルールはこれだ。アノテーションは双方向(リターンタグ)でなければならない。 ページ A が B を自身のドイツ語版として列挙するなら、B は A を自身の英語版として列挙しなければならない。たった 1 つのリンクでリターンが欠けていると、Google はそのページに対するクラスタ全体を無視する。これは握手のようなものだと考えるとよい—両方の手を差し出さなければ、取引は成立しない。
方法 1 — HTML の <link> 要素
最も一般的な方法。各ページの <head> に、**自分自身を含めて(自己参照)**すべてのロケール版と x-default を列挙する。
<!-- In the <head> of https://example.com/en/product -->
<link rel="alternate" hreflang="en" href="https://example.com/en/product" />
<link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/product" />
<link rel="alternate" hreflang="de" href="https://example.com/de/produkt" />
<link rel="alternate" hreflang="zh-CN" href="https://example.com/zh-cn/product" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/product" />
このセットに含まれるすべての代替ページが、同じブロックを持たなければならない(各エントリの 1 つとして自身の URL を自己参照する)。この同一性こそが双方向の握手だ。
方法 2 — XML サイトマップ
大規模サイトに最適。何千ものページの head ではなく 1 つのファイルでアノテーションを管理でき、サイトマップの 1 エントリでクラスタ全体を一度に宣言できる。
<url>
<loc>https://example.com/en/product</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/product"/>
<xhtml:link rel="alternate" hreflang="en-GB" href="https://example.com/en-gb/product"/>
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/produkt"/>
<xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/en/product"/>
</url>
ルート要素に名前空間を付けるのを忘れずに: xmlns:xhtml="http://www.w3.org/1999/xhtml"。そして双方向ルールはここでも適用される—クラスタ内のすべての <url> エントリには、1 つのピアへのリンクだけでなく、完全なセットの xhtml:link 子要素が必要だ。
方法 3 — HTTP の Link ヘッダー
PDF のような非 HTML ファイルで唯一の選択肢。編集できる <head> がないためだ。レスポンスヘッダーとして配信する。
Link: <https://example.com/en/manual.pdf>; rel="alternate"; hreflang="en",
<https://example.com/de/handbuch.pdf>; rel="alternate"; hreflang="de"
方法の選び方
| 方法 | 適する場面 | 注意点 |
|---|---|---|
HTML <link> | 小〜中規模サイト、テンプレートを完全に制御できる場合 | ページ重量が増す。ロケール変更時に全ページを編集 |
| XML サイトマップ | 大規模サイト、プログラムによる生成 | サイトマップを実 URL と完全に同期し続ける必要がある |
| HTTP ヘッダー | PDF などの非 HTML アセット | サーバー/エッジの設定が必要。忘れやすい |
コードを正しく書く
値は language または language-REGION だ。
- 言語のみ —
en、de、zh、fr。その言語の話者をどこにいても対象にする。 - 言語 + 地域 —
en-GB、en-US、zh-CN、pt-BR。その国におけるその言語を対象にする。
言語コードは ISO 639-1(2 文字)。地域コードは ISO 3166-1 alpha-2(2 文字で、大陸や言語ではなく国)。よくある罠: 英国の国コードは UK ではなく GB だ。そして x-default はフォールバックの受け皿で、あなたが明示的にカバーしていない言語/地域のユーザーに表示されるページを指す(次節で詳述)。大文字小文字は強制されないが、慣例的な形式は言語を小文字、地域を大文字とする: zh-CN、en-GB。
よくある間違い — 何時間も奪う失敗パターン
hreflang は静かに失敗する。エラーページは出ない。タグが単に無視され、ロケールが順位の中で漂い出す。以下が繰り返し起きる原因だ。
-
リターンタグの欠落。 ページ A は B を指すが、B は A を指し返さない。最も頻繁に起きる失敗であり—壊れたリンクだけでなくクラスタ全体を無効にする。常に完全で対称なセットをすべてのページにレンダリングすること。
-
誤った、または無効なコード。
en-GBではなくen-UK。存在しない地域コードの捏造(en-EU—EUという国はない)。地域が入るべき場所に言語を使う。1 つの無効なエントリがセット全体を無効にしうる。ISO リストに照らして検証すること。 -
相対 URL。 hreflang はプロトコルとホストを含む絶対 URL を要求する—
/de/produktではなくhttps://example.com/de/produkt。相対 URL は無視される。 -
canonical が hreflang と争う。 これが微妙ながら致命的だ。各ロケールページの canonical は自己参照でなければならない—
/de/produktは/de/produktを正規化先とする。もし全ロケールが代わりに英語版を正規化先にすると、Google に「これらは重複なので英語版だけをインデックスせよ」と伝えることになり、「これらは別個のロケール相当物だ」という hreflang の主張と真っ向から矛盾する。canonical が勝ち、翻訳がインデックスから消える。ルール: 自己参照 canonical + hreflang セットを、すべてのページに。 -
x-defaultの欠落。 厳密には必須ではないが、これがないと Google はマッチしないユーザーに対する宣言済みフォールバックを持てない。常にx-defaultを含めること—通常は言語選択ページか、最も汎用的/デフォルト言語版を指す。 -
リダイレクトや非 200 の URL へのアノテーション。 セット内のすべての URL は
200 OKを返し、インデックス可能でなければならない。301 リダイレクトや 404 を返す URL を hreflang で指すと、そのクラスタのノードが壊れる。 -
配信方法の不整合な混在。 サイトマップは A と言い、HTML head は B と言う。単一の信頼できる情報源を 1 つ選ぶこと。
⚠️ 注意: hreflang はクラスタリングとルーティングのヒントであって、順位のブーストではない。弱いページを引き上げることはない。正しく実装されたとき、すでに順位が付いている適切なページが各検索ユーザーに表示されるよう保証する。期待すべきは「ユーザーが正しいロケールに着地するようになった」であって、「トラフィックが倍増した」ではない。
言語ターゲティング vs 地域ターゲティング — 自分自身と競合しない
最も難しい戦略的判断は、どこまで細かく分けるかだ。ロケールページは多ければ良いというものではない。保守を増やし、自己競合のリスクを高める。
言語のみでターゲティングする(en、de、fr)のは、 その言語の話者全員に対して、国に関係なくコンテンツが本当に同一の場合だ—同じ製品、同じ価格、同じコピー。ドイツ・オーストリア・スイスを 1 つのドイツ語ページで賄うほうがシンプルで、単一 URL にシグナルを集中できる。
言語 + 地域でターゲティングする(en-US、en-GB)のは、 同じ言語が市場ごとに異なるコンテンツを必要とする場合だ—価格や通貨の違い、配送や在庫の違い、地域固有の法務文言、分ける価値のあるスペルや慣用表現の違い(color/colour、fall/autumn)。
危険地帯は同じ言語で、複数地域、ほぼ同一のコンテンツだ—価格文字列だけが異なる en-US と en-GB のページ。Google にはこれらが同じクエリで競合する重複に見え、典型的な自己カニバリゼーションの罠にはまる。抜け道は 2 つ。
- 分ける価値があるだけ差別化する—異なる価格、ローカルな事例、市場固有のセクション—さらに正しい hreflang を組んで、Google が勝手に選ぶのではなく地域でルーティングするようにする。
- あるいは言語のみに統合する(
en+x-default)。市場が本当に変わらないなら。強い 1 ページは、弱い双子 2 つに勝る。
💡 提示: 役立つテスト—米国と英国の訪問者が同じページで等しく満足できるなら、地域別ページは不要だ。 体験が本当に分岐するときだけ分割する。
ツールと検証
hreflang は規模が大きくなると目視では検証しきれないほどエラーが起きやすい。ワークフローに組み込むこと。
- Google Search Console。 International Targeting(インターナショナル ターゲティング)/ Page indexing(ページのインデックス登録)レポートが、Google 自身のパース結果から hreflang エラー(「リターンタグなし」「不明な言語コード」)を直接示す。これが真実(グラウンドトゥルース)だ—Google が見ているものを Google が教えてくれる。ロケールを展開するたびに確認すること。
- hreflang バリデーター。 専用チェッカー(Merkle の hreflang タグテストツール、TechnicalSEO.com、Aleyda Solis のジェネレーター)が URL を受け取り、相互参照・コードの妥当性・絶対 URL を検証する。ジェネレーターで正しい最初のセットを生成し、次にバリデーターで公開済みページを確認するとよい。
- クローラー。 Screaming Frog、Sitebliss、Ahrefs のサイト監査は、サイト全体をクロールし、リターンタグの欠落、非 200 の代替ページ、canonical と hreflang の衝突を何千もの URL にわたって一度に検出する—大規模サイトを監査する唯一の実用的な手段だ。
curlでヘッダーと head の手早いチェック。 HTTP ヘッダー hreflang やページの head を単発で検証する場合:
# Inspect HTTP Link-header hreflang (e.g. on a PDF)
curl -sI https://example.com/en/manual.pdf | grep -i '^link:'
# Pull every hreflang link from a rendered page
curl -s https://example.com/en/product | grep -o 'hreflang="[^"]*"'
🧑💻 開発者視点: CI チェックを追加すること。ビルド成果物をクロールし、各ページの hreflang セットをパースし、相互参照・絶対 URL・自己参照 canonical をデプロイ前にアサートする。パイプライン内の 30 行のスクリプトが、3 週間後に Search Console で発覚する代わりに、PR の時点でリターンタグ欠落バグを捕まえてくれる。
🧑💻 このサイト自体を実例として
このサイト自体が二言語(英語と中国語)であり、これらのルールに従って成り立っている。Astro の i18n サポートで構築されており、各ガイドは /en/ と /zh/ のパスプレフィックスの下に存在する(サブディレクトリ—上述の推奨)。各ロケールを hreflang 値とパスプレフィックスにマッピングする単一のロケール設定によって駆動される。その設定こそ開発者視点の提示にある単一の信頼できる情報源であり、言語スイッチャー・ルーティング・hreflang タグはすべてそこから読み取る。
hreflang アノテーションは、各ページの head に手書きするのではなく、Astro のサイトマップインテグレーションによって自動生成される。サイトがビルドされると、インテグレーションがロケール設定を走査し、翻訳された各ページについて完全な双方向 xhtml:link クラスタ(x-default を含む)を出力し、1 つのサイトマップを書き出す。新しいロケールの追加は、数百ファイルを掃き直すのではなく設定の編集で済む—そして相互参照は構造的に保証される。ジェネレーターが毎回対称なセットを出力するからだ。
これはフレームワークの**レイヤー 7(Advanced & Extensions)が動いている姿だ—国際 SEO は、基礎が固まってから重ねる上級の関心事である。だが実装はレイヤー 2(Build レイヤー)**の深部で行われている。i18n ルーティングとサイトマップ生成は、後から取って付けたものではなく、サイトの土台に組み込まれている。静的出力とサイトマップがどう生成されるかの仕組みを知りたければ、Edge SEO とビルドレイヤーのガイドが、これを自動化するデプロイと生成のパイプラインを扱っている。
重要ポイント
- ✅ デフォルトはサブディレクトリ(
/de/、/en-gb/)—オーソリティを集約し、コストが最も低く、静的ジェネレーターが自然に生み出す形だ。ccTLD は強い地域信頼が必要なケースに限る。 - ✅ すべての hreflang セットを双方向かつ自己参照にし、絶対 URL と
x-defaultを備えること—リターンタグが 1 つ壊れるとクラスタ全体が無効になる。 - ✅ canonical は各ロケールで自己参照を保つこと。翻訳をデフォルト言語に正規化してはいけない、さもないとインデックスから消える。
- ✅ ISO コードを正しく使う—言語は ISO 639-1、地域は ISO 3166-1(
en-UKではなくen-GB)。 - ✅ 地域で分けるのはコンテンツが本当に異なるときだけ。それ以外は言語でターゲティングして自己カニバリゼーションを避ける。
- ✅ 継続的に検証する—Search Console + クローラー + CI の相互参照チェック。hreflang は静かに失敗するからだ。