GA4の既知Bot除外をすり抜ける米国のdirectセッション ─ データセンター発のヘッドレスブラウザをnavigator.webdriverで計測から外し、それでも残った話

当ページのリンクには広告が含まれています。
この記事の結論
GA4の米国セッションが急に増えていたのは、データセンターから来るヘッドレスブラウザ(画面を持たない自動操作のブラウザ)でした。GA4の既知Bot除外も管理画面のフィルタも効かなかったため、navigator.webdriver が true のブラウザでは計測そのものを始めないようにしました。ただ、修正を入れた後の約5時間でも米国のセッションは減っておらず、この判定だけでは止められないBotが残っています。

お疲れ様です!IT業界で働くアライグマです!

個人開発している技術ニュースキュレーションサービス「DevPick」のGA4を見ていたところ、米国からのセッションだけが急に増えていました。日本語中心のサービスなので海外からの閲覧は少ないはずで、増え方も不自然でした。

この記事では、そのセッションをBotと判断した根拠、GA4の設定だけでは除外できなかった理由、コードで計測を止めた方法、そして修正後もまだ残っている分を順に書きます。

目次

米国からのセッションだけが急に増えていた

1日1〜2件だった米国のセッションが、30件を超えた

DevPickの閲覧者はほとんどが日本からです。米国からのセッションは、10月中旬までは1日1〜2件で、0件の日もありました。それが10月23日に17件、10月27日には34件になっていました。

GA4のData APIで、米国のセッション数と平均セッション時間を日ごとに取り出したのが次の表です。

日付 米国のセッション 平均セッション時間
10月16日 2 約1秒
10月18日 2 約3秒
10月20日 4 約62秒
10月21日 6 約2秒
10月22日 4 約52秒
10月23日 17 約5秒
10月24日 10 約2秒
10月25日 11 約2秒
10月27日 34 約5秒

10月26日は米国からのセッションが記録されていませんでした。増え方は一直線ではなく、日によってばらつきがあります。

全体の数字を押し上げるほどの量になっていた

同じ時期のサイト全体のセッションは、1日20〜60件ほどです。10月27日は全体が64件で、そのうち34件が米国でした。半分以上が、日本語のサービスを数秒で離れていく米国からのセッションだったことになります。

この状態では、ユーザー数やセッション数が増えても、利用者が増えたのか、Botが増えたのかを区別できません。平均のエンゲージメント時間のように、全体を平均する数字も下に引っ張られます。

IT女子 アラ美
全体の半分が数秒で帰っていく米国の人って、さすがに怪しいでしょ。

ITアライグマ
はい。まずは本当にBotなのか、特徴を1つずつ確かめることにしました。

Botと判断した根拠 ─ 流入元・滞在時間・都市・画面サイズ

ほぼ全部がdirect流入の新規ユーザーで、滞在は約8秒だった

調べた時点(10月28日)の直近14日間で、米国からのセッションは101件ありました。そのうち94件は流入元が (direct) / (none) で、検索から来た google / organic は6件だけです。direct は、ブックマークやURLの直接入力のように「どこから来たか分からない」流入です。

平均滞在は約8秒で、日本からのセッションの約168秒とは大きく違います。101件のうち新規ユーザーが100件で、2回目以降の訪問は1件だけでした。直接URLを開いて数秒で離れ、二度と戻ってこない閲覧が、毎日まとまって来ていたことになります。

都市名にデータセンターの所在地が並んでいた

都市の内訳には、The Dalles、Ashburn、Boardmanが並んでいました。The DallesにはGoogleのデータセンターがあり、AshburnとBoardmanはAWSのデータセンターがある場所です。人が住んでいる街からの閲覧ではなく、クラウド上のサーバーからアクセスされていると考えるのが自然です。都市が空欄や (not set) のセッションも50件ありました。

画面サイズと時間帯も、人の閲覧らしくなかった

端末は Windows の Chrome が84件でした。画面サイズには 800×600、1280×1280、1024×1024 のような、普通のノートPCやモニターではあまり見ない値が含まれています。正方形の画面のように、人が使う端末としては不自然なものもありました。

アクセスの時間帯も、24時間に均等に散らばっていました。人の閲覧なら、住んでいる地域の昼や夜に偏るはずです。

ここまでの特徴から、このセッションは「JavaScriptを実行できるヘッドレスブラウザが、データセンターからページを開いている」ものだと判断しました。

IT女子 アラ美
都市がデータセンターだらけって、もう答え出てるようなものね。

ITアライグマ
はい。1つの特徴だけでは決めず、5つが同じ方向を指していたので判断しました。

