はじめに:数値の異常に気づくのが遅れる課題

「先月の売上、なんか落ちてない?」と気づいたときには、すでに2週間が過ぎていた。中小ECや個人事業主のサイト運営では、こういう「後手」がとても起きやすいです。

理由はシンプルで、毎日GA4のダッシュボードを開いて、前週比やCVRを一つひとつ見比べる時間が取れないからです。レポートは作ったきり開かなくなり、異常があっても誰も気づかない。気づいたときには売上が落ちきっている、という流れです。

この記事では、BigQuery(以下 BQ)に溜めたGA4データを Claude Code に渡して、

  1. 異常値の検知(前週比・移動平均・標準偏差でしきい値判定)
  2. 原因の仮説出し(どの流入・どのページ・どのデバイスが効いたか)

までを半自動でこなす構成と、その「プロンプト設計」を具体的に紹介します。専門のアナリストを雇わなくても、まず「異常に早く気づいて、当たりをつける」ところまでは仕組み化できる、という話です。

💡 補足 この記事は「GA4 を BigQuery にエクスポート済み」であることを前提にしています。GA4 管理画面の「BigQuery のリンク」設定は無料枠でも利用できます。設定手順の細部は変わりやすいので、最新の公式ドキュメントに従ってください。


BQ上のGA4データをClaude Codeに渡す構成

まず全体像です。難しい仕組みは必要ありません。

GA4 ──(日次エクスポート)──> BigQuery

                    Claude Code が SQL を実行

              異常値の検知 → 原因仮説の出力(ターミナル / Markdown)

Claude Code から BQ を触る方法は大きく2つあります。

  • bq コマンド(CLI)を Claude Code から実行させる:手元に bq が入っていればすぐ始められます。
  • MCP サーバー経由で BQ に接続する:クエリ実行や結果取得を Claude Code が自然言語のやり取りの中で行えます。

MCP を使った社内分析基盤の作り方は MCPでBigQueryをClaude Codeにつなぐ社内分析基盤の作り方 で詳しく扱っているので、接続まわりはそちらを参照してください。この記事では「つないだ後、異常検知に何をさせるか」に集中します。

💡 補足 いきなり全自動を目指すと事故ります。最初は「Claude Code が SQL を実行して結果を表で出す」までを手動で確認し、慣れてから定期実行(cron や Cloud Scheduler)に載せるのがおすすめです。


異常値の判定ロジックの考え方

「異常値」と一口に言っても、何をもって異常とするかを決めないと、AI も人もブレます。中小ECでまず押さえたいのは次の3つです。

1. 前週比(直近の急変を捉える)

同じ曜日同士で比べるのが基本です。GA4 の指標は曜日の影響が大きいので、「火曜 vs 火曜」で見ます。前週同曜日比で -30% を割ったら要注意、といったしきい値を置きます。

2. 移動平均(トレンドからの乖離を捉える)

7日移動平均を引いて、当日値がそこからどれだけ離れているかを見ます。単発のスパイクに振り回されず、「じわじわ落ちている」を捉えられます。

3. 標準偏差(ばらつきを基準にした判定)

過去N日(例:28日)の平均と標準偏差を計算し、当日値が 平均 ± 2σ の外に出たら異常、とします。指標ごとのばらつきの大きさを自動で考慮できるのが利点です。

これらを1本の SQL にまとめた例です。purchase イベント数(日次)を対象にしています。

-- 過去35日のpurchaseを日次集計し、移動平均・標準偏差・前週比を付与
WITH daily AS (
  SELECT
    PARSE_DATE('%Y%m%d', event_date) AS dt,
    COUNTIF(event_name = 'purchase') AS purchases
  FROM `your_project.analytics_XXXXXX.events_*`
  WHERE _TABLE_SUFFIX BETWEEN
    FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 35 DAY))
    AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
  GROUP BY dt
),
stats AS (
  SELECT
    dt,
    purchases,
    -- 7日移動平均(当日含む直近7日)
    AVG(purchases) OVER (
      ORDER BY dt ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ) AS ma7,
    -- 前週同曜日の値
    LAG(purchases, 7) OVER (ORDER BY dt) AS prev_week,
    -- 過去28日(当日除く)の平均と標準偏差
    AVG(purchases) OVER (
      ORDER BY dt ROWS BETWEEN 28 PRECEDING AND 1 PRECEDING
    ) AS avg28,
    STDDEV(purchases) OVER (
      ORDER BY dt ROWS BETWEEN 28 PRECEDING AND 1 PRECEDING
    ) AS std28
  FROM daily
)
SELECT
  dt,
  purchases,
  ROUND(ma7, 1) AS ma7,
  prev_week,
  -- 前週比(%)
  SAFE_DIVIDE(purchases - prev_week, prev_week) * 100 AS wow_pct,
  -- 平均からの乖離(何σ離れているか)
  SAFE_DIVIDE(purchases - avg28, std28) AS z_score,
  -- 異常フラグ:前週比-30%割れ または |z| >= 2
  CASE
    WHEN SAFE_DIVIDE(purchases - prev_week, prev_week) <= -0.30 THEN '前週比急落'
    WHEN ABS(SAFE_DIVIDE(purchases - avg28, std28)) >= 2 THEN '統計的外れ値'
    ELSE 'OK'
  END AS anomaly_flag
