エッジ判定とスクリプト連携
トラフィックを自社サイトに置いたまま、公式 PHP パック、Cloudflare Worker、または Cloudflare Pages で判定に接続。訪問者ルールに従って通過、ページ出力、同一サイトのパスを開く、リダイレクト、またはステータスのみを返します。
訪問者が自社サイトに来たとき、公式スクリプトがプラットフォームに結果を問い合わせ、通過、ページ出力、同一サイトのパスを開く、302、またはステータスのみの返却を行います。ドメインとサイトを当社側へ移す必要はありません。
公式パックは 3 種類で、判定の動作は揃えています。サイト環境に合わせて選びます:
- PHP パック(
{name}-php.zip):従来のホスティング。サイトが PHP 8.3 のとき、サイトディレクトリへ置く。常に 1 パック。Apache / Nginx のリライト例は同じパック内 - Cloudflare Worker(
{name}-cf-worker.zip):オリジンがすでに Cloudflare にあり、Worker ルートを付けるとき - Cloudflare Pages(
{name}-cf-pages.zip):サイトが Cloudflare Pages 上のとき。_routes.jsonが必須
Worker と Pages は同一 Workers ランタイムですが掛け方が異なります。コンソールは zip を 2 つに分けてダウンロードします。同じルートに Worker と Pages ミドルウェアを付けないでください。
適用シーン
- ドメインとサイトを自社側に残したい
- 公式スクリプトで判定に接続し、自前の API 連携を書きたくない
ホスティング配信(ドメインをプラットフォームへ向ける)も従来どおり使えます。
スクリプトの選び方
| サイト環境 | 使うもの |
|---|---|
| 自社サーバーまたはレンタルで PHP 8.3 | {name}-php.zip |
| サイトがすでに Cloudflare にある(オリジン + ルート) | {name}-cf-worker.zip |
| サイトが Cloudflare Pages 上 | {name}-cf-pages.zip |
いずれも同じ判定 API(POST /v1/decision、Bearer)を呼び出します。スクリプトは実行時に PHP バージョンを検査しません。
使い方
- エッジ判定を開通し、プランを確認する
- コンソールの「エッジ連携」でルールテンプレと、通過/遮断時の動作を設定する
- 環境に合わせて公式 PHP パック、Cloudflare Worker、または Cloudflare Pages をダウンロードする(並列、どれか一方)
- 下の対応する手順でデプロイする
- 訪問者がそのサイトを開くと、スクリプトが結果に従って実行する
シーン設定
「エッジ連携」の各シーンは、キー 1 本、ルールテンプレ 1 件、動作一式に対応します。
| フィールド | 値 | 説明 |
|---|---|---|
name | 1–128 文字 | シーン名 |
rule_template_id | 必須 | アカウント内で見える広告ルールテンプレ(国、UA、IP など) |
pass_action | allow / html / redirect / path | ルール通過時の動作 |
pass_file | html のとき必須 | ファイル名のみ。例 land.html |
pass_url | redirect のとき必須 | http/https、または / で始まるサイト内パス |
pass_path | path のとき必須 | / で始まるサイト内パス |
fail_action | html / redirect / path / deny | ルール不通過時の動作 |
fail_file | html のとき必須。既定 safe.html | ファイル名のみ |
fail_url | redirect のとき必須 | pass_url と同じ |
fail_path | path のとき必須 | pass_path と同じ |
deny_status | 403 / 404 / 204 / 410。既定 404 | deny のみ |
append_query | 0 / 1。既定 1 | redirect と path で現在のクエリを付けるか |
fail_mode | html / allow。既定 html | 通信失敗や JSON を読めないとき:セーフページまたは LP |
status | normal / disabled。既定 normal | disabled のとき判定 API は 403 |
ファイル名・URL・パスの制約:
- HTML ファイル名:
^[A-Za-z0-9._-]+\.html$、最大 128。..、/、\は不可 - リダイレクト先:最大 1024。host 付きの
http/https、または/で始まるサイト内パス。//evil.com、..、バックスラッシュは不可 - サイト内パス:最大 1024。
/で始める。..、//、http、バックスラッシュ、空白は不可。?以降のクエリは可
通過/遮断の動作は保存後すぐに効きます。キー、シーン ID、fail_mode、パック内の既定 HTML ファイル名はスクリプト定数です。これらを変えたら再ダウンロードして上書きしてください。
作成またはローテーション後、PHP パック、Cloudflare Worker、Cloudflare Pages はいつでもダウンロードできます(Peek で ZIP に入れ、同じキーを繰り返し取得可能)。正式キーはローテーション時だけ変わります。ローテーションまたはシーン削除後、旧キーは直ちに無効になるため、再ダウンロードして上書きしてください。
判定リクエスト
公式スクリプトは次を送ります:
POST /v1/decision
Authorization: Bearer <シーンのキー>
Content-Type: application/json
Accept: application/jsonパックのタイムアウトは 2500 ms。本文:
| フィールド | 必須 | 制約 | スクリプトの取り方 |
|---|---|---|---|
ip | はい | 有効な IPv4 / IPv6 | CF-Connecting-IP → X-Real-IP → X-Forwarded-For の先頭 → REMOTE_ADDR |
ua | はい | 非空、最大 1024 | User-Agent |
referer | いいえ | 最大 2048 | Referer |
language | いいえ | 最大 256 | Accept-Language |
url | はい | 最大 4096。scheme と host が必要 | 現在の完全な URL(クエリ含む) |
scene_id | はい | 正の整数。キーのシーンと一致必須 | ダウンロード時に定数へ書き込む |
{
"ip": "203.0.113.10",
"ua": "Mozilla/5.0 ...",
"referer": "https://example.com/",
"language": "ja,en;q=0.8",
"url": "https://yoursite.com/",
"scene_id": 12
}scene_id がキーと一致しない、またはシーンが停止中のときは 403 です。国、ASN、プロキシなどはプラットフォームが ip などから計算します。スクリプトはお客様側で第三者 IP データベースを呼びません。
判定レスポンス
成功時は HTTP 200:
{
"code": 200,
"msg": "SUCCESS",
"data": { "action": "allow" }
}data は action によって変わります:
action | その他の data | スクリプトの動作 |
|---|---|---|
allow | (なし) | LP を出す。PHP / Cloudflare はパック内 ALLOW_HTML_FILE(既定 land.html) |
html | page:landing(通過)または safe(遮断);file:HTML ファイル名 | そのファイルを出す |
redirect | url;append_query(真偽) | http/https またはサイト内パスへ 302 |
path | path;append_query(真偽) | 同一サイトのパスを開く(アドレスバーは変わらない) |
deny | status:403 / 404 / 204 / 410 | その HTTP ステータスのみ。本文なし |
code が 200 でない、通信失敗、または JSON を読めないときは、シーンの fail_mode(html はセーフページ、allow は LP)になります。スクリプトの応答は Cache-Control: no-store です。
公開判定のよくある失敗(公式スクリプトはすべてフォールバックし、訪問者にはこれらのコードを出しません):
| HTTP | 意味 |
|---|---|
| 401 | キー欠落または無効 |
| 403 | 未開通、シーン停止、scene_id 不一致、またはアカウント利用不可 |
| 400 | リクエスト項目が不正、またはルールテンプレが無効 |
| 429 | 当日の回数切れ |
| 503 | プラットフォームが一時不通 |
PHP と Cloudflare
同じ action は揃えます。実装は実行環境に従います:
action | PHP(PHP 8.3) | Cloudflare |
|---|---|---|
html / allow | index.php と同じディレクトリのファイルを読む | ローカルディスクはないため、そのファイル名を同一オリジン GET |
path | ドキュメントルート内を include。realpath はドキュメントルート内 | 同一オリジンのパスを fetch して本文を返す |
redirect | どちらも 302。append_query は既定オン | 同左 |
deny | 対応する HTTP ステータス | 同左 |
path は / で始める必要があります。..、//、http、バックスラッシュは不可。リダイレクトに //evil.com は使えません。
コンソールでの設定
- 開通後、「エッジ連携」を開く
- 上の項目でシーンを設定する
- 公式 PHP パック、Cloudflare Worker、または Cloudflare Pages をダウンロードする
- 「判定記録」で成功・失敗を確認できる。シーン / 通過 / アクション / IP で絞り込み
ページ上部に本日の使用/残量が表示され、日次回数はプランに従います。
PHP パック
サイト側は PHP 8.3 からプラットフォームへ HTTPS で届ければ足ります。パックは実行時に PHP バージョンを検査しません。公式 PHP は常に 1 パック({name}-php.zip)です。ファイルをサイトディレクトリへ置き、実ファイル以外は index.php へ向けます。
- 公式 PHP パックをダウンロードして解凍する
- サイトディレクトリへ置く(
index.phpとページファイルを同じ階層に) - パック内の
.htaccessまたはnginx.conf.exampleで、実ファイル以外をindex.phpへ向ける。サイトルート/はindex.phpへ入ること。同じ階層にindex.htmlがあると/が静的トップになり、判定を通らないことがある - プレースホルダを実 HTML に差し替え、ファイル名はコンソールと一致させる
パックの中身:index.php(https の判定口、キー、シーン定数済み)、シーンのファイル名に合わせたプレースホルダ HTML、README.txt、.htaccess、nginx.conf.example。実ファイル(拡張子付きの静的ファイルを含む)は判定を通さずそのまま出します。LP はスクリプトが出力してください。/land.html を直接開いてルールを走らせないでください。
Cloudflare Worker
オリジンがすでに Cloudflare にあり、Worker ルートを付けるときは {name}-cf-worker.zip をダウンロードします。Pages と同一ランタイムで、収集と動作も同じです。まず CF-Connecting-IP、続けて UA、Referer、Accept-Language、完全な URL を付け、Bearer で判定 API を呼びます。Node の fs は使いません。html / path は同一オリジンからファイルを取得します。拡張子付きの静的ファイルは判定を通さずそのまま出します。
パックの中身:
worker.jswrangler.toml.exampleREADME.txt- シーンのファイル名に合わせたプレースホルダ HTML
functions/ と _routes.json は含みません。Pages ミドルウェアと同じルートに付けないでください。
- コンソールから Cloudflare Worker をダウンロードする
land.html/safe.html(またはシーンで設定したファイル名)を同一オリジンで GET できる場所へ置く- README に従い
wrangler.toml.exampleをwrangler.tomlに変え、アカウントとルートを記入する - wrangler でデプロイし、Worker をサイトのルートに紐付ける
html は同一オリジンからファイルを取得します(fetch(new URL('/' + file, request.url)))。これらのファイルがオリジンで届くことを確認してください。
Cloudflare Pages
サイトが Cloudflare Pages 上のときは {name}-cf-pages.zip をダウンロードします。functions/_middleware.js を使います(Pages Functions、Worker と同じランタイム)。公式の置き方はサイト全体のミドルウェアでサイトルートを扱います。/go のような入れ子パスだけの試験配置とは異なります。Worker と同じルートに付けないでください。
パックの中身:
functions/_middleware.js_routes.json(Pages では必須)README.txt- シーンのファイル名に合わせたプレースホルダ HTML
functions/_middleware.jsを Pages プロジェクトのfunctions/ディレクトリへ置く_routes.jsonを Pages プロジェクトのルートへ置く(functionsと同じ階層)。静的出力がpublic/の場合(Astro / Vite など)はpublic/_routes.jsonにし、公開ルートに含まれるようにする。Pages では_routes.jsonが必須land.html/safe.html(またはシーンのファイル名)をサイトルートへ置く(functionsと同じ階層)。Functions と同じ URL 接頭辞の下に置かない(例:functions/goと静的/go/*.html)。Pages が Functions を自動除外し、ミドルウェアが動きません- 既に
functions/_middleware.jsがある場合(言語リダイレクト、地域ブロックなど)、公式ファイルで丸ごと上書きしない。判定ロジックをマージするか、別パスに載せる。_routes.jsonのinclude /*は残す - Pages の手順で公開する
Pages にローカルディスクはありません。html / path の同一オリジン GET は、Pages の ASSETS を優先し、なければ同一オリジン fetch に内部ヘッダを付けて、判定へ再入しないようにします。
回数
成功した公開判定だけ当日分に計上します。枠はプラットフォーム側で集計します。枠切れや一時不通のときはフォールバックになります。
よくあるつまずき
| 現象 | 確認 |
|---|---|
| 「エッジ連携」が見えない | 開通済みか、管理者アカウントか |
| キーを替える、または漏洩を疑う | ローテーションし、再ダウンロードして上書き |
| アップロード後ずっとセーフページ | ルールの想定、プレースホルダ差し替え、ファイル名の一致 |
サイトルート / で判定が走らず静的トップのまま | index.php へのリライトがあるか。同じ階層の index.html がトップを奪っていないか |
| Worker / Pages がずっとセーフページ、または html が出ない | 同一オリジンのファイルを GET できるか、ルートがスクリプトに届いているか。Pages では HTML がサイトルートにあり、_routes.json があるか |
| Pages ミドルウェアが動かない | 公開ルートに _routes.json(include /*)があるか。LP の HTML が Functions と同じ接頭辞で自動除外されていないか。既存のルート _middleware が公式ファイルを丸ごと上書きしていないか |
| path が出ない | PHP:ドキュメントルート内か、index.php へのリライトか。Cloudflare:同一オリジンのパスを GET できるか |
| プラットフォーム不通なのに LP が出る | フォールバックが通過側(リスクあり) |