GA4の設定だけでは除外できなかった

既知Bot除外は、JavaScriptを実行するヘッドレスブラウザを拾えない

GA4には、既知のBotやクローラーによるトラフィックを自動で除外する仕組みがあります。Googleアナリティクスのヘルプによると、判定はGoogleの調査と、IAB(Interactive Advertising Bureau)が管理する「International Spiders and Bots List」を組み合わせて行われます。この除外はオフにできず、除外された量も確認できません。

この仕組みが見ているのは、名乗り方が分かっているBotです。普通のChromeと同じようにページを開いてJavaScriptを実行し、GA4の計測タグも動かすヘッドレスブラウザは、ブラウザとしては普通の閲覧と見分けがつきません。実際、今回のセッションは除外されずにレポートに残っていました。

データフィルタには、国や都市で外す種類がなかった

次に、管理画面のデータフィルタで外せないかを確認しました。GA4のデータフィルタで作れるのは、次の3種類です。

  • デベロッパートラフィック:デバッグモードで送られたデータを外す
  • 内部トラフィック:指定したIPアドレスからのアクセスを外す
  • ウェブホスト名のトラフィック:データを送ってきたドメインで外す

国や都市を条件にしたフィルタはありません。内部トラフィックのフィルタはIPアドレスを指定して外せますが、自分や社内からのアクセスを外すためのもので、外部から来るBotのIPアドレスを把握して登録する仕組みではありません。

レポートを見るときに国や流入元で絞り込むことはできますが、それはデータを集めた後の見方の話です。集まる数字そのものは水増しされたままなので、送る側で止めることにしました。

IT女子 アラ美
公式の除外が効かないのに、オフにもできないし量も見られないのね。

ITアライグマ
はい。GA4の外側、つまりサイトのコードで送らないようにするしかありませんでした。

navigator.webdriverがtrueなら、gtagを初期化しない

navigator.webdriverは「自動操作されているか」をページに伝える値

ブラウザには navigator.webdriver という読み取り専用の値があります。MDNの説明では、ブラウザが自動操作で制御されているかどうかを示す値です。Chromeでは、--enable-automation や --headless を付けて起動したときなどに true になります。

自動操作に協力的なブラウザが「今は機械が動かしています」とページに自己申告する仕組み、と考えると分かりやすいです。この値が true のときは、GA4に何も送らないことにしました。

計測タグの初期化スクリプトの中で判定した

DevPickはNext.jsで作っていて、GA4の計測タグはNext.jsの Script コンポーネントに渡した初期化スクリプトで動かしています。navigator.webdriver はブラウザの中でしか読めないため、判定はこの初期化スクリプトの中に置きました。修正後のスクリプトを作る関数は次のとおりです。

export function gtagInitScript(gaId: string, rssLanding: boolean): string {
  const campaign = rssLanding ? ",{campaign_source:'rss',campaign_medium:'referral'}" : "";
  return `if(!navigator.webdriver){window.dataLayer=window.dataLayer||[];window.gtag=function(){dataLayer.push(arguments);};gtag('js',new Date());gtag('config','${gaId}'${campaign});}`;
}

修正前は、同じ処理を if で囲まずにそのまま書いていました。gtag('config', ...) を呼ぶとGA4はページビューを送ります。if(!navigator.webdriver) で囲んだことで、自動操作のブラウザではこの呼び出しが行われません。campaign_source の部分は、RSSから来た閲覧を見分けるための既存の処理です(経緯はRSSのutm_sourceで検索流入を誤計上しかけた話に書いています)。

gtagを定義しないことで、ほかのイベント送信もまとめて止まる

この修正では、gtag 関数の定義そのものも if の中に入れました。DevPickでは、ページビュー以外にもGA4へ送っているイベントがあります。表示速度の計測、広告枠のクリック、アプリの案内のクリックです。これらはどれも、送る前に gtag が使えるかを確かめています。

if (typeof gtag === "function") {
  // GA4へイベントを送る
}

自動操作のブラウザでは gtag が定義されないので、この判定で全部止まります。イベントごとに navigator.webdriver を確かめる処理を足す必要はありませんでした。表示速度の計測についてはNext.jsでLCP・CLS・INPをGA4に送る話で書いていて、こちらの数字もBotで汚れずに済みます。

なお、GA4のライブラリ本体(gtag/js)の読み込みは、この修正では変えていません。止めたのは初期化と送信です。

テストは3通り、E2Eには影響しなかった

単体テストでは、関数が返す初期化スクリプトの文字列をブラウザと同じように実行し、navigator.webdriver が true・false・未定義の3通りで結果を確かめています。true のときは gtag もデータの送信キューも作られないこと、false と未定義のときは従来どおり送られることを確認しました。

