実測と修正の記録・2026年8月15日

同じページが4つのURLで200を返していた|10サイトを実測して301で寄せた記録

「新しいページが検索に出ない」という症状を追っていて、同じ内容が最大4つのURLで200を返していることに気づきました。10サイト全部で同じ状態でした。クロールの予算を4分割していたことになります。

このサイトはAnthropicの公式サイトではありません。Claude Codeの機能・料金・提供範囲は変わる可能性があるため、重要な判断の前には公式のドキュメントと自分のアカウント設定を確認してください。

何が起きていたか

ひとつのページには、ふつう次の4通りのアドレスがあり得ます。

  • https://example.jp/(正規にしたいURL)
  • https://www.example.jp/
  • http://example.jp/
  • http://www.example.jp/

正しくは、下の3つが正規URLへ301で飛ぶ必要があります。ところが実測すると4つとも200を返し、4つとも同じHTMLを返していました。検索エンジンから見ると、中身の同じページが4本存在しているのと変わりません。

規模の小さいサイトほどこれが効きます。クロールに割り当てられる量には上限があり、それを4分割していたわけです。実際、調べていた6サイトは平均順位が17〜21位(=検索結果の2ページ目)にかたまっていて、クリック率の問題ではなく、そもそも順位が付いていない状態でした。

HTMLを見ていると気づけない

この欠陥がやっかいなのは、ページのソースを見ても正常に見えることです。10サイトすべてで <link rel="canonical"> は正しく https の非www を指していました。canonicalが正しいので、HTMLを目視しても、HTMLを機械で検査しても、何も出てきません。

気づくには、HTMLではなくレスポンスヘッダを見る必要があります。4通りのURLを順に叩いて、ステータスコードと Location ヘッダを並べるだけです。

curl -I http://example.jp/
curl -I https://www.example.jp/
curl -I http://www.example.jp/

この3本が 301Location: https://example.jp/ を返していなければ、4分割が起きています。1サイト10秒で判定できます。

先に %{HTTPS} を実測する(ここを飛ばすとサイトが落ちる)

直し方は .htaccess に301のルールを1本足すだけですが、先に実測しないと書いてはいけない値があります。サーバーが「今のアクセスはhttpsだ」と申告するかどうかです。

ロードバランサやプロキシの後ろにいるサーバーだと、実際にはhttpsで来ていても %{HTTPS} が常に off のままになることがあります。その状態で「httpならhttpsへ飛ばす」と書くと、飛ばした先でもまた off なので無限にリダイレクトし続け、サイト全体が見えなくなります

そこで、診断用のPHPを1サイトに一時的に置いて、httpとhttpsの両方から叩きました。

<?php
header('Content-Type: text/plain; charset=UTF-8');
header('X-Robots-Tag: noindex, nofollow');
foreach (array('HTTPS','SERVER_PORT','REQUEST_SCHEME',
               'HTTP_X_FORWARDED_PROTO','HTTP_HOST') as $k) {
  echo $k . '=' . (isset($_SERVER[$k]) ? $_SERVER[$k] : '(未設定)') . "\n";
}

結果はこうでした。

アクセスHTTPSSERVER_PORTX-Forwarded-Proto
https でon443未設定
http で未設定80未設定

X-Forwarded-Proto が無く、%{HTTPS} がスキームどおりに変わる=プロキシを挟んでいない、と確認できたので、%{HTTPS} !=on を条件に使って問題ないと判断しました。

この診断PHPは使い終わったら消します。消えたかどうかの確認はFTPのファイル一覧で行ってください。削除直後にブラウザで叩くと404ではなく500が返ることがあり、HTTPの応答だけでは「消えた」と判定できません。

投入したルール

.htaccess の先頭に置きました。2つの条件を1本のルールにまとめているのがポイントで、こうすると http://www.example.jp/ も1回のリダイレクトで正規URLに着きます。条件を分けて2本書くと2ホップになり、その分だけ余計に遅くなります。

# canonical-host-20260815
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^ https://example.jp%{REQUEST_URI} [R=301,L]
</IfModule>

先頭に置いても、既存の RedirectMatch(mod_alias)や後続のルールとは干渉しませんでした。IfModule の中で完結しているためです。

1サイトずつ、復旧できる形で流す

10サイトあっても一括では流しませんでした。手順は1サイトにつき次の4段です。

  1. 今の .htaccess をFTPでダウンロードして退避する(ローカルの一時領域へ。公開ディレクトリの中に置かない
  2. ルールを先頭に足してアップロードする
  3. 4通りのURLを叩いて、正規URLが200、他3本が301であることを確認する
  4. 正規URLが200でなければ、退避したファイルをその場で戻す

4段目が肝心です。ループが起きた場合、正規URLは200を返さなくなります。その判定を自動で入れておけば、事故ってもそのサイトだけで止まります。実際のコードでは、キャッシュで揺れることがあるので1.5秒あけて最大4回まで見に行き、それでも駄目なら復旧、としました。

結果は10サイトすべてで 301が3/3、正規URLは200。下層ページ・sitemap.xml・robots.txt もあわせて確認しました。

robots.txt まで301しないこと

ひとつ注意があります。サイトの引っ越しで同じようなルールを書くとき、/robots.txt まで転送先へ301してはいけません。移転元のrobots.txtが読めなくなると、クローラが移転元を回らなくなり、その結果301そのものが認識されなくなります。

今回のようにホスト名を揃えるだけの301なら、同じサイト内なのでこの問題は起きません。ドメインをまたぐときだけ気をつけてください。

よくある質問

canonicalタグを入れてあれば十分ではないですか?

canonicalは「どれが正規か」という申告であって、強制力はありません。4つのURLが全部200を返す状態そのものが残るので、クロールは4回発生します。301はアクセスの時点で1本に寄せるので、そこが違います。

www有りを正規にする場合は?

向きが逆になるだけで考え方は同じです。ただし途中で向きを変えると、それまでに積み上げた評価がいったん揺れます。すでにどちらかで運用しているなら、いま検索結果に出ているほうに合わせてください。

サーバー管理画面の「HTTPSにリダイレクト」機能ではだめですか?

httpsへの強制だけならそれで足ります。ただしwww有無は別問題なので、そちらは処理されません。両方を1本で扱いたかったので、今回は.htaccessに書きました。

効果はいつ分かりますか?

クロールの配分が戻るまで時間がかかるので、2〜4週間あけてから再測定する予定です。すぐに順位が動く種類の修正ではありません。

次に読むページ