目次11
古いガジェットのレビュー記事に、アフィリエイトリンクを足そうとしていた。GA4ではそれらが一番見られているページで、ミニ三脚のレビューを先頭に、マウスとウォークマンのレビューが続いていた。このサイトでAmazon経由の収益を狙うなら、ここだろうと思った。
その前に国別で並べ替えてみた。1位はシンガポールで、28日で210セッションと2位以下を大きく引き離していた。ところがその210セッションのうちエンゲージしたのは1件で、滞在時間の合計は0秒だった。
Cloudflareの無料プランでは、アクセス元のネットワーク(ASN)が見えない。データセンター発だと確かめる一番手軽な方法が使えないわけだ。そこで、手元のデータだけで人かどうかを判定した手順と、ボットを外したらページの並びがどう変わったかを残しておく。
GA4に出ていた数字
GA4はシンガポールの流入を普通の訪問として記録していたが、形は人のものではなかった。直近28日、シンガポール分だけを抜き出すとこうなる。
| 指標 | シンガポール |
|---|---|
| セッション | 210 |
| エンゲージしたセッション | 1 |
| 合計エンゲージ時間 | 0秒 |
| チャネル | すべて Direct |
| 1セッションあたりのページ | 1 |
全員が初回訪問で、1ページだけ開いて去っている。session_start ≈ first_visit ≈ page_view というこの形は、AIクローラーの数字がスキャンだった件で疑うようになった形そのものだ。日本の読者は、スクロールもするし滞在もする。
ただ、エンゲージが低いだけでは人ではないとまでは言えない。開いてすぐ閉じる人は普通にいる。人間なら出さない痕跡が欲しかった。
画面サイズが同じだった
一番はっきりした手がかりはGA4の中にありました。シンガポールの210セッションのうち201件が、画面解像度 1280x1200 を報告している。
ほぼ正方形で、よくあるノートPCやスマホのどれにも当てはまらない。本物の訪問者なら解像度は何十通りにも散らばる。1つの国のほぼ全セッションが同じ珍しい値を出しているなら、それは読者層ではなく、誰かの設定値だ。
| ディメンション(シンガポール・28日) | 値 | セッション |
|---|---|---|
| 画面解像度 | 1280x1200 | 210中201 |
| ブラウザ / OS | Chrome / Windows | 210中201 |
| 市区町村 | Singapore | 210中210 |
| ランディングページ | 2021〜22年のレビュー・選び方記事 | ほぼ全部 |
プロパティ全体を 1280x1200 で絞って5月まで遡ると、最初のセッションは2026-06-18。4日で1日17件まで増え、その後は1日5〜12件で続いている。シンガポールからこの画面サイズで来たセッションは、ここまでで556件になる。同じ解像度は他の20か国ほどからも1〜2件ずつ来ていたが、これは何とも言えないので触っていない。
ASNが見えない無料プランで何が取れるか
普通なら次はアクセス元のネットワークを調べる。家庭向け回線でなくクラウド事業者からなら、それで結論が出る。ところが無料プランのゾーンでは、GraphQL Analytics APIに clientAsn を指定するとこう返ってくる。
zone '...' does not have access to the field 'clientasndescription'
無料プランでも、リクエストのUser-Agent・パス・ステータス・時間帯は取れる。そしてCloudflare Web Analyticsを入れていれば、JavaScriptを実行したクライアントしか叩かないパスが1つある。ビーコンの送信先 /cdn-cgi/rum だ。このパスをUser-Agent別に数えれば、ページのJavaScriptを実際に動かしたクライアント、つまりGA4のタグを発火させるのと同じ相手が分かる。
QUERY = """
query($zone: String!, $since: Time!, $until: Time!, $country: String!) {
viewer { zones(filter: { zoneTag: $zone }) {
httpRequestsAdaptiveGroups(
limit: 5000,
filter: {
datetime_geq: $since, datetime_lt: $until,
clientCountryName: $country,
clientRequestPath: "/cdn-cgi/rum"
}
) { count dimensions { userAgent datetimeHour } }
} }
}
"""
無料プランは1クエリにつき1日分までなので、1日ずつ7回投げて合算した。同じクエリを日本でも流して、比較対象にした。
ビーコンのChromeバージョンを日本の読者と比べる
判定を決めたのは比較対象のほうだった。/cdn-cgi/rum に届いたビーコンの7日分を並べる。
| シンガポール | 日本(比較対象) | |
|---|---|---|
| ビーコン数 | 147 | — |
| OS | 147件すべてWindows | Windows |
| Chromeのバージョン | 103〜133、メジャー版で十数種類 | 153と154 |
| ビーコンが来た時間帯(UTC) | 24時間中23時間 | 数時間に固まる |
Chromeは自動で更新される。日本の読者は153と154で、2026年10月時点の最新版だ。103のまま止まったブラウザが1台あるだけなら珍しい程度で済む。けれど、同じ都市から103・105・106・107・109・110・111・112・116・117・131・133と満遍なく散らばって来るなら、それはツールがUser-Agentをリストから選んで名乗っているということになる。
時間帯も同じことを示している。シンガポールのビーコンは24時間中23時間に届いていて、夜の落ち込みがない。人が住む都市の読まれ方ではない。
同じ7日間のシンガポールからのリクエスト845件も、残りは辻褄が合う。277件は Linux x86_64 のChrome 131で、ヘッドレスブラウザによくある既定値。154件はHuaweiのPetalBot。273件は /admin/.env や /phpinfo.php を狙ってパスルールで403になったもので、名乗りは同じく古いWindows版Chromeの使い回しだった。
どれもデータセンター発だと直接証明するものではない。そこは言い過ぎないでおきたい。ただ、画面サイズ・ブラウザのバージョン・時間帯・エンゲージの4つが同じ方向を向いていて、4つ全部を説明できる人間の行動が思いつかない。
ボットが読んでいたページ
ボットはサイト全体に散らばらず、古いレビューと選び方の記事にほぼ集中していた。同じ28日間の、ボットによるページビューを並べる。
| ページ | ボットのPV |
|---|---|
| Manfrotto PIXI EVO レビュー | 15 |
| モニターアームの選び方 | 15 |
| Logicool MX Master 3 レビュー | 14 |
| Sony NW-A105 レビュー | 11 |
| microSDカードの選び方 | 10 |
| HDMIケーブルの選び方 | 9 |
一番読まれていると思っていたページが、そのまま並んでいる。この設定を除くと、サイトで一番読まれているのはCloudflare Workersのcron記事で、ボットは一度も来ていない。レビュー記事にも本物の読者はいるが、サイトの上位だったことは一度もなかった。
アフィリエイトリンクはレビュー記事に置いたままにする。期待値は下げた。
ボットはシンガポールだけでもない。同じ週、米国からのビーコンのうち47件がChrome 122で、すべてUTCの同じ1時間に収まっていた。国で絞れば一番大きな塊は外せるが、残りがきれいになるわけではない。
変えたこと、変えなかったこと
シンガポールの遮断はしていない。数字が膨らむ以外に害は無く、混ざっていたスキャンはパスルールで止まっている。国ごと遮断すれば、現地の本物の読者まで締め出すことになる。遮断はオリジンを守る道具で、数字をきれいにする道具ではない。これはWAFで偽装UAを弾いた1か月で行き着いた切り分けと同じだ。
GA4の側では除外できない。既知のボットは自動で落としてくれるが、そのリストは見えないし追加もできない。GA4のデータフィルタは内部トラフィックと開発者トラフィック向けしか用意されていない。
なので、手当ては数字の読み方に入れた。
- セッション数ではなく
engagedSessionsを見る。このボットは210セッションでエンゲージ1件しか出していない - ページの順位を見るときは、シンガポールの
screenResolution = 1280x1200を除外する。解像度はボット側が決めている値なので、ときどき設定が変わっていないか見直す - 「一番読まれているページ」を根拠に何かを始める前に、そのビューがどこから来ているかを確かめる
3つ目は、危うく飛ばすところだった手順です。一番稼げそうに見えたページは、ほとんど1台の機械の巡回で埋まっていた。国別のレポートを10分見れば分かることでした。
FAQ
GA4にシンガポールからの直接流入が大量に出るのはなぜ?
このサイトでは読者ではなく、自動操作のブラウザでした。28日で210セッションあってエンゲージは1件、滞在は0秒。201件が同じ 1280x1200 の画面サイズで、どれも1ページだけ開いて離脱しています。シンガポールにはクラウドのデータセンターが集まっているので、そこでJavaScriptを実行するクローラーが動くと、GA4のタグが訪問者と同じように発火します。
GA4はボットを自動で除外してくれないの?
既知のボットだけです。GA4は既知のボット・スパイダーのリストに載ったトラフィックを自動で除外しますが、そのリストは見ることも追加することもできません。普通のブラウザのUser-Agentを名乗るヘッドレスChromeはリストに無いので、セッションとして記録されます。GA4のデータフィルタは内部トラフィックと開発者トラフィック(IPやパラメータで自分で定義するもの)向けで、他人のクローラーには使えません。
Cloudflareの無料プランでアクセス元のASNは見られる?
GraphQL Analytics APIでは見られません。無料プランのゾーンで httpRequestsAdaptiveGroups に clientAsn を指定すると、そのフィールドへのアクセス権が無いというauthzエラーが返ります。User-Agent・パス・ステータス・時間帯は取れるので、Web Analyticsのビーコン(/cdn-cgi/rum)を手がかりにすれば、どのUser-Agentが実際にJavaScriptを実行したかが分かります。
シンガポールをWAFで国ごと遮断したほうがいい?
遮断はしませんでした。数字が水増しされる以外に害は無く、混ざっていた認証情報スキャンは既存のパスルールで403になっています。国ごと遮断すると、シンガポールにいる本物の読者まで締め出してしまいます。そのため、数字を読む段階で除外しています。エンゲージしたセッションを見ること、ページの順位を見るときに1280x1200の設定を外すことの2つです。