Google Search Consoleでサイトマップが更新されない時の解決法:Last-Modifiedと304応答で改善
Google Search Console(以下 GSC)でサイトマップの読み込み日が更新されず、新しい記事がインデックスに反映されない現象が発生しました。
WordPress + OpenLiteSpeed(LiteSpeed Cacheプラグイン)環境で運用しており、親サイトマップ(sitemap.xml
)は読み込まれているものの、月別の子サイトマップ(例:sitemap-posttype-post.202508.xml
)が8月5日から更新されていない状態でした。
Bing Webmaster Tools では正常に取得されていたため、Google 側のクロール判断や更新検知に関わる条件が満たされていないと推測しました。
目的
-
GSC が子サイトマップの更新を確実に検知するようにする
-
サイトマップ読み込み日が更新され、新規ページのインデックス登録が促進される状態にする
-
将来の誤キャッシュや更新検知漏れを防ぐ
調査でわかった課題
$ curl -I https://donguri3.net/sitemap-posttype-post.202508.xml HTTP/2 200 etag: "1924cd0be2d2a478d9675f0d7d647bd6" content-type: application/xml; charset=UTF-8 x-robots-tag: noindex, follow expires: Wed, 11 Jan 1984 05:00:00 GMT cache-control: no-cache, must-revalidate, max-age=0, no-store, private, no-store link: <https://donguri3.net/wp-json/>; rel="https://api.w.org/" vary: Accept-Encoding x-litespeed-cache: hit date: Sun, 10 Aug 2025 13:40:14 GMT server: LiteSpeed alt-svc: h3=":443"; ma=2592000, h3-29=":443"; ma=2592000, h3-Q050=":443"; ma=2592000, h3-Q046=":443"; ma=2592000, h3-Q043=":443"; ma=2592000, quic=":443"; ma=2592000; v="43,46"
-
Last-Modified
ヘッダーが欠落-
Google は
Last-Modified
を更新検知の参考にしますが、WordPress の出力には含まれていませんでした。
-
-
ETagが固定化している可能性
-
LiteSpeed のキャッシュやプラグインの影響で、コンテンツが変わっても ETag が変化しない場合があります。
-
-
サイトマップがLiteSpeed Cacheの対象
-
キャッシュヒットによって古いXMLが返される恐れがありました。
-
-
If-Modified-Sinceへの対応がない
-
Googlebot が条件付きリクエストを送っても、304 Not Modified を返さず毎回200を返す状態。
→ 無駄な再取得が発生し、効率的なクロールになっていない。
-
解決策
1. サイトマップをキャッシュ除外
LiteSpeed Cache(LSCWP)のキャッシュ>除外>「URIs をキャッシュしない」に以下を追加。
/sitemap.xml /sitemap-*.xml /sitemap-posttype-*.xml /*sitemap*.xml
さらに .htaccess
または OLS の VHost Rewrite にもバイパス設定を追記し、将来キャッシュを有効にしても影響を受けないようにしました。
# --- Sitemaps を完全バイパス(将来の誤キャッシュ防止) --- RewriteCond %{REQUEST_URI} "(^/sitemap\.xml$|/sitemap-.*\.xml$|/.*sitemap.*\.xml$)" RewriteRule .* - [E=cache-control:no-cache,E=cache-disable=1]
2. Last-Modified
と 304 応答の実装
functions.php
に、子サイトマップの実データ(その月の最新更新記事)から最終更新時刻を取得し、それを Last-Modified
にセット。
さらに If-Modified-Since
と比較して同一または新しい場合は 304 Not Modified を返すようにしました。
add_action('init', function () { $req = $_SERVER['REQUEST_URI'] ?? ''; if (!preg_match('#/(wp-sitemap|sitemap).*\.xml$#', $req)) return; $lm_ts = null; if (preg_match('#/sitemap-posttype-post\.(\d{4})(\d{2})\.xml$#', $req, $m)) { $q = new WP_Query([ 'post_type' => 'post', 'post_status' => 'publish', 'date_query' => [['year' => (int)$m[1], 'month' => (int)$m[2]]], 'orderby' => 'modified', 'order' => 'DESC', 'posts_per_page' => 1, 'no_found_rows' => true, 'fields' => 'ids', ]); if (!is_wp_error($q) && !empty($q->posts)) { $lm_ts = (int) get_post_modified_time('U', true, $q->posts[0]); } wp_reset_postdata(); } if (!$lm_ts) $lm_ts = time() - 600; $lm_http = gmdate('D, d M Y H:i:s', $lm_ts) . ' GMT'; header_remove('ETag'); header('Last-Modified: ' . $lm_http, true); header('Cache-Control: no-cache, must-revalidate, max-age=0, no-store, private', true); $ims_raw = $_SERVER['HTTP_IF_MODIFIED_SINCE'] ?? ''; $ims_ts = $ims_raw ? strtotime($ims_raw) : false; if ($ims_ts !== false && $ims_ts >= $lm_ts) { status_header(304); http_response_code(304); if (php_sapi_name() === 'cgi-fcgi') header('Status: 304 Not Modified', true); header('Content-Length: 0'); exit; } }, 0);
3. 動作確認
ヘッダー確認
curl -I https://blog.example.com/sitemap-posttype-post.202508.xml
-
Last-Modified
が実際の最終更新時刻 -
ETag
なし -
Cache-Control
に no-cache 指定
304応答確認
LM="Sat, 02 Aug 2025 06:05:23 GMT" curl -I -H "If-Modified-Since: $LM" https://blog.example.com/sitemap-posttype-post.202508.xml
→ HTTP/2 304 Not Modified
結果
修正後、GSC で読み込みが止まっていた子サイトマップを再送信し、しばらくすると「成功」と表示され、最終読み込み日が更新されました。
その後、新しい記事も順調にインデックス登録されています。
まとめ
-
Last-Modified
ヘッダーは更新検知に重要 -
キャッシュ除外設定は必須(特にLiteSpeed環境)
-
304応答で無駄クロール削減&更新検知精度向上
-
GSCでの「最終読み込み日」が動かないときは、サーバ・アプリ両方のキャッシュとヘッダー周りを見直す
今回の対応で、Googleのクロールが安定し、インデックス速度も改善しました。
同じように GSC でサイトマップが更新されない方は、Last-Modified
とキャッシュ制御をチェックしてみてください。
ディスカッション
コメント一覧
まだ、コメントがありません