一方で、E2Eテストに使っているPlaywrightのブラウザも navigator.webdriver が true になります。ただ、計測を確かめるE2Eテストは window.gtag を自前の関数に差し替えて送信内容を記録する作りだったため、この修正の影響は受けませんでした。

IT女子 アラ美
gtagを定義しないだけで全部止まるのは、作りがまとまってたおかげね。

ITアライグマ
はい。送る前に必ず確かめる作りにしていたので、変更は1か所で済みました。

修正後の約5時間でも、米国のセッションは減らなかった

修正は10月28日21時14分に本番へ出た

この修正をmainにマージしたのは10月28日の21時01分で、自動デプロイが終わったのは21時14分です。本番のトップページが読み込むJavaScriptに if(!navigator.webdriver) の判定が入っていることも、配信されているファイルで確かめました。

翌朝8時過ぎにGA4のData APIで米国のセッションを分単位で取り出したところ、取得できたのは10月29日1時台までのデータでした。修正後の21時14分から1時台までに記録された米国のセッションは、次の8件です。

時刻 都市 OS・画面サイズ 流入元
21:31 The Dalles Linux・1280×1280 direct
21:47 (空欄) Windows・1366×768 direct
22:41 The Dalles Linux・1280×1280 direct
23:07 (空欄) Windows・1920×1080 direct
23:43 Elizabeth Windows・1920×1080 direct
0:22 (空欄) Windows・1920×1080 direct
0:36 Providence Mac・1512×982 検索
1:22 (空欄) Windows・1536×864 direct

前日の同じ時間帯より、むしろ多かった

前日の同じ時間帯(10月27日21時〜28日1時台)の米国のセッションは6件でした。件数で見る限り、修正の前後で減ってはいません。0時36分の検索から来たMacのセッションを除くと、残りの7件はどれも滞在が十数秒以下のdirect流入です。The Dalles・Linux・1280×1280という、修正前にも見ていた組み合わせも2件残っていました。

なぜ止まらなかったのかは、特定できていない

この7件が navigator.webdriver を false に偽装したBotなのか、そもそも true にならない方法で自動操作しているのかは、GA4のデータからは分かりません。GA4に届いているということは、少なくともこの判定を通り抜けたということです。修正を入れる時点で、webdriverを偽装するBotは残るので、レポートを見るときに国や流入元で絞って補う前提にしていました。それでも、修正前と比べて減ったと言える数字は、今のところ出ていません。

5時間分、件数にして1桁のデータなので、たまたまの揺れの可能性もあります。ただ、少なくともこの判定だけでBotの水増しが止まるとは言えない、というのが今の結果です。

IT女子 アラ美
入れた対策がまだ効いてないのを、そのまま書くのは潔いじゃない。

ITアライグマ
はい。効いたと書けるデータがまだ無いので、無いまま書いておきます。

まとめ

DevPickのGA4で急に増えた米国のセッションは、流入元・滞在時間・都市・画面サイズ・時間帯のどれを見ても、データセンターから来るヘッドレスブラウザの特徴と一致していました。GA4の既知Bot除外はJavaScriptを実行するブラウザを拾えず、データフィルタにも国や都市で外す種類がないため、GA4の設定だけでは除外できません。

そこで、navigator.webdriver が true のブラウザでは gtag の定義と初期化をしないようにしました。送信前に gtag の有無を確かめる作りにしていたので、ページビューだけでなく、表示速度やクリックのイベントもこの1か所の変更でまとめて止まります。

ただ、修正後の約5時間では米国のセッションは前日の同じ時間帯より減っておらず、同じ型のBotも残っていました。navigator.webdriver は自動操作に協力的なブラウザの自己申告なので、それを出さないBotには効きません。今の自分は、この判定を「正直に名乗る自動操作を外すための最低限の対策」と捉えています。数字を読むときは、国や流入元で絞って見ることを前提にしておくのが現実的だと考えています。

IT女子 アラ美
自己申告に頼る対策って、結局ずるいBotには効かないのよね。

ITアライグマ
はい。だからこそ、数字を見る側でも疑ってかかる前提を持っておきたいです。

運営サービス・姉妹メディア

この記事をシェアする
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

ITアライグマのアバター ITアライグマ ITエンジニア / PM

都内で働くPM兼Webエンジニア(既婚・子持ち)です。
AIで作業時間を削って実務をラクにしつつ、市場価値を高めて「高年収・自由な働き方」を手に入れるキャリア戦略を発信しています。

目次