こんにちは、Shinonです。

最近、自分のポートフォリオサイト(shinotech78.com)をRenderにデプロイし、独自ドメインを設定しました。Webアプリが無事に世界に公開されてホッとしていたのですが、数日後に思わぬ問題に直面しました。

Googleで自分のサイトを検索したところ、せっかく設定した独自ドメインではなく、RenderのデフォルトURL(my-photo-portfolio.onrender.com)のほうが検索結果の上位に表示されてしまっていたのです。

今回は、この「検索結果にデフォルトURLが出てしまう問題」の原因と、Django側でスマートに解決した2つの方法についてまとめておきます。同じようにPaaSでのURL重複に悩んでいる方は、ぜひ参考にしてみてください。

 

1. なぜデフォルトURLが検索結果に出てしまうのか?

原因を調べたところ、これは「URLの正規化(カノニカライゼーション)」ができていないことが理由でした。

Renderに独自ドメインを紐づけただけの場合、サイト自体は「独自ドメイン(shinotech78.com)」と「RenderのデフォルトURL(onrender.com)」のどちらからでもアクセスできる状態になっています。

この状態を放置すると、Googleのクローラーが「中身が全く同じなのに、別のURLを持つ2つのサイトがある」と認識してしまいます。どちらの玄関を評価すべきか迷った結果、デフォルトURLのほうがインデックスされてしまうという現象が起きます。これはSEO的にも評価が分散してしまうため、早急に対策する必要があります。

 

2. 対策1:HTMLで正規URLを宣言する(カノニカルタグ)

まず手軽にできる対策として、HTMLの <head> タグ内で「こちらが本当のURLです」と検索エンジンに伝えるカノニカルタグを導入しました。

Djangoの場合、共通のテンプレートファイルである base.html などの <head> 内に以下の1行を追加します。

<link rel="canonical" href="https://shinotech78.com{{ request.path }}">

コードの解説

末尾にある {{ request.path }} がポイントです。これによって、トップページだけでなく、各ブログ記事や詳細ページなど、現在アクセスされているページのパス(例:/blog/1)を動的に取得して埋め込むことができます。

これにより、クローラーに対してページ単位で正しく独自ドメイン側が本物であることをアピールできます。

※注意点として、このテンプレート変数を使用するには、settings.pyTEMPLATES 内にある context_processors'django.template.context_processors.request' が含まれている必要があります(Djangoの標準設定では最初から有効になっていることが多いです)。

 

3. 対策2:Djangoミドルウェアで301リダイレクト(根本解決)

カノニカルタグは検索エンジンに対する「シグナル(お願い)」のようなものなので、クローラーが100%従うとは限りません。また、一般のユーザーが偶然デフォルトURLにアクセスした場合に、自動で独自ドメインに切り替わるわけでもありません。

そこで、RenderのURL(onrender.com)にアクセスがあった場合、強制的に独自ドメインへ転送する「301リダイレクト」の仕組みをDjango側に実装するのが最も確実な根本解決になります。

今回は、Djangoの「ミドルウェア(Middleware)」という仕組みを使い、リクエストがビューに到達する前の段階で一括してドメインの判定とリダイレクトを行うプログラムを作成しました。

 

【手順A】middleware.py の作成

プロジェクト内(または各アプリ内)の適切な場所に middleware.py というファイルを作成し、以下のコードを記述します。

from django.shortcuts import redirect

class CustomDomainRedirectMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        host = request.get_host()

        # ホスト名に 'onrender.com' が含まれているかを判定します
        if 'onrender.com' in host:
            # 恒久的な移転を示す301リダイレクト(permanent=True)を実行します
            return redirect('https://shinotech78.com' + request.path, permanent=True)

        return self.get_response(request)

 

【手順B】settings.py への登録

作成したミドルウェアを有効化するため、settings.pyMIDDLEWARE 設定のなるべく上のほう(リクエストを受けてすぐの段階)に追記します。

MIDDLEWARE = [
    # 自作したミドルウェアを早い段階で実行させます
    'your_app_name.middleware.CustomDomainRedirectMiddleware', 

    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # ...以下省略
]

your_app_name の部分は、実際に middleware.py を配置したアプリ名やディレクトリ名に合わせて書き換えてください

 

4. 実装後の効果

この設定を行うことで、ユーザーやクローラーが my-photo-portfolio.onrender.com/about のようなデフォルトURLにアクセスしたとしても、自動的かつ瞬時に https://shinotech78.com/about へと転送されるようになります。

301リダイレクトは「恒久的な移転」を意味するため、Googleのクローラーも「これからは独自ドメインのほうをインデックスすればいいのだな」と正しく理解し、これまでデフォルトURLが蓄積していた検索エンジンの評価(SEO評価)も新しいドメインへと綺麗に引き継がれます。

RenderなどのPaaSはインフラの管理がとても楽で便利ですが、独自ドメインを運用する際はこうしたURLの正規化が盲点になりやすいです。コード数行で実装できてSEO対策にもなるので、同じような状況で困っている方はぜひ試してみてください。