あなたのサイトマップは正しく機能していますか?
- 画像タグ対応XMLサイトマップ――WordPress標準サイトマップを置き換える理由
- コアサイトマップの不足点
- ほかのプラグインとの場所の奪い合い
- しかも、その多くが同じアドレス、/sitemap_index.xmlに自分のサイトマップを登録しようとする。これでは場所の奪い合いになる。
- robots.txtのSitemap行も自分で管理する
- この場合、Yoastを完全に削除した瞬間にその行も一緒に消え、検索エンジンが自力でサイトマップを探さなければならなくなる。
- 末尾のスラッシュ1つでサイトマップがHTMLを返した事故
- サイトマップがサイトマップではなく、ホームページのHTMLを返していたのだ。
- キャッシュが新しい記事を隠してしまう問題
- オン・オフをユーザーに委ねた理由
- SOHO SEOサイトマップ処理の結論
画像タグ対応XMLサイトマップ――WordPress標準サイトマップを置き換える理由
これまで、インデックス管理のグループを取り上げてきた。ここからはサイトマップのグループに移る。
最初に取り上げるのは、一般的なXMLサイトマップだ。WordPressには、標準で独自のサイトマップ(wp-sitemap.xml)が用意されている。
しかし私は、SOHO SEOを開発するにあたってこれを無効にし、完全に作り直した。今回は、すでに存在するものをなぜあえて置き換えたのか、そしてその過程で実際に直面した問題について話したい。

コアサイトマップの不足点
WordPressコアのサイトマップが抱える最大の問題は、画像情報を十分に含められないことだ。
コアのサイトマップに並ぶのは、URLと最終更新日ほどの情報に限られる。私は、これではDiscoverの時代には不十分だと考えている。このシリーズで繰り返し強調してきたように、Discoverは画像を中心としたチャンネルだからだ。
<image:image>タグを含むサイトマップを作った。これは、これまでの記事で取り上げてきたクロール段階の効率性の問題に直結する。
クロールバジェットは無限ではない。画像を別の経路で発見させるためにGooglebotを余計に巡回させるより、1つのサイトマップでテキストと画像の情報をまとめて伝えるほうが、はるかに効率的だ。
ほかのプラグインとの場所の奪い合い
サイトマップを独自に作ると決めた瞬間から、注意すべき問題が生じる。
WordPressサイトには、通常、複数のプラグインが同時にインストールされている。Yoast、Rank Math、All in One SEO、SEOPressといったプラグインも、それぞれ独自のサイトマップを生成する。
しかも、その多くが同じアドレス、/sitemap_index.xmlに自分のサイトマップを登録しようとする。これでは場所の奪い合いになる。
WordPressのrewriteルールは、どちらが後から登録されたかによって勝敗が決まる仕組みになっている。そのため、両方を最優先で登録したとしても、結果が常に同じになる保証はない。
私はこの問題を実際に経験した。新しい記事がサイトマップに反映されないという問い合わせがあり、原因を調べてみると、SOHO SEOのサイトマップが更新されていなかったのではなく、以前削除したつもりだった別のプラグインのサイトマップが代わりに応答していたのだ。
そこで現在は、Yoast、Rank Math、AIOSEO、SEOPressが公式に提供している「自分のサイトマップを無効にする」フィルターを、すべて明示的に呼び出している。
対象のプラグインがインストールされていなければ、これらのフィルターは何の影響も与えず、そのまま無視される。このサイトでは、SOHO SEOのサイトマップだけが唯一応答するようにしている。
robots.txtのSitemap行も自分で管理する
robots.txtには慣例として、「Sitemap: [アドレス]」という行を記載し、検索エンジンにサイトマップの場所を知らせる。
ところが私は、この行が偶然に任されているサイトを何度も見てきた。以前インストールしていたYoastが残した行が、そのまま残っているといったケースだ。
この場合、Yoastを完全に削除した瞬間にその行も一緒に消え、検索エンジンが自力でサイトマップを探さなければならなくなる。

同じ行がすでにあれば重複して追加せず、なければ新たに追加する。
末尾のスラッシュ1つでサイトマップがHTMLを返した事故
この機能を作る中で遭遇した、最も厄介なバグについて話したい。
実際に運用しているサイトで、/sitemap_index.xmlや/sitemap-posts.xmlのようなアドレスにリクエストが届くと、WordPressのカノニカルリダイレクト機能がリクエストの末尾にスラッシュを付け、301リダイレクトしてしまう現象が起きていた。
本来なら、リクエストパスにドット(.)が含まれていればファイルとして認識され、このリダイレクトは回避されるはずだ。しかし実際のサーバーでは、そう動作していなかった。
その結果、末尾にスラッシュが付いたアドレスへリダイレクトされ、そのスラッシュ付きのURLはサイトマッププラグインのrewriteルールと一致しなかったため、WordPressがそのままホームページとして処理してしまった。
何が起きたかというと、サイトマップのアドレスにアクセスしたのに、レスポンスは200、Content-Typeはtext/html、実際の内容はブログのホームページだった。
サイトマップがサイトマップではなく、ホームページのHTMLを返していたのだ。
しかし、原因を完全に特定できないからといって、手をこまねいているわけにはいかなかった。そこで、SOHO SEOのサイトマップ関連のクエリ変数がすでに認識されているリクエストについては、そもそもカノニカルリダイレクトが実行されないよう明示的に止めることにした。
原因が何であっても再発を防ぐという方法だ。私は、この種のバグこそSEOプラグインの開発で最も恐ろしいものだと思っている。
キャッシュが新しい記事を隠してしまう問題
もう1つ注意したのが、キャッシュとの衝突だ。

すでに保存されている古いコピーまで削除してくれるわけではない。実際、別のSEOプラグインからSOHO SEOに移行したサイトで、新しい記事が何本も追加された後も、古いサイトマップのコピーがそのまま表示され続けるケースがあった。
そこで、記事が公開・更新・削除されるたびに、サイトマップ関連のアドレスのキャッシュを直ちに能動的に削除するようにした。
どのキャッシュプラグインがインストールされているかを事前に知ることはできない。そのため、LiteSpeed Cache、W3 Total Cache、WP Rocketが提供するURL単位のキャッシュ削除フックを、可能な限りすべて呼び出すようにしている。対象のプラグインがなければ何も実行しない、安全な仕組みだ。
サイト全体のキャッシュを一括で削除するよりも、はるかに軽い処理で目的を達成できる。そして、これも完全ではないことを実サーバー上で改めて確認した。
オン・オフをユーザーに委ねた理由
これだけの機能を備えた上で、私は設定画面にサイトマップのオン・オフスイッチを残した。
オフにすると、SOHO SEOはサイトマップに関して本当に何も触らない。WordPressコアのサイトマップも、ほかのSEOプラグインのサイトマップもブロックせず、そのままにする。
これはRank MathやYoastと同じ動作だ。理由は明確で、すでに別のサイトマップソリューションに満足しているユーザーに、SOHO SEOのサイトマップを無理に使わせる必要はないからだ。
ただし、rewrite ruleとtemplate_redirectフック自体は、オフの状態でも登録したままにしている。実際のレンダリング段階でもう一度この設定を確認し、オフなら処理をスキップするため、これでも安全だ。
そのため、設定にかかわらずルールは常に同期的かつ即座に登録し、実際に応答するかどうかだけを設定によって分けている。
SOHO SEOサイトマップ処理の結論
画像タグを含むサイトマップは、一見すると単純な機能に見える。しかし、実際に安定して動作させるには、ほかのプラグインとの場所の奪い合い、WordPressコアによる予期せぬリダイレクト、複数のキャッシュソリューションとの衝突まで、すべてに注意を払わなければならなかった。
この過程で学んだことがある。1つの機能を「作る」ことと、「実際の運用環境で安定して動かす」ことの間には、大きな違いがあるということだ。後者のために費やした時間は、実際には前者を大きく上回った。
私自身、すでに有名なプラグインを使っていて、サイトマップにエラーが出る状況を経験した。そのプラグインだけに問題があったとは言い切れない。しかし、自分でプラグインを作る中で、システムの安全性を確保することは簡単ではない一方、決して不可能でもないと分かった。
経験を通じて、自分にとって最適なシステムを選ぶことも、1つの知恵だといえる。
次回はGoogleニュースサイトマップに移る。なぜ48時間という厳格なルールが存在するのか、そしてそれがDiscoverの鮮度シグナルにどのようにつながるのかを取り上げる予定だ。