FROM stats
ORDER BY dt DESC
LIMIT 14;

purchase の部分を session_start(セッション数)や、CVR を出したいなら「セッションあたり購入」に置き換えれば、指標ごとに同じ枠組みで監視できます。

⚠️ 注意 しきい値(-30%、2σ)はあくまで出発点です。アクセスの少ないサイトでは1〜2件の変動で簡単に2σを超えてしまうため、「分母が小さい日は無視する」「平日と週末を分けて基準を持つ」といった調整が必要です。数字の少ないサイトほど、しきい値は緩めから始めましょう。


「検知→原因仮説まで」出させるプロンプト設計

SQL で「どこが異常か」までは機械的に出ます。ここからが Claude Code の出番で、「なぜ起きたかの仮説」 を出させます。コツは、丸投げせず、観点と手順を与えることです。

ステップ1:役割と前提を固定する

最初に役割・データの素性・禁止事項を明示します。これだけで出力の質が安定します。

あなたはGA4とBigQueryに詳しいWebアナリストです。
これから渡すのは、あるECサイトの日次purchaseの異常検知クエリ結果です。
- 数字はBigQuery上のGA4実データで、捏造・補完はしないこと
- データにない事象を断定しないこと(必ず「仮説」と明示する)
- 専門用語は最小限にし、店舗運営者が読んで分かる言葉で説明すること

ステップ2:観点(切り口)を渡す

「原因を考えて」だけだと曖昧な答えになります。どの軸で深掘りすべきか を渡します。

直近で anomaly_flag が 'OK' でない日について、次の観点で原因の当たりをつけてください。
1. 流入チャネル別(Organic / Paid / Direct / Referral)のどこが落ちたか
2. ランディングページ別に、特定ページの急落がないか
3. デバイス別(mobile / desktop)に偏りがないか
4. 計測側の問題の可能性(タグ不発・重複・期間欠損)はないか
それぞれについて、追加で確認すべきSQLやレポートも提案してください。

ステップ3:段階的に深掘りさせる

最初から全部の SQL を書かせず、「まず仮説 → 検証クエリ → 結果を見て絞り込み」 の順で進めます。Claude Code はファイルやコマンドを扱えるので、提案された検証 SQL をその場で実行させ、結果を踏まえて仮説を更新させる、という往復ができます。

まず観点ごとに「考えられる仮説」と「確からしさ(高/中/低)」を一覧で出してください。
次に、最も確からしい仮説を1つ選び、それを検証するSQLを実行して結果を見せてください。
結果を踏まえて、仮説を「採用 / 棄却 / 保留」に更新してください。

この「仮説 → 検証 → 更新」を回すと、たとえば「全体の購入が落ちた → チャネル別で見ると Paid だけ落ちている → 広告の配信が止まっていた可能性が高い」というところまで、人が張りつかずに当たりがつきます。広告まわりの真の費用対効果を見る話は BigQueryでGoogle広告とGA4を突き合わせてキーワードの真のROASを出す でも触れています。

💡 補足 出力フォーマットを最初に指定すると、毎回同じ形のレポートになり比較しやすくなります。「異常サマリ(1行)/仮説リスト(確からしさ付き)/推奨アクション(3つまで)」のような型を渡しておくと運用が楽です。


注意:AIの仮説は必ず検算・裏取り

ここがいちばん大事です。

⚠️ 注意 Claude Code が出す原因仮説は、あくまで「データから導いた仮説」であって事実ではありません。もっともらしい説明ほど鵜呑みにしやすいですが、必ず人間が裏を取ってください。

  • 集計クエリの期間・フィルタ・JOIN が正しいか自分の目で確認する
  • 「広告が止まっていた」なら広告管理画面で実際に止まっていたか確認する
  • 数字の急落が「実態」か「計測トラブル」かを切り分ける(GTM・タグの変更履歴を見る)
  • サンプルが少ない日の異常判定は特に疑う

AI は「データに書いていないこと」も、それらしく語ってしまうことがあります。検知のスピードは AI に任せ、意思決定の根拠になる事実確認は人間が握る。この役割分担を崩さないことが、安全に使い続けるコツです。


まとめ

  • 中小ECで起きがちな「異常への気づきの遅れ」は、BQ + Claude Code で前倒しできます。
  • 異常判定は 前週同曜日比・7日移動平均・平均±2σ の3点セットが扱いやすく、1本の SQL にまとめられます。
  • 原因仮説を出させるときは丸投げせず、役割の固定 → 観点の付与 → 仮説/検証/更新の往復 の順でプロンプトを設計します。
  • AI が出すのは「仮説」。検算と裏取りは必ず人間が行い、スピードは AI・判断は人間という分担を守ります。

まずは1指標(購入数 or セッション数)だけで小さく始めて、「異常に早く気づける」体験を一度作ってみるのがおすすめです。そこから監視対象を増やしていけば、データを見ない日があっても、異常のときだけ手元に通知が届く仕組みに育てられます。