Cloudflare WorkersのSEO
Cloudflare Workersで技術SEOを実装する方法を、fetchハンドラー、HTMLRewriterによるcanonical・hreflang・JSON-LDの注入、KVリダイレクト、Cache API・エッジキャッシュ・Cache-Controlの違い、クローキング境界、Googlebotをブロックし得るBot Fight Modeの観点から説明します。
言語
このページには証拠シグナルが1件あります
- リンクされたソースデータgooglebot.json
Cloudflare Workers SEOは、Cloudflareのサーバーレスランタイムで技術SEOを行うことです。Workerは設定済みルートに一致するリクエストだけを受け、1つのfetchハンドラーでリクエスト、レスポンスヘッダー、本文を順に書き換えます。本文の書き換えはHTMLRewriterで行い、canonical、hreflang、JSON-LDをCMSデプロイなしに注入できますが、欠落・重複・非HTMLに対して冪等でなければなりません。大量リダイレクトはKVまたはD1、小規模ならBulk Redirects/Rulesが簡単ですが、URLごとの所有者は1つにします。Workers Cache API、Cloudflareエッジキャッシュ、オリジンCache-Controlという3つのcacheを混同せず、キャッシュキー、層、TTL、無効化で診断します。厳格なルールはGooglebotとユーザーへ同じロジックを適用することです。Worker固有の大きな落とし穴は、WAFのallowルールが届かないBot Fight ModeがGooglebotをブロックすることです。変更はバージョン情報とテスト済みロールバックを記録して出荷し、GSC URL検査とCF-Cache-Statusで検証します。一般概念はEdge SEOハブを参照してください。
要点 — Cloudflare Workersは、実際のサイトの前段でCloudflareのネットワーク上で動く小さなプログラムです。ページにリダイレクトを追加したり、メタタグを修正したり、ページが通過する際にcanonicalタグを注入したりできます。CMSを変更したり、開発者を待ってサイト自体をデプロイしたりする必要はありません。これは、より広いEdge SEOの考え方を、Workersで実際にコードレベルで実装する方法を扱うページです。破ってはいけないルールは1つだけです。Workerが変更するものは、Googleにも実際の訪問者にも同じように変更しなければなりません。Googleだけに別のものを見せるのはクローキングです。
Cloudflare Workerとは、平たく言うと
Cloudflareを使うサイトでは、訪問者やGooglebotからのリクエストは実サーバーに届く前にCloudflareネットワークを通ります。Workerはその経路で実行する小さなスクリプトで、受信リクエストと返送レスポンスを変更できます。
Evidence for this claim Cloudflare Workers run code on Cloudflare's network and can inspect or modify requests and responses. Scope: Cloudflare Workers request handling. Confidence: high · Verified: Cloudflare Workers: How Workers worksSEO上の魅力は、通常は編集できないページを修正できることです。ロックされたプラットフォームや開発待ちのcanonicalタグでも、サイト自体をデプロイせずにWorkerでライブ修正できます。
SEOでWorkersを使う用途
- リダイレクト — エッジで古いURLを新しいURLへ送り、数千件にも対応します。
- タグの修正・追加 — canonical、title、hreflang、構造化データをページソースの編集なしで注入します。
- ヘッダーの書き換え —
X-Robots-Tagなどを追加・修正します。
破ってはいけないルール
Workerが行う処理は、誰に対しても同じでなければなりません。ランキング操作のために、実際の人が見るページとは異なるページをGooglebotへ見せるのはクローキングであり、Googleのルールに反します。 Evidence for this claim Google defines serving materially different content to search engines and users to manipulate rankings as cloaking and a spam-policy violation. Scope: Google Search spam policy; legitimate personalization is context-dependent. Confidence: high · Verified: Google: Spam policies — cloaking 安全なパターンは単純で、誰がリクエストしているかにかかわらず、すべてのリクエストへ同じロジックを適用します(このルールの詳しい説明はEdge SEOハブにあります。このページでは概念を理解したうえで、Cloudflare固有の実装方法を知りたい読者を想定しています)。
自分で招く2つの問題
「CloudflareがSEOを損なった」という話の多くは、Workerコード自体が原因ではありません。
- ボットブロック設定。 Bot Fight ModeがGooglebotを誤ってブロックまたはチャレンジすることがあります。Googleがページを取得できなければ、他の対策は意味を持ちません。
- キャッシュの混同。 Cloudflareには複数のキャッシュがあり、どの層を操作しているか分からないと変更が反映されないように見えます。
実際のコード、fetchハンドラー、HTMLRewriterの例、KVリダイレクト表と、キャッシュおよびボットブロックの詳細を確認するには、Advancedタブへ切り替えてください。
要点 — Cloudflare Workerは、設定されたルートに一致するリクエストだけを受け取り、1つの
fetchハンドラーで、リクエスト、レスポンスヘッダー、HTMLRewriterによるレスポンス本文を順に書き換えます。これは「canonicalを注入する」「titleを修正する」実際の仕組みであり、単に正常系が動くだけでなく、欠落、重複、非HTMLレスポンスに対して冪等であることをテストする必要があります。大量のリダイレクトは高速なキー検索のKVまたはリレーショナルなD1に置き、小規模な集合ならBulk Redirects/Rulesがより簡単です。ただし、Worker、Bulk Redirect、Redirect Rule、オリジンのリダイレクトが同じパスで発火し得るため、URLごとの所有者は1つに決めます。「cache」という語を共有するのは、Workers Cache API(caches.default)、Cloudflareエッジキャッシュ、オリジンのCache-Controlの3つです。これらを混同すると、注入したタグが表示されない原因を誤診します。キャッシュキー、層、TTL、無効化で切り分けてください。GoogleのETag/If-None-Match/304に関する指針も、レスポンスを所有するWorkerに直接適用できます。クローキングの境界は、すべてのリクエスト元へ同じロジックを実行することです。さらに、WAFルールが届かない場所でBot Fight Modeが動き、Googlebotをブロックすることがあります。SEOに影響する変更は、バージョン情報、テスト済みロールバック、停止条件を記録して出荷し、GSC URL検査とCF-Cache-Statusヘッダーで検証します。
この記事の範囲
これはEdge SEOハブの実務・コードレベルの補足です。一般定義、Workers・Akamai・Fastly・Lambda@Edge・Vercel・Netlifyの比較、SnippetsとWorkersの選択、クローキングルールの全体像はハブが扱うため、ここでは繰り返しません。このページでは、Cloudflare Workers、つまりこのサイト自身のWorkerもwrangler.tomlのrun_worker_firstを通じて使っているランタイムを、エッジコンピュートならタグを注入できるという曖昧な説明ではなく、実際のAPIで掘り下げます。
コードの前に明記すると、GoogleにはCloudflare Workers専用のSEO文書はありません。適用されるクローキング、HTTPキャッシュ、CDNクロールの公式指針は一般論であり、どのエッジ実装にも当てはまります。
Workerがリクエスト/レスポンス経路に入る場所
WorkerはV8 isolate上で動くサーバーレススクリプトです。ルーティングされたすべてのリクエストはfetchハンドラーから入ります。 Evidence for this claim A Cloudflare Worker receives HTTP requests through a fetch handler. Scope: Cloudflare Workers handlers. Confidence: high · Verified: Cloudflare Workers: Fetch handler この文で「ルーティングされた」は重要です。Workerが見るのは、設定済みのルートまたはカスタムドメイン に一致するリクエストだけで、それ以外はfetchハンドラーへ到達しません。2つのルートが同じURLに一致し得る場合は、より具体的なパターンが優先されます。したがって、特定URLでWorkerの挙動を信頼する前に、ルートが実際に一致することと、どのデプロイ済みバージョンが稼働しているかを確認してください(Wranglerの環境や段階的ロールアウトによって、実際にトラフィックを処理するバージョンがエディター上のものと違うことがあります)。ハンドラー内で行うことは、次の3つに分かれます。
- リクエストを書き換える。 オリジンへ送る前に変更します。
- レスポンスヘッダーを書き換える。 戻りの途中で変更します。
- レスポンス本文を書き換える。
HTMLRewriterを使います。
最小構成は次の形です。
export default {
async fetch(request, env, ctx) {
// 1. (optionally) inspect/modify the request
const response = await fetch(request); // hit the origin
// 2. rewrite headers
const headers = new Headers(response.headers);
headers.set("X-Robots-Tag", "index, follow");
// 3. rewrite the body with HTMLRewriter (see next section)
return new Response(response.body, { ...response, headers });
},
};SALT.agencyのチームは、リクエスト、レスポンス、本文の3つのフィルターからなるチェーンを作りました。名前は違っても同じ3段階です。
HTMLRewriterでHTMLを書き換える
HTMLRewriterはCloudflareのストリーミングHTMLパーサーで、タグを注入する仕組みの実際のAPIです。 Evidence for this claim Cloudflare HTMLRewriter provides selector-based handlers that can transform streamed HTML elements. Scope: Cloudflare Workers HTMLRewriter API. Confidence: high · Verified: Cloudflare Workers: HTMLRewriter .on(selector, handler)で要素ハンドラーを登録すると、ハンドラーからgetAttribute/setAttribute、prepend/append、setInnerContent、replaceを使えます。ストリーミング方式なので、文書全体をメモリへバッファリングする必要もありません。
canonicalタグを注入または修正する
class CanonicalHandler {
constructor(url) { this.url = url; }
element(el) { el.setAttribute("href", this.url); }
}
const rewriter = new HTMLRewriter()
.on('link[rel="canonical"]', new CanonicalHandler("https://example.com/preferred/"));
return rewriter.transform(response);ページにcanonicalがまったくない場合は、headにハンドラーを付けてappendし、既存タグを編集する代わりに追加します。どちらの方法でも、canonicalization側で説明した教訓を忘れないでください。rel=canonicalは命令ではなくヒントです。Workerでプラットフォーム全体に一貫して設定できても、最終判断はGoogleが行います。
上のCanonicalHandlerは、タグがすでに存在し、レスポンスがHTMLであることを前提にしています。本番ではどちらも保証されません。前提を誤ると、1ページにcanonicalが1つではなく2つできます。このような書き換えを出荷する前に冪等にし、次をテストしてください。
- 既存のcanonicalがない場合。 ハンドラーは欠落を検出し、
link[rel="canonical"]に一致するものがなくても何もしないのではなく、headへ1つappendする必要があります。 - 重複または不正なcanonicalがすでにある場合。 余分なタグを削除するのか、書き換えで2つ目を追加するのかを決めます。後者は実際のバグであり、例外的なケースではありません。
- 非HTMLレスポンスの場合。 APIルート、画像、リダイレクトを同じWorkerが通す場合、
HTMLRewriterを適用してはいけません。実際に確認したルートとコンテンツタイプだけに変換範囲を限定します。 - 同じレスポンスを2回処理する場合。 リトライや入れ子の
fetchでも、タグを2つ目に追加しないことを確認します。
hreflang alternateを追加または修正する
設定データを使い、ロケールごとにalternateリンクをheadへ1つ追加します。関係を持つ設定はD1、単純な対応表ならKVに置けます。リクエスト元を分岐せず、全員へ同じように注入します。(link[rel="alternate"])
JSON-LD構造化データを注入する
new HTMLRewriter().on("head", {
element(head) {
head.append(
`<script type="application/ld+json">${JSON.stringify(schema)}</script>`,
{ html: true }
);
},
});大規模運用で効くCPU制限
競合ページの「制約なしでサブミリ秒」という主張には反論したいところです。実際の上限はCPU時間で、無料プランは10 ms、有料プランは30 msです(fetchで待つ壁時計時間は数えず、CPU時間を数えます)。通常の書き換えでは気になりませんが、非常に大きなページへ重いHTMLRewriter処理を行う場合は、煽りではなく設計上の制約になります。
エッジのリダイレクト:KV、D1、Rules
リダイレクトはサーバーよりエッジに置く方を通常は好みます。オリジンの処理を減らし、ページ生成前に適用できるからです。Cloudflareでは単一・一括リダイレクト、Redirect Rules、Page Rules、KVペアを使うWorkerなど複数の選択肢があります。 出典
Workerの表形式リダイレクトには、URLをキーにする高速で結果整合性のある検索を提供するKVが自然です。
export default {
async fetch(request, env) {
const url = new URL(request.url);
const target = await env.REDIRECTS.get(url.pathname); // KV namespace
if (target) return Response.redirect(target, 301);
return fetch(request);
},
};リダイレクトがロケール別・セグメント別のSQLならD1を使います。小規模で固定的ならBulk RedirectsまたはRedirect Rulesが簡単で、50件のためにKV Workerを自作する必要はありません。 出典
特定URLの所有者は1つに決め、Workerリダイレクト、Bulk Redirect、Redirect Rule、オリジンリダイレクトを同じパスへすべて適用しないでください。これらは別々のシステムなので、同じリクエストでそれぞれ発火し得ます。複数が一致すると、きれいな1回のリダイレクトではなく優先順位をデバッグすることになります。どこかにリダイレクトを追加する前に、他のシステムが同じパスをすでに所有していないかを確認してください。照合の複雑さ(単純な1対1かパターンか)、規模、誰が監視・ロールバックするかで層を選びます。Workerリダイレクトはコードとログにあり、Bulk RedirectやRuleはダッシュボードにあり、開発者以外でも監査・復元しやすいという違いがあります。
キャッシュは3種類、名前は1つ
ここは競合ページが省きがちなセクションで、「変更を出したのに、なぜ表示されないのか」という混乱が最も起きる場所です。「cache」という語を共有する別々の層は3つあります。
- Workers Cache API —
caches.defaultとcaches.open()。コードから読み書きする、Worker単位のプログラム可能なキャッシュです。 - Cloudflareエッジキャッシュ — アセットを配信するCDNキャッシュで、Cache APIとは別物です。
- オリジンの
Cache-Control— オリジンまたはWorkerが設定するヘッダーで、上の2層とGooglebotの挙動に影響します。
3つを混同すると、実際にはpurgeしていない層から配信されているだけなのに、デプロイが失敗したと思い込みます。
変更が本当に表示されないときは、推測せず層ごとに診断します。
- キャッシュキー。 URL、ヘッダー、Cookieなど、2つのリクエストが同じキャッシュ項目に当たるかを決める属性を確認します。キャッシュキーに含まれない値で書き換えが変わると、誤ったバリアントを返します。
- どの層がレスポンスを返したか。
CF-Cache-Status(HIT/MISS/EXPIRED/DYNAMIC)を確認し、エッジキャッシュが応答したのか、Workerへ届いたのかを見ます。 - 場所と状態。 Cloudflareのキャッシュはデータセンターへ分散しているため、purgeや新しいデプロイが全エッジをすぐに無効化するとは限りません。
- TTLと設定したルール。 キャッシュルール、オリジンの
Cache-Control、Worker自身が設定したヘッダーのどれがTTLを制御しているか確認します。 - 無効化。 特定URLだけをpurgeしたのか、全消去したのか、TTLの期限切れを待ったのかを確認します。Workerが所有するCache APIの項目(
caches.default)には個別のdelete()が必要で、CDNキャッシュのpurgeでは消えません。
GooglebotがETag/If-None-Match/304をどう扱うか
Workerがレスポンスを生成または書き換えるなら、キャッシュヘッダーを所有します。つまり、Googleの2024年12月のHTTPキャッシュ指針を直接適用できます。GoogleはETag/If-None-MatchとLast-Modified/If-Modified-SinceによるヒューリスティックHTTPキャッシュをサポートし、ETag を強く推奨しています。クローラーのETagが一致した場合、サーバーは本文なしの304 Not Modifiedを返すべきです。レスポンスを生成するWorkerなら、ETagを計算しIf-None-Matchと比較して、自ら304へ短絡できます。計算量を節約し、Googlebotへ高速でキャッシュ可能な信号を返せます。
max-ageと再クロールのトレードオフ
Googleは、クローラーが特定URLをいつ再クロールするか判断しやすくするため、Cache-Control: max-ageの設定も検討するよう述べています。ただしHTMLを書き換えるWorkerでは、注入タグを変更した直後のページに長いmax-ageを設定すると、Googlebotが更新を見るまで遅れる可能性があります。書き換えたHTMLへ長いキャッシュ期間を設定して放置しないでください。
Workersに適用するクローキング境界
Workersでの厳格なルールは、すべてのリクエスト元へ同じロジックを実行することです。Googleのスパムポリシーは、ランキング操作の意図でユーザーと検索エンジンに異なる内容を提示すること をクローキングと定義し、検索エンジンからのリクエストにだけテキストやキーワードを挿入すること を具体例として挙げています。
ここで、過剰に反応しないための補足を2つ確認します。
- User-Agentの確認は自動的にクローキングではありません。 ボット通信の記録や全クライアントへの高速キャッシュは可能です。
- WorkersでURL単位のA/Bテストは可能です。 URLでユーザーを分け全リクエストに同じ扱いをするのは合法ですが、ボットと人間で分けるのは違反です。
このサイト自身のプレビューゲートは安全なパターンの実例です。Workerは、Cookieが秘密値と一致しない/preview/パスへ、Googlebotを含む全員に404を返します。ボットだけに何かを隠し、ユーザーへ別のものを見せるのではなく、1つのルールを一律に適用しているため安全です。
Workersでボットだけに事前レンダリングする方法を、きれいに構築できたとしても採用しないでください。Googleは動的レンダリングを回避策であり長期的な解決策ではない と説明しています。ボットだけに事前レンダリングするWorkerは、その非推奨パターンを引き継ぎます。
WorkerがGooglebotを誤ってブロック・遅延させる仕組み
Workersで最も固有の落とし穴ですが、通常はWorkerコード内ではありません。
Bot Fight ModeはRuleset Engineの外で動く
Bot Fight Mode(およびSuper Bot Fight Mode)は、Googlebotを含む正当なクローラーを誤検知することがあります。落とし穴は、Bot Fight ModeがWAF Ruleset Engineとは別のパイプラインで評価されることです。そのため通常のWAFの「allow」または「skip」カスタムルールでは上書きできません。Bot Fight ModeがGooglebotへチャレンジしているなら、allowルールで直すのではなく、モード自体を変更または無効化します。依存する前に、CloudflareのBot Fight Mode とSuper Bot Fight Mode の現行ドキュメントで仕組みを確認してください。ボット製品は変わります。
検証済みボットのカスタムルール
Cloudflareにはcf.client.botフィールドと検証済みボットを許可するパターン があり、カスタムルールで既知の良好なクローラーを許可できます。これはWAF側には有用ですが、前述のとおりBot Fight Modeには届きません。
CDN自体は中立からプラス
誤解のないように言うと、CloudflareというCDN自体はSEOを損ないません。Googleの2024年のCrawling December 資料は、CDNを検出するとクロール率を上げる一方、WAFやボットルールがGooglebotを誤ってブロックする可能性があり、ボット検証インタースティシャルより503の方がよいと説明しています。リスクはインフラではなく、誤設定されたWorkerまたはボット設定です。
Googlebotが実際に受け取ったものを検証する
Workerをデプロイしたら、クローラーが実際に受け取った内容を推測せず確認します。
- GSC URL検査 → ライブURLをテスト。 Googleとしてページを取得し、注入したcanonical、hreflang、JSON-LDが実際に存在するレンダリングHTMLを確認します。
- HTMLと
CF-Cache-Statusを一緒に確認。HIT/MISS/EXPIREDで、見ているのが新しいWorkerレスポンスかキャッシュかを判断します。「変更が表示されない」問題が本当はキャッシュ層の問題だと気付く最速の方法です。 - Googlebotとして直接取得。 Googlebotのユーザーエージェントでリクエストして比較します。ただし文字列が一致しても身元の証明にはなりません。Scriptsタブの手順どおり、Googleの公開範囲に対する逆引きDNSと正引きDNSで本物のGooglebotを確認します。
Workers固有のデプロイ衛生
成功したwrangler deployはスクリプトが出荷されたことを示すだけで、Googlebotが正しいレンダリング出力を受け取っているとは限りません。SEOに影響するWorker変更は、単なるpushではなく記録を伴うリリースとして扱います。
- ルートを限定する。 既定で
/*へWorkerを実行せず、wrangler.tomlの必要なパスのルートパターンに絞り、バグがサイト全体を停止させないようにします。 - 規模を約束する前に現行制限を確認する。 CPU時間、サブリクエスト数、スクリプトサイズはプランや時期で変わるため、具体的な上限を記憶に頼らずCloudflareの現行制限ページ で確認します。
- リリースのバージョン情報を記録する。 Cloudflareのバージョンとデプロイ モデルは、デプロイごとのソースバージョン、互換性日付、バインディング、ルートを追跡します。どのルートでどのバージョンが稼働しているかを記録します。
- Wrangler環境でバージョン管理とロールバックを行う。 ステージングへ出し、割合を決めて段階的に展開し、直前のバージョンへ即座に戻せる状態を維持します。
- 制限を踏まえてスコープ付きログを使う。 Workers Logs とログテーリングは段階的ロールアウトのデバッグに使えますが、ログはサンプリングされ、保持期間も限られます。捕捉したリクエストの証拠であり、すべてのクローラー訪問の完全な記録ではないと扱います。
- 停止条件を決め、必要になる前にロールバックをテストする。 エラー率、スポットチェックでの誤ったレスポンス、クロール率の低下など、何がロールアウトを止めるかを先に決め、実際にロールバックできることを確認します。
- デプロイの一部としてキャッシュをpurgeする。 3つのキャッシュ層があるため、書き換えを出荷する際の明示的な手順にキャッシュのpurge/無効化を含めます。
Bingに関する注意と、今後の1点
BingにもCloudflare/エッジ専用の指針はありません。しかしWorkerのデプロイは即時でもクロールはそうではないため、IndexNow を組み合わせ、Workerによるリダイレクト表やタグ変更を出荷した瞬間に通知して、Bingや他の参加エンジンへ早く再クロールしてもらうのが自然です。Cloudflareは「Redirects for AI Training」というエッジ強制canonical化を製品機能として提供し、切り替え1つで検証済みAIトレーニングクローラーをcanonical URLへ301します。これはWorkerでcanonicalロジックを自作する場合との有用な対比であり、クローラーへユーザーと異なるものを提供するボット条件分岐を見直す材料でもあります。
より広い背景(プラットフォーム比較、SnippetsとWorkers、開発キュー、ガバナンス)については、Edge SEOハブへ戻ってください。
AI要約
Advanced版を短くまとめると、次のとおりです。
- Cloudflare Workers SEOは、CloudflareのV8 isolateランタイムで技術SEOを行うこと。 一般的なEdge SEOの概念を、Workers固有のコードで実装します。定義、プラットフォーム比較、クローキングの詳しい説明はハブを参照してください。
- Workerが見るのはルートに一致したものだけ。 ルート/ドメイン設定と優先順位で、どのリクエストが
fetchハンドラーへ届くかが決まります。URLの挙動を信頼する前に、ルートとデプロイ済みバージョンを確認します。 - 1つの
fetchハンドラー、3段階。 リクエスト、レスポンスヘッダー、レスポンス本文を書き換えます。本文書き換えは**HTMLRewriter**で行い、canonical、hreflang、JSON-LDを注入します。冪等にし、欠落、重複、不正、非HTMLレスポンスをテストします。 - リダイレクト。 高速なキー検索はKV、リレーショナルな設定はD1、小規模な固定集合はBulk Redirects/Rulesです。エッジをサーバーより好みますが、Worker、Bulk Redirect、Rule、オリジンが同じパスで発火し得るためURLごとの所有者は1つにします。
- 3つのキャッシュ。 Workers Cache API(
caches.default)、Cloudflareエッジキャッシュ、オリジンCache-Controlを混同すると「変更が表示されない」状態になります。キャッシュキー、層、TTL、無効化で診断します。 - GoogleのETag/If-None-Match/304指針。 レスポンスを所有するWorkerは自ら304へ短絡できますが、強い
max-ageは変更ページの再クロールを遅らせます。 - クローキングルール。 すべてのリクエスト元へ同じロジックを適用します。UAをログ用に調べること自体はクローキングではなく、ランキング操作のため身元ごとに内容を変えることが問題です。
- 最大の固有リスク。 Bot Fight ModeはWAF Ruleset Engineの外で動くため、通常のallowルールは届きません。モード自体を変更します。
- 意図的に出荷する。 現行プラン制限を確認し、互換性日付・バインディング・ルートのバージョン情報を記録し、サンプリングされたスコープ付きログでロールアウトを見守り、必要になる前に停止条件とロールバックをテストします。
- 検証する。 GSC URL検査(ライブURLをテスト)と
CF-Cache-Statusヘッダーを使い、重い書き換えでは無料10 ms/有料30 msのCPU制限に注意します。
公式ドキュメント
GoogleやBingにCloudflare Workers専用のSEO文書はありません。検索エンジンのポリシーとキャッシュ、CloudflareのランタイムAPIに分かれた一次資料を確認します。
Google(どのエッジ実装にも適用)
- スパムポリシー — クローキング — Workerロジックが守るべき厳格な境界です。
- Crawling December:HTTPキャッシュ(2024) — レスポンスを所有するWorkerに直接適用できるETag/If-None-Match/304/max-ageの資料です。
- Crawling December:CDNとクロール(2024) — CDNがクロール率へ与える影響と、ボットルールがGooglebotをブロックする仕組みです。
- 動的レンダリング(非推奨) — ボットだけに事前レンダリングするWorkerが非推奨パターンを引き継ぐ理由です。
- Googleクローラーとフェッチャーの概要 — 検証用のユーザーエージェントと公開IP範囲です。
Cloudflare(ランタイム)
- HTMLRewriter — ストリーミングHTMLパーサーAPIです。
- Cache API —
caches.default/caches.open()を扱います。 - キャッシュの仕組み — Cache APIとエッジキャッシュの違いを整理します。
- ルートとドメイン — ルートの一致、優先順位、Workerを実際に起動するリクエストを説明します。
- Bulk Redirects — Workerリダイレクトと競合・重複し得るノーコードのリダイレクトシステムです。
- Workersの制限 — CPU、サブリクエスト、スクリプトサイズの現行上限です。プランと日付で変わるため直接確認します。
- バージョンとデプロイ — バージョン付き/段階的デプロイとロールバックです。
- Workers Logs — 実行ログ、テーリング、サンプリングと保持期間の制限です。
- Bot Fight Mode /Super Bot Fight Mode — Googlebotをブロックし得るボット設定です。
- 検証済みボットからの通信を許可 —
cf.client.botのカスタムルールパターンです。
Bing — エッジ/Workers専用のページはありません。デプロイ後にすぐ再クロールしてもらうには、IndexNow が関連します。
出典からの引用
記録された発言です。各Googleリンクは出典ページの引用箇所へ移動します。
Google — クローキングの境界
Google Search Centralのクローキング定義と検索エンジンだけにテキストやキーワードを挿入する例を引用します。 “Cloaking refers to the practice of presenting different content to users and search engines with the intent to manipulate search rankings and mislead users.” (翻訳)「クローキングとは、検索ランキングを操作してユーザーを誤解させる意図で、ユーザーと検索エンジンに異なる内容を提示する行為です」 “Inserting text or keywords into a page only when the user agent that is requesting the page is a search engine, not a human visitor” (翻訳)「検索エンジンであるリクエスト元にだけテキストやキーワードを挿入すること」 出典 出典
Google — HTTPキャッシュ(Crawling December、2024年)
- “Google’s crawling infrastructure supports heuristic HTTP caching as defined by the HTTP caching standard, specifically through the ETag response- and If-None-Match request header, and the Last-Modified response- and If-Modified-Since request header.” (翻訳)「Googleのクロール基盤は、HTTPキャッシュ標準で定義されたヒューリスティックHTTPキャッシュをサポートしており、具体的にはETagレスポンス/If-None-Matchリクエストヘッダーと、Last-Modifiedレスポンス/If-Modified-Sinceリクエストヘッダーを使います。」 引用へ移動
- “We strongly recommend using ETag because it’s less prone to errors and mistakes (the value is not structured unlike the Last-Modified value).” (翻訳)「ETagはLast-Modifiedの値と違って構造化されておらず、エラーやミスが起きにくいため、強く推奨します。」 引用へ移動
- “If the ETag value sent by the crawler matches the current value the server generated, your server should return an HTTP 304 (Not modified) status code with no HTTP body.” (翻訳)「クローラーが送ったETagの値がサーバーの生成した現在値と一致する場合、サーバーは本文なしのHTTP 304(Not modified)ステータスコードを返すべきです。」 引用へ移動
- “While not required, consider also setting the max-age field of the Cache-Control header to help crawlers determine when to recrawl the specific URL.” (翻訳)「必須ではありませんが、クローラーが特定URLをいつ再クロールするか判断できるよう、Cache-Controlヘッダーのmax-ageフィールドの設定も検討してください。」 引用へ移動
Google — 動的レンダリング(非推奨)
動的レンダリングが回避策であり長期解決策ではないというGoogleの説明を引用します。 “Dynamic rendering was a workaround and not a long-term solution for problems with JavaScript-generated content in search engines.” (翻訳)「動的レンダリングは回避策であり、検索エンジンにおけるJavaScript生成コンテンツの問題への長期的な解決策ではありません」 出典
私 — エッジレベルのリダイレクトについて
リダイレクトをサーバーよりエッジに置く方を好むという説明を引用します。 “I typically prefer to have redirects on the edge (CDN-level) over having them on the server.” (翻訳)「私は通常、リダイレクトをサーバーよりエッジ(CDNレベル)に置く方を好みます」 出典
Cloudflare/SALT.agency — リダイレクトにWorkersを使う理由
多くのプラットフォームで簡単なはずのリダイレクトが未対応だったという記述を引用します。 “we needed to implement simple redirects, which should be easy to create on the majority of platforms but wasn’t supported” (翻訳)「多くのプラットフォームで簡単に作れるはずの単純なリダイレクトを実装する必要がありましたが、対応されていませんでした」 出典
注:クローキングと動的レンダリングのディープリンクはEdge SEOハブでも重要です。キャッシュ引用はライブページとの完全一致を確認済みです。用途に合うツール
「リダイレクトを追加したい」
- 少数で固定的(数十件、ロジックなし)なら → Bulk RedirectsまたはRedirect Rules。Workerもコードも不要です。
- URLをキーにした数千件なら → Worker+KV検索。
- ロケール別・セグメント別でSQL検索するリレーショナルなリダイレクトなら → Worker+D1。
- 同じ処理でリダイレクトとヘッダー書き換えが必要なら → Worker(Rulesは両方を行えません)。
「タグ(canonical、hreflang、title、JSON-LD)を注入または修正したい」
- →
HTMLRewriterを使うWorker。 任意の本文書き換えに対応するCloudflareのノーコード製品はなく、これはWorkersの仕事です。
「Cloudflareを追加したらGooglebotのクロールが落ちた」
- 最初に疑うのはWorkerではなくBot Fight Mode/Super Bot Fight Modeです。Googlebotへチャレンジしているか確認し、WAFのallowルールでは直せず、モード自体を変更する必要があることを覚えておきます。
- 次にWAFカスタムルールと、ボットへ
503やインタースティシャルが返っていないかを確認します。 - それからWorkerコードとルート範囲を監査します。
「注入したタグが表示されない」
CF-Cache-Statusを確認します。HIT/EXPIREDならキャッシュされたレスポンスを見ています。正しい層(Workers Cache APIまたはエッジキャッシュ)をpurgeして再テストします。MISSでも誤っているなら、Workerロジックまたはルート範囲をGSC URL検査で確認します。
「Workerでボットだけに事前レンダリングすべきか」
- いいえ。それは動的レンダリングであり、Googleが非推奨にしています。全員へ適用するSSRまたは静的レンダリングを選んでください。
Cloudflare Workers SEOチェックリスト
書き換えWorkerを出荷する前
- ルートを
wrangler.tomlの必要なパスに限定している(反射的に/*へ適用していない)うえ、どのデプロイ済みバージョンが稼働しているか確認している。 - Workerがすべてのリクエスト元へ同じロジックを適用する(ボットと人間で内容を分岐しない)。
-
HTMLRewriterハンドラーが冪等で、欠落タグ、重複/不正な既存タグ、非HTMLレスポンスを、正常系だけでなくテストしている。 - リダイレクトに適切なツール(小規模/固定ならBulk Redirects/Rules、URLキーの大規模ならKV、リレーショナルならD1)を選び、別のリダイレクトシステムがそのURLをすでに所有していないことを確認している。
- 現行プランのCPU、サブリクエスト、スクリプトサイズ制限を記憶ではなく直接確認している。
- 書き換えたHTMLの
Cache-Controlが強すぎて、変更ページの再クロールを遅らせない。 - 互換性日付、バインディング、ルートのバージョン情報をリリースに記録し、テスト済みロールバックと停止条件を定義している。
キャッシュの確認
- 触っている層が、Workers Cache API、エッジキャッシュ、オリジンの
Cache-Controlの3つのどれか把握している。 - Workerがレスポンスを所有する場合、正しい
ETagを設定し、304へ短絡できる。 - キャッシュのpurge/無効化をデプロイの明示的な手順にしている。
ボットアクセス
- Bot Fight Mode/Super Bot Fight ModeがGooglebotへチャレンジしていない(WAFのallowルールでは上書きできないことを直接確認している)。
- WAF側で制御する場合、検証済みボットのカスタムルール(
cf.client.bot)を用意している。 - ボットを遅くする必要がある場合、検証インタースティシャルではなく
503を返す。
デプロイ後の検証
- GSC URL検査 → ライブURLをテストで、注入したタグがレンダリングHTMLにあることを確認する。
-
CF-Cache-Status(HIT/MISS/EXPIRED)を確認し、キャッシュコピーを見ているか判断する。 - リダイレクト表またはタグ変更を出荷した場合、IndexNowを送る(Bingなど)。
- Wrangler環境でバージョン管理し、ロールバック経路をテストしている。
メンタルモデル
1. 1つのハンドラー、3段階。
すべてのWorkerはfetchハンドラーであり、行う処理は順番に、リクエストの書き換え → レスポンスヘッダーの書き換え → レスポンス本文の書き換え(HTMLRewriter)の3段階のどこかにあります。コードを書く前に、何を変更するのかをこの順序で特定します。
2. 「cache」は1つではなく3つ。
Workers Cache API(caches.default)≠ Cloudflareエッジキャッシュ ≠ オリジンCache-Controlです。変更が「表示されない」ときは、コードを触る前に実際に見ている層を確認します。
3. クローキングのテスト:身元とロジックを分ける。 誰がリクエストしたかで分岐して内容を変えることはクローキングです。UAをログや速度のために調べても、全員へ同じロジックを適用するなら問題ありません。問いは「実際のユーザーがGooglebotとまったく同じものを受け取るか」です。
4. クロール低下の責任を確認する順序。 Bot Fight Mode → WAFルール → Workerコード → ルート範囲の順です。ボット設定はallowルールが届かないパイプラインで動くため、最初に疑います。
5. Workerはレスポンスを所有し、キャッシュの意味も所有する。
Workerが本文を生成または書き換えるなら、ETag、304、max-ageを管理する責任があります。自ら304へ短絡できる能力である一方、キャッシュしすぎて再クロールを遅らせる責任でもあります。
Cloudflare Workers SEO — チートシート
リダイレクトツールの選択
| 状況 | 使用するもの |
|---|---|
| 数十件の固定リダイレクト | Bulk Redirects/Redirect Rules(コード不要) |
| URLキーで数千件 | Worker+KV |
| 関係データ/ロケール別 | Worker+D1 |
| リダイレクトとヘッダー書き換えを同時に行う | Worker |
3つのキャッシュ
| 層 | 内容 | 操作場所 |
|---|---|---|
| Workers Cache API | Worker単位でプログラム可能なキャッシュ | caches.default、caches.open() |
| Cloudflareエッジキャッシュ | CDNキャッシュ | キャッシュルール/purge |
オリジンCache-Control | レスポンスヘッダー | オリジンまたはWorker |
HTMLRewriterハンドラーAPI
getAttribute/setAttribute— タグ属性(canonicalのhrefなど)を読み書きする。prepend/append— 要素内へマークアップ(headのタグなど)を追加する。setInnerContent— 要素の内容を置き換える。replace— 要素全体を置き換える。
要点
- CPU制限:無料10 ms/有料30 ms(壁時計の
fetch待ちは数えない)。 - クローキング:ランキング操作のためリクエスト元の身元で内容を変えること。WorkerがUAを読むだけではない。
- Bot Fight ModeはWAF Ruleset Engineの外で動く。 allowルールは届かないため、モードを変更する。
- Workerの変更はGSCのライブURLをテストと
CF-Cache-Statusヘッダーで確認する。 - Googleは**
ETagを推奨し、一致時は本文なしの304**を返す。
Workerデプロイ後にGooglebotが受け取った内容を確認する
Googlebotとして取得し差分を見る(シェル)
# Fetch as a normal browser
curl -sS -A "Mozilla/5.0" https://example.com/page/ -o user.html -D user.headers
# Fetch as Googlebot's UA
curl -sS -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
https://example.com/page/ -o bot.html -D bot.headers
# The bodies should be identical — a diff is a cloaking red flag
diff user.html bot.html && echo "identical (good)"
# Check what cache layer served it
grep -i "cf-cache-status" bot.headers # HIT / MISS / EXPIRED本物のGooglebotを確認する(UA文字列は簡単に偽装できる)— 逆引き+正引きDNS
# 1) Reverse DNS the IP from your logs — must end in googlebot.com / google.com
host 66.249.66.1
# 2) Forward DNS that hostname back — must resolve to the same IP
host crawl-66-249-66-1.googlebot.comどちらかの確認に失敗すればGooglebotではありません。Googleが公開するgooglebot.json の範囲と照合する方法もあります。
レンダリングHTMLから注入タグを読む(DevToolsコンソール)
// Paste into the browser console on the live page to confirm your Worker's injection
[...document.querySelectorAll('link[rel="canonical"]')].map(l => l.href);
[...document.querySelectorAll('link[rel="alternate"][hreflang]')]
.map(l => `${l.hreflang} -> ${l.href}`);
[...document.querySelectorAll('script[type="application/ld+json"]')].map(s => s.textContent);Worker内でETag/304を短絡する最小例
export default {
async fetch(request, env, ctx) {
const res = await fetch(request);
const body = await res.text();
const etag = `"${await sha1(body)}"`; // your hash of choice
if (request.headers.get("If-None-Match") === etag) {
return new Response(null, { status: 304 }); // no body, per Google's guidance
}
const headers = new Headers(res.headers);
headers.set("ETag", etag);
return new Response(body, { ...res, headers });
},
}; Workers SEOを構築・検証するツール
- Wrangler — Workersの開発、バージョン管理、デプロイ(ルート範囲、環境、ロールバック、秘密情報)を扱います。デプロイ衛生の中心です。
- HTMLRewriter — 本文を書き換える組み込みストリーミングHTMLパーサーです。
- Workers KV/D1 — リダイレクト表と設定の保存先です(KVはキー検索、D1はSQL)。
- GSC URL検査 → ライブURLをテスト — Googleとして取得・レンダリングし、canonical/hreflang/JSON-LDの注入を確認します。
CF-Cache-Statusヘッダー(curl -IまたはDevTools Network)—HIT/MISS/EXPIREDで、キャッシュコピーか新しいWorkerレスポンスかを判断します。- IndexNow — Workerによる変更を出荷した瞬間にBingなどへ通知します。
- サーバーログ分析 — 検証済みの本物のGooglebotがWorkerのルートへ到達しているかを知る根拠です。
SEO整合性とキャッシュ動作のためにWorkerを監査する
Review this Cloudflare Worker fetch handler as an SEO edge change. Trace the request,
response-header, body-rewrite, redirect, and caching paths. Return:
1. Every branch based on user agent, bot status, cookie, geography, or request header
2. Whether Googlebot/no-cookie traffic can receive different indexable content or SEO tags
3. HTMLRewriter selectors that fail when a tag is missing or create duplicates
4. Redirect lookups that can chain, loop, or fall through unexpectedly
5. Each use of the Cache API, Cloudflare edge cache behavior, and origin Cache-Control—kept as separate layers
6. Cache keys that could mix variants or preserve a stale canonical/robots/header change
7. A minimal test matrix for users, verified bots, cache hit/miss, and representative URLs
Apply the same content and SEO logic to bots and users. Flag intentional personalization
for human review rather than calling it cloaking automatically. Do not invent Cloudflare
settings, bindings, routes, cache rules, or origin behavior that are not in my input.
Worker code, bindings, routes, and relevant cache/security configuration:
[PASTE INPUT]デプロイ前にHTMLRewriter変更をレビューする
Audit this HTMLRewriter implementation for one SEO task: [CANONICAL / HREFLANG / JSON-LD].
Check whether it handles existing, missing, and duplicate elements; produces valid absolute
URLs or JSON; applies to the intended route cohort; and behaves identically for every
requester. Then return corrected code plus raw-response and rendered-response tests.
Do not add product, organization, locale, URL, or schema facts that are not supplied.
Code and expected per-route output:
[PASTE INPUT] Cloudflare Workers SEOを自分で確認する
Cloudflare Workersで技術SEOを行う際の5つの確認問題です。各問で答えを選び、最後に確認します。
時間を使う価値のあるリソース
関連する私の執筆
- リダイレクトの11種類とSEOへの影響 (Ahrefs)— Cloudflareのリダイレクト選択肢と、サーバーよりエッジを好む理由です。
- テクニカルSEO初心者向けガイド (Ahrefs)— エッジ変更が広いSEOの中でどこに位置付くかを説明します。
- JavaScript SEOの問題とベストプラクティス (Ahrefs)— エッジでの事前レンダリングを検討する場合にも関係する、レンダリング側の資料です。
私の講演
- テクニカルSEO、ページ速度、セキュリティを微調整する (Marketing Speakインタビュー)— Cloudflare Workersでユーザーがページを見る前に書き換え、リダイレクトをCDNへ移す方法を説明します。話し言葉のインタビュー記録です。具体的な言い回しは逐語引用ではなく要約として扱ってください。
業界の資料
- Cloudflare WorkersでテクニカルSEOを掘り下げる — Cloudflareブログで、リクエスト/レスポンス/本文のフィルターチェーンの起点となった記事です。
- Edge SEOとは? (Search Engine Land)— このページの親ハブが扱う概念を第三者の立場から説明します。
- Edge SEO (Dan Taylor)— Cloudflare Workersの調査をもとに用語を作った人物による記事です。
- HTMLRewriter (Cloudflareドキュメント)— 本文書き換えAPIの基準リファレンスです。
- キャッシュの仕組み (Cloudflareドキュメント)— Cache APIとエッジキャッシュの違いを整理します。
- AIトレーニング向けリダイレクト (Cloudflareブログ)— エッジでcanonical化を強制する製品機能で、Workerで自作する方法との対比になります。
さらに読む
- Edge SEO — 一般概念、プラットフォーム比較、SnippetsとWorkers、クローキングルールの全体を扱う親ハブです。
変更履歴
2026年8月22日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。
2026年8月8日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。
2026年7月18日に更新。
編集概要と記録された変更の詳細。変更の詳細
-
変更の詳細な注記は現在英語でのみ提供されています。
-
変更の詳細な注記は現在英語でのみ提供されています。
完全な比較は利用できません — この改訂の以前のスナップショットがアーカイブされていません。