https://example.com/ と https://www.example.com/ は、人から見れば同じサイトですが、URL としては別のものです。どちらでも同じページが表示される状態だと、検索エンジンには同じ内容のページが 2 つあるように見え、評価が分かれたり、検索結果にどちらが出るかが定まらなかったりします。どちらか一方を正式な URL に決め、もう一方からは 301 リダイレクトで転送してそろえておきましょう。

301 は「恒久的に移動した」ことを表す HTTP のステータスコードです。検索エンジンは、転送先の URL を正式なものとして扱います。

先に DNS とサーバーの設定を確かめる

転送を設定する前に、両方のホスト名でサーバーにたどり着けることが必要です。

  • DNS に、www 付きのホスト名のレコード (A レコードや CNAME) がある。無いと、www 付きの URL はそもそも開けず、転送もできません
  • サーバー側で、両方のホスト名が同じ公開フォルダーに結び付いている。レンタルサーバーでは、管理画面で独自ドメインを設定するときに決めることが多いです
  • HTTPS で公開するなら、SSL/TLS の証明書が両方のホスト名を含んでいる。転送は暗号化の接続が済んでから行われるため、証明書が www 付きに対応していないと、転送の前に警告の画面が出てしまいます

.htaccess の mod_rewrite で転送する

mod_rewrite は、条件に応じて URL を書き換えたり転送したりする Apache のモジュールです。基本の書き方は mod_rewrite の覚え書きの記事 も参考にしてください。

www 無しにそろえる

公開フォルダーのいちばん上に置いた .htaccess に、次のように書きます。

RewriteEngine On
# www 付きのホスト名で来た要求を、www 無しへ転送する
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
  • %{HTTP_HOST} は、ブラウザーが送ってきた Host ヘッダー (アクセス先のホスト名) です
  • [NC] は、大文字と小文字を区別しない指定です
  • ^(.*)$ でパスをまるごと取り出し、$1 として転送先に付けます。.htaccess の中では、パスは先頭の / を除いた形で照らし合わされます
  • R=301 で 301 リダイレクトにし、L でこのあとの規則を処理しないようにします

クエリ文字列 (? より後ろ) は、転送先に ? を書かなければ、そのまま引き継がれます。

ホスト名を書かずに、どのドメインでも使える形にもできます。%1 は、直前の RewriteCond の正規表現で ( ) に一致した部分です。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

www 付きにそろえる

www 付きを正式にする場合は、条件と転送先を入れ替えます。

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

どちらを正式にしても、検索エンジンの扱いに優劣はありません。大事なのは、一度決めたら変えないことです。

HTTPS への転送とまとめる

http から https への転送も行うときに、別々の規則で書くと「http の www 付き → https の www 付き → https の www 無し」と 2 回転送されることがあります。条件を [OR] でつなぐと、1 回で正式な URL に送れます。

RewriteEngine On
# http で来たとき、または www 付きで来たときは、https の www 無しへ転送する
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]

%{HTTPS} は、暗号化された接続なら on、そうでなければ off になります。ただし、レンタルサーバーによっては、暗号化の処理を手前の別の機器で行うため、%{HTTPS} がいつも off になり、転送が繰り返されることがあります。その場合は、サーバー会社の説明にある書き方 (%{HTTP:X-Forwarded-Proto} のようなヘッダーで判定するなど) に従ってください。

設定したら、curl コマンドで応答のヘッダーを見て確かめます。

curl -I http://www.example.com/about.html
# HTTP/1.1 301 Moved Permanently
# Location: https://example.com/about.html

ブラウザーは 301 の転送を覚えてしまうことがあります。試している間は R=302 (一時的な転送) にしておき、うまく動いてから R=301 に変えると、やり直しが楽です。

各ページの head 要素に正式な URL を書いておくと、検索エンジンに、どの URL を正式とみなしてほしいかを伝えられます。

<link rel="canonical" href="https://example.com/about.html">

canonical は検索エンジンへのヒントで、転送のように利用者を移動させるものではありません。転送で URL をそろえたうえで、canonical も書いておく組み合わせが確実です。

なお、サーバーの設定ファイルを編集できる環境なら、Apache の公式の資料では、mod_rewrite より、正式でないホスト名のバーチャルホストに Redirect を書く方法がもっとも良いとされています。

<VirtualHost *:80>
    ServerName www.example.com
    # パスを保ったまま、正式なホスト名へ転送する
    Redirect permanent "/" "https://example.com/"
</VirtualHost>

まとめ

  • www 付きと www 無しは別の URL として扱われるので、どちらかに決めて 301 で転送する
  • 先に、DNS のレコード、公開フォルダーの結び付け、証明書が両方のホスト名に対応しているかを確かめる
  • .htaccess では %{HTTP_HOST} を条件にして RewriteRule で転送する。HTTPS への転送は [OR] でまとめると 1 回で済む
  • 試すときは 302 で確かめてから 301 にする。canonical もあわせて書く

参考