Claude Media
Claude CodeでGA4とSearch Consoleを突き合わせ、流入が伸びないページを探す

Claude CodeでGA4とSearch Consoleを突き合わせ、流入が伸びないページを探す

Search ConsoleとGA4のAPIをClaude Codeに叩かせ、順位は上がったのに流入が増えないページを洗い出す手順です。結合キーの正規化、期間の揃え方、順位を固定したCTRの読み方を扱います。

順位が上がったのに流入が増えないページは、2つのデータの突き合わせで見つかる

Search Consoleの平均掲載順位が改善しているのに、GA4のセッションは横ばい。この状態は片方のツールを眺めていても原因が分かりません。順位と表示回数はSearch Console、訪問後の動きはGA4が持っているからです。

取得と結合の定型作業はClaude Codeにスクリプトとして書かせ、判断は人間が握ります。流れは次の3段階です。

手順

突き合わせの流れ

  1. 1

    2つのデータを取る

    Search Consoleのページ別データと、GA4のランディングページ別データを同じ期間で取ります。

  2. 2

    URLを正規化して結合する

    両側のURLを同じ規則でパスにそろえ、結合できなかった行まで数えます。

  3. 3

    順位帯をそろえて比べる

    順位帯ごとにCTRと流入を並べ、伸びないページを型に振り分けます。

この記事のコードは、ここで使う2つのAPIの仕様に沿った骨組みです。実際のプロパティで動かすときは、認証まわりを自分の環境に合わせて足してください。

2つのAPIは何を返すのか

Search ConsoleのAPIで検索パフォーマンスを取るのは、Search Analyticsのqueryメソッドです。POST /sites/siteUrl/searchAnalytics/queryにJSONを投げると、指定したディメンションで集計した行が返ります。GA4側は、Data APIのrunReportメソッドがカスタムレポートを返します。

観点Search Console(searchAnalytics.query)GA4(Data API runReport)
主な指標Search Console(searchAnalytics.query)clicks / impressions / CTR / positionGA4(Data API runReport)sessionsなどの利用状況指標
ページを表す軸Search Console(searchAnalytics.query)page(URL)GA4(Data API runReport)landingPage(パス)
日付の基準Search Console(searchAnalytics.query)PT(UTC-7:00/8:00)GA4(Data API runReport)date(YYYYMMDD形式)。時間帯ディメンションはプロパティのタイムゾーン
1回の行数Search Console(searchAnalytics.query)rowLimitは1〜25,000、既定1,000GA4(Data API runReport)limitの既定は10,000、上限は250,000(offsetで続きを取る)
認証スコープSearch Console(searchAnalytics.query)webmasters.readonlyで読み取り可GA4(Data API runReport)analytics.readonlyで読み取り可

GA4のlandingPageは、セッション内で最初にページビューがあったページのパスです。クエリ文字列まで含めたい場合はlandingPagePlusQueryStringを使います。

Search Console側のリクエスト本文は次の形になります。

{
  "startDate": "2026-08-01",
  "endDate": "2026-08-31",
  "dimensions": ["page"],
  "rowLimit": 25000,
  "startRow": 0
}

dataStateを省略すると、確定したデータだけが返ります。allを指定すると直近の暫定データも含まれるので、前後比較の材料には向きません。

Search Console側には、取りこぼしの注意もあります。リファレンスには、APIはSearch Consoleの内部的な制限に縛られ、全行ではなく上位の行を返す場合があると書かれています。行はクリック数の降順で返ります。結合でright_onlyが出たとき、原因は正規化だけとは限りません。dateをディメンションに入れると、データのない日は行ごと省かれます。

GA4側はlandingPageをディメンション、sessionsを指標にして同じ期間を指定します。Google検索経由に絞るなら、sessionSourceとsessionMediumでフィルタをかけます。

Claude Codeに渡す前提を先に決める

突き合わせのスクリプトは、認証情報を扱います。Claude Codeに書かせる前に、読ませないファイルと使わせる権限を決めておきます。

.claude/settings.jsonには、認証情報を置いたファイルをReadのdenyルールに入れます。パス指定はRead(./.env)やRead(./secrets/**)の形です。.claudeignoreは効かないので、その中身もReadのdenyルールへ移します。

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./secrets/**)"
    ]
  }
}

サービスアカウントの鍵ファイルをsecrets/に置く運用なら、この設定でClaudeのファイルツールからは読めなくなります。GrepやGlob、@fileでの指定にも、Readルールはベストエフォートで適用されます。同じパスへのEditとWriteも止まります。スクリプト自身は環境変数やパス指定で鍵を読めばよく、Claudeがその中身を見る必要はありません。

Search Console側は、読み取り専用のスコープwebmasters.readonlyで足ります。sitemapsやsitesのメソッドで登録や削除もできてしまうので、この分析では書き込み権限を渡さない構成にします。

CLAUDE.mdには、分析ルールを短く書いておきます。次のような断片が実用的です。

## GA4とSearch Consoleの突き合わせ
- 期間はSearch Consoleの日付(PT基準)に合わせ、暫定データは含めない
- 結合前に、両側のURLを同じ規則で正規化する
- 結合できなかった行の件数と上位10件を必ず出力する
- 集計後、Search ConsoleのUIの合計クリック数と照合する

GA4に接続するMCPサーバーを使う方法もあります。ただ、突き合わせは同じ手順を毎月回すので、質問のたびに結果が揺れる形より、スクリプトに固定した方が再現できます。MCPが増えるとコンテキストを圧迫する点は、MCPのツール定義がコンテキストを圧迫する理由で扱っています。

結合キーはURLの正規化で決まる

2つのデータをつなぐキーはページのURLですが、表記が食い違います。Search Consoleのpageは完全なURL、GA4のlandingPageはパスです。ここをそろえないと、結合しても行が大量に落ちます。

正規化で決めることは4つあります。

  • スキーム(https://)とホスト名を落とし、パスだけにする
  • クエリ文字列を残すか落とすかを決める(landingPageは落ちた形、landingPagePlusQueryStringは残った形)
  • 末尾スラッシュの有無を統一する
  • 大文字小文字の扱いを決める(Search Consoleのpageフィルタは、equalsとnotEqualsのとき大文字小文字を区別し、containsなどは区別しない)

pandasでの正規化と結合は、次のように書けます。

from urllib.parse import urlparse
import pandas as pd
 
def to_path(url: str) -> str:
    p = urlparse(url)
    path = p.path or "/"
    return path.rstrip("/") or "/"
 
gsc["path"] = gsc["page"].map(to_path)
ga4["path"] = ga4["landingPage"].map(to_path)
 
# GA4側は同じパスが複数行に分かれることがあるので、先に合算する
ga4 = ga4.groupby("path", as_index=False)["sessions"].sum()
 
merged = gsc.merge(ga4, on="path", how="outer", indicator=True)
print(merged["_merge"].value_counts())

Search Consoleのリファレンスでは、ページ単位の集計は正規URI(canonical)で行われると書かれています。ヘルプでも、ページでグルーピングした表はページ単位の集計と説明されています。一方のGA4landingPageは、訪問者が実際に着地したパスです。パラメータ付きURLや別URLからcanonicalに寄せているサイトでは、片側にしかない行が出やすくなります。

indicator=Trueが肝です。left_onlyはSearch Consoleにあって、GA4のランディングページに現れなかったページです。right_onlyは、GA4にあって検索表示が無かったページを指します。この件数が目安として全体の1割を超えるなら、分析の前に正規化を疑います。データ処理の書かせ方と検証ループの組み方は、pandasのデータ処理をClaude Codeに書かせる手順にまとめています。

期間と集計単位のずれを先に潰す

Search ConsoleのAPIは、startDateとendDateをPT(UTC-7:00/8:00)で解釈します。日本時間の日付とは半日以上ずれます。日単位の細かい突き合わせをするなら、この差を織り込む必要があります。月次や週次の集計なら、影響は小さくなります。

集計単位も違います。Search Consoleの指標は、検索結果での表示とクリックです。GA4のセッションは、サイト到着後の計測です。同じ「訪問」に見えても数は一致しません。

Search Consoleのヘルプでは、表の集計が次のように分かれると説明されています。

  • クエリ・国・デバイス・日付でグルーピングした表は、プロパティ単位の集計
  • ページと検索の見え方でグルーピングした表は、ページ単位の集計

APIでもaggregationTypeがこれに対応します。pageでグルーピングやフィルタをするときはautoにします。byPropertyを指定するとエラーになります。

つまり、ページ別の数字を足し上げても、プロパティ全体の合計とは一致しません。1つのクエリに同じサイトの2ページが出ると、プロパティ単位では1回の表示でも、ページ単位では両方に1回ずつ数えられるためです。突き合わせの検算に使う合計は、必ずpageでグルーピングした同じ条件の値を使います。

直近数日は、確定前の暫定データで数字が動きます。比較期間の終わりは、数日前に置きます。

GA4側の日付も注意が要ります。hourディメンションはプロパティのタイムゾーンで報告されると書かれていますが、dateの説明はYYYYMMDD形式という点にとどまります。日単位で突き合わせるなら、プロパティ設定のレポートタイムゾーンを先に確認し、PTのSearch Consoleとのずれ幅を把握しておきます。

もう1つ、type(検索の種類)の指定でも数字が変わります。省略時の既定はwebで、DiscoverとGoogleニュースの結果は含まれません。

type対象
web対象検索の「すべて」タブ(既定。DiscoverとGoogleニュースは含まない)
image / video対象画像検索 / 動画検索
news対象検索の「ニュース」タブ
discover対象Discoverの結果
googleNews対象news.google.comとGoogleニュースアプリ

GA4の流入元の分類によっては、Discover経由のセッションも含まれることがあります。その場合、webだけを取ったSearch ConsoleのクリックがGA4のオーガニック流入より少なく見えます。原因がDiscoverなら、typeをdiscoverにして別に取ると差が説明できます。

順位を揃えて読む — 「上がったのに伸びない」の4分類

平均掲載順位は、pageごとの表ではそのURLの平均順位です。ただし、クエリが混ざった平均なので、1位のクエリと30位のクエリが混じると実態が見えなくなります。可能ならpageとqueryの2軸で取り、主要クエリを絞って見ます。

順位が上がったページは、CTRの比較を順位帯でそろえて読みます。同じ順位帯でCTRが下がっていれば、タイトルや説明文の問題を疑えます。順位が上がって表示回数も増えたのにクリックが増えないなら、その順位帯の平均CTRに届いていないだけかもしれません。

突き合わせで見つかるページは、次の4型に振り分けます。

分類

「上がったのに伸びない」の4型

  • A型: 表示は増えたがクリックが動かない

    順位上昇、表示回数増、クリック横ばい、GA4のセッションも横ばいです。まず疑うのは、タイトルや説明文が検索意図と合っていない点です。

  • B型: 表示も増えていない

    順位上昇、表示回数横ばい、セッション横ばいです。上がったクエリの検索ボリュームが小さい可能性を疑います。

  • C型: 検索側は増えたのにGA4が増えない

    Search Consoleのクリックは増え、セッションは横ばいです。結合キーのずれ、計測の欠落、期間のずれを疑います。

  • D型: 流入は増えたが到達後が悪い

    順位上昇、クリック増、セッション増のうえで、到達後の行動が悪化しています。ページ内容と検索者の期待のずれを疑います。

C型は検索側の問題ではありません。GA4のData APIには、Search ConsoleとリンクしていればorganicGoogleSearchClicksやorganicGoogleSearchImpressionsといった指標もあります。ただし、これらはSearch Consoleとの有効なリンクを前提にするので、リンクの有無から確認します。

A型とB型は、見分け方が違います。A型は表示回数が増えているので、CTRを順位帯別の基準と比べます。B型は表示回数が増えていないので、順位が上がったクエリを個別に見ます。

ここまでの判定は、あくまで疑う順序を決めるためのものです。原因を断定する材料は、この2つのデータには入っていません。

Claude Codeに検証ループを回させる

集計を書かせたら、出力を読ませて検算させます。次のようなプロンプトが、例として使えます(公式の例ではなく、この記事の手順に合わせた書き方です)。

gsc.csv(page, clicks, impressions, ctr, position)と
ga4.csv(landingPage, sessions)を、CLAUDE.mdの規則で正規化して結合して。
結合できなかった行数と上位10件を表示し、
gsc.csvのclicks合計をSearch ConsoleのUIの数字と照合できる形で出して。
そのうえで、position改善が0.5以上でsessionsの変化率が5%以内のページを一覧にして。

スクリプトが動いたら、次のコマンドで結果を確認します。

python compare.py --gsc gsc.csv --ga4 ga4.csv \
  --out candidates.csv
head -20 candidates.csv

Claude Codeには、出力の先頭行と_mergeの内訳を読ませ、想定と違えば正規化規則から見直させます。「結合できたので次へ」ではなく、落ちた行の中身を見ることが、この作業の検証です。

大きなサイトや定期実行での選び方

APIで取れる行数は、1回に最大25,000行です。それを超えるサイトは、startRowを進めながら繰り返し取ります。

ページ数が数万を超えるサイトでは、データをBigQueryに集めてSQLで結合する構成も選択肢になります。仕様の細部は、設定前にSearch ConsoleとGA4それぞれのBigQuery連携のヘルプで確認してください。BigQuery側の接続と自然言語での分析は、BigQueryをClaudeで自然言語のまま分析する手順で扱っています。

規模・頻度向く取り方理由
数百〜数千ページ、月1回向く取り方2つのAPIをスクリプトで取る理由構成が単純で、Claude Codeに書かせやすい
数万ページ以上向く取り方BigQueryでのSQL結合理由1回25,000行の制限を意識しなくてよい
都度の質問向く取り方GA4に接続するMCPサーバー理由再現性は低いが、すぐ聞ける

よくあるつまずき

  • 結合後の行数が急に減る: 末尾スラッシュや大文字小文字で、キーが合っていません。_mergeの内訳を確認します。
  • Search Consoleのクリックが、GA4のGoogleオーガニック流入より少ない: GA4側にDiscover経由が含まれている場合があります。typeをdiscoverで別に取って、差を確かめます。
  • 認証情報を誤ってClaudeに読ませた: Readのdenyルールを見直し、鍵は環境変数で渡します。

まとめ

A〜D型のどれかに振り分けると、タイトルの見直し、キーの修正、到達後の内容確認のどこから手を付けるかが決まります。

最初の1回は、_mergeの内訳とSearch ConsoleのUIの合計との照合まで済ませてください。ここが合えば、以降の月次実行はスクリプトと検証ループに任せられます。構造化データを入れたページの前後比較にも、同じ集計を使えます。実装はClaude CodeでJSON-LD構造化データを実装する手順にあります。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. developers.google.com/analytics/devguides/reporting/data/v1
  2. developers.google.com/analytics/devguides/reporting/data/v1/api-schema
  3. developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properti…
  4. developers.google.com/webmaster-tools/v1/api_reference_index
  5. developers.google.com/webmaster-tools/v1/searchanalytics/query
  6. support.google.com/webmasters/answer/7576553
  7. code.claude.com/docs/en/permissions
この記事を共有:XはてブLinkedIn