ga-use について
ga-useは、マーケターの自然言語による依頼をGA4 Data APIレポートに変換し、結果を解釈するスキルです。Pythonスクリプトで定型的なクエリ処理を行い、イベントやフィールドに基づいて分析内容を対応付けます。
主な機能
- 01自然言語によるGA4レポート依頼
- 02イベントとパラメーターの対応付け
- 03GA4 Data APIクエリの実行
- 04結果の解釈と要約
- 05分類表とイベント実績の確認
活用シーン
- 01トラフィックやイベント指標の確認
- 02コンバージョンファネルや経路の分析
- 03パフォーマンス変化の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ ogaeng/ ga4-skill --skill ga-useインストール後、Claude Code で/ga-useを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
requirements.txtreferences/analysis-guide.mdanalysis-recipes.mdscripts/ga4_cohort.pyga4_common.pyga4_funnel.pyga4_metadata.pyga4_pivot.pyga4_query.pyga4_realtime.pyga4_reporting.py詳細
GA4 分析・クエリスキル(ga-use)
マーケターの自然言語による分析依頼に、GA4 Data API レポートで回答します。
決定的な処理は scripts/ 内の Python が行います。依頼からクエリへの
マッピングと結果の解釈は、あなたが担当します。
言語
ユーザーの言語で回答してください。ユーザーが韓国語で書いた場合は韓国語で、 英語で書いた場合は英語で回答します。これは、セットアップの案内、 進捗の報告、結果、エラーの説明など、すべての手順に適用されます。
GA4 API の識別子(eventCount、sessionSource、runReport)、
ファイル名とディレクトリ名(.ga4/token.json)、シェルコマンド、
JSON のフィールド名は翻訳しないでください。
スクリプトの出力をそのままユーザーに見せてはいけません。 スクリプトは常に英語の
error/hint 文字列を出力します。スクリプトが "ok": false を返した場合、
hint をユーザーの言語に書き換えてから表示する必要があります。英語のまま
貼り付けたり、生の JSON を表示したりしないでください。識別子、パス、
コマンドは書き換えた文章内でもそのまま維持し、周囲の説明文だけを翻訳してください。
例 — スクリプトが次を返した場合: {"ok": false, "hint": "token.json is missing. Log in first with the ga-auth skill."} 韓国語を話すユーザーには、次のように伝えます: ログイン情報(.ga4/token.json)がありません。まず ga-auth スキルでログインします。 次のようにはしないでください:「token.json is missing. Log in first with the ga-auth skill.」
インタープリターのルール
ga4_query.py、ga4_realtime.py、ga4_pivot.py、ga4_cohort.py、ga4_funnel.py、ga4_metadata.pyは、.ga4/venv/bin/pythonで実行する必要があります(google-analytics-data が必要です){SKILLS_DIR}は、これらの ga スキルがインストールされているディレクトリ、つまりこのスキルの ディレクトリの親ディレクトリです(Claude Code プロジェクトでは.claude/skills、その他のエージェントではそれぞれの場所を使用します)。 実際のパスに置き換えてください。コマンドはプロジェクトのルートから実行してください。
ステップ 0:ステータス確認(必ず最初に実施)
.ga4/ を確認し、どこから始めるかを判断します。
config.json(property_id)とtoken.jsonは存在しますか?存在しない場合は、まず ga-auth スキルで接続するようユーザーに案内してください。- ライブラリの準備はできていますか?
python3 {SKILLS_DIR}/ga-auth/scripts/ga4_status.pyのdeps_readyがfalseの場合は、このスキルが付属のdeps_fixコマンドを実行し(「この分析で必要なライブラリをインストールします」)、処理を続ける前に再確認します。マーケターに pip の実行を依頼しないでください。nullの場合は、確認自体が失敗しています。依存関係が不足していると決めつけず、そのまま続行してください。 taxonomy.mdは存在しますか?- 存在する場合は、読み込んでリクエストをイベント/パラメーターに対応付けます。
パラメーターテーブルの Query Name 列は、そのまま使用してください。
method (standard)はプレフィックスなしでmethodをクエリすることを意味し、(metric)はmetricsに含めることを意味します。また、Not registered — cannot queryはクエリしてはならず、まず登録が必要であることをユーザーに伝えてください。名前だけからcustomEvent:を推測すると、400 エラーになります。Reserved name — cannot be registered or queriedは別の扱いです。登録するよう依頼してはいけません。 GA4 は予約済みの名前とプレフィックス(user_id、session_id、google_/firebase_/ga_/_で始まるもの)を拒否するため、リクエストは拒否され、Data API を通じて値をクエリすることはできません。マーケターを管理者に案内するのではなく、その旨を明確に伝えてください。customEvent:x — prefer standard yの場合はyを使用してください。 GA4 にはそのパラメーターに対応する標準フィールドがあり、カスタム定義には登録前のデータがありません。そのため、標準フィールドで完全にカバーできる過去の期間のデータが、カスタム定義では気付かれないまま欠落します。標準フィールドで何も返されない場合に限り、customEvent:名を使用してください。 古いtaxonomy.mdファイルでは、同じ意味の韓国語ラベル(조회명= Query Name、미등록 — 조회 불가= Not registered)が残っている場合があります。ga-taxonomy でシートを再解析すると、英語ラベルに更新されます。 - タクソノミーシートに記載されているのは、実際に起きたことではなく、起きるはずのことです。 対応付けたイベントを基に分析を行う前に、リクエストされた期間に実際に何回発生したかを確認してください(
eventName×eventCountのクエリを 1 回実行すれば十分です)。実際には、タクソノミーの 31 項目中 14 項目は直近 30 日間にヒットがなく、90 日間に広げても 1 桁のままの項目もありました。このことを把握せずにファネルを作成すると、「3 件中 1 件が完了 → 完了率 33%」のような意味のない数値を自信ありげに報告することになります。サンプル数が少ない場合は、割合ではなく 実数を報告し、その旨を伝えてください。 - 存在しない場合は、分析の前にイベントの全体像を調べます。
eventName×eventCount/activeUsersをlimit50 以上でクエリし、このプロパティにあるイベントを確認してから、リクエストを対応付けてください。応答にtruncated: trueが含まれる場合は、limit を引き上げて再度クエリしてください(イベントの欠落は、主要な行動そのものを見落としていることを意味する場合があります)。
- 存在する場合は、読み込んでリクエストをイベント/パラメーターに対応付けます。
パラメーターテーブルの Query Name 列は、そのまま使用してください。
custom_definitions.jsonは存在しますか?(ga-taxonomy によって作成されます)- 存在する場合は読み込みます。タクソノミーのパラメーターを実際のクエリ名(
customEvent:...)と単位に変換する際に使用してください。詳細はreferences/analysis-guide.mdの「Custom Definitions」セクションを参照してください。 - 存在しない場合は、
ga4_metadata.py get-metadataの結果からcustomEvent:、customUser:、customItem:で始まる項目を探し、同じように使用できます。
- 存在する場合は読み込みます。タクソノミーのパラメーターを実際のクエリ名(
プラットフォームのコンテキスト
ステータスチェックでは platforms が報告されます。これは、このプロパティがデータを収集しているプラットフォームを、GA4 独自の表記(web、iOS、Android、または unknown)で示します。存在するイベントやディメンションそのものが変わるため、何かが欠けていると結論づける前に確認してください。
nullは、まだ一度も参照されていないことを意味します。プラットフォームを推測しないでください。 推測を防ぐためにこのフィールドがあります。.ga4/venv/bin/python {SKILLS_DIR}/ga-auth/scripts/ga4_admin.py get-property <PROPERTY_ID> を再実行し、ga-auth スキルの Step 4 の項目 4 と 5 を通じて保存してください。保存時にconfig.jsonは一から再構築されるため、同じコマンドで通貨、タイムゾーン、保持期間も再度渡さないとnullになります。その結果、ga-use はレポートする収益の通貨を取得できなくなります(リアルタイムのレスポンスにはメタデータがまったく含まれません)。また、ファネルが空であることを確認する際に使う保持期間の値も失われます。[]は、プロパティにデータストリームがなく、何も収集していないことを意味します。unknownの項目は、ストリームを分類できなかったことを意味するため、このリストだけでは完全な回答になりません。unknownがある場合にwebがないことを「アプリのみ」と解釈しないでください。そのプロパティを分類できなかったと伝え、ウェブのみ、またはアプリのみと判断しないでください。platforms_age_daysが 180 を超える場合、その後チームが追加したプラットフォームがリストに反映されていない可能性があります。これを根拠にする前に再確認してください。platformsは設定済みのストリームを示します。一方、platformディメンションは、実際に到達したトラフィックを示します。設定済みのストリームでもデータがゼロの場合があるため、両者を混同して述べないでください。
分析の流れ
- 必要な分析内容(指標、期間、内訳ディメンション、フィルター)を確認します。
- 複合的な質問の場合(レシピにある質問の種類、つまりコンバージョン分析、経路/ジャーニー、パフォーマンスの概要、変化の診断、コンテンツのパフォーマンス、行動上の重要度の比較に該当する場合)は、まず
references/analysis-recipes.mdを読み、クエリを計画します(何を、なぜ、どのように組み合わせるか)。 対象件数が少ない可能性がある分析(コンバージョン、セグメント)では、まず規模を確認し、references/analysis-recipes.mdのサンプルサイズの基準に従って分析の深さを決めます。 - 依頼内容を実際のイベント名/パラメーター名に対応づけます。Step 0 で収集した情報(
taxonomy.md、または該当するものがなければ照会したイベント一覧)を使用します。 - ディメンション/指標が不明確な場合は、メタデータを照会します。
--searchで対象を絞り込んでください:
1 つのプロパティには約 400 個のディメンションと約 120 個の指標があるため、絞り込まずに出力すると約 12k トークンになります。一方、.ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_metadata.py get-metadata --search item--searchで単一フィールドを検索すると約 150 トークンです。--searchは繰り返し指定でき(いずれかの検索語句に一致する項目が保持されます)、API 名または UI 名が検索対象になります。--kind dimension|metricを指定すると、もう一方の一覧が除外されます。絞り込み後のレスポンスには、絞り込む前の合計数を含むfilteredキーが付与されます。このキーがある場合、カタログ全体を見ているわけではありません。 - 拡張 JSON 仕様を作成してクエリを実行します(形式は
references/analysis-guide.mdを参照):echo '<request JSON>' | .ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_query.py - 結果を表または要約にまとめて回答します。結果が空の場合やエラーが発生した場合は、
references/analysis-recipes.mdの再試行ループに従って対処します。truncatedが true の場合、表示されたのは上位の一部だけです。「合計」として説明しないでください。limitを増やして再度クエリを実行するか、「上位 N 件に基づく」と明記します。ファネル結果にsteps_without_dataがある場合、そのステップはレスポンスに行がありませんでした(GA4 では到達数がゼロのステップは省略されるため、通常はゼロを意味しますが、決めつけず、そのまま伝えてください)。
作業原則(重要)
対象読者は技術に詳しくないマーケターです。
- 作業を小さなステップに分け、各ステップで「何を/なぜ」を一行で説明します。
- 可能な限り、ファイルの配置とコマンドの実行は自分で行います。
- 自然言語を JSON 仕様に変換するのは Claude の役割です。マーケターに JSON を求めないでください。
よくあるリクエストパターン
-
上位N件:
order_bys(降順)+limit。例:イベント数の上位10件。(ピボットは軸ごとに指定するため、pivots[].order_bys/pivots[].limitに設定します。) -
dimensionによる並べ替えでは、数値順やカレンダー順ではなく、GA4 の辞書順が使われます。hour/minuteはゼロ埋めされないため、このスクリプトはこの2つに対して NUMERIC の順序タイプを自動的に要求します。対応は不要です。dayOfWeekNameとappVersionも同じ問題がありますが、サーバー側での解決方法はありません(それぞれテキストと複数部分からなる文字列であり、NUMERIC の順序タイプも役に立ちません。どちらも実測済みです)。そのため、代わりにnoteで警告します。dayOfWeekNameの場合は、dayOfWeek(0=日曜日~6=土曜日)で並べ替え、表示には名前を使ってください。appVersionの場合、代替となるディメンションはありません。各バージョンのドット区切りの部分を整数として解析し、返された行を独自に並べ替えてください。その他の数値に見えるディメンション(カスタムのものを含む)でも同じ問題が起こる可能性があります。安全な項目の全一覧はreferences/analysis-guide.mdを参照してください。 -
合計を得るために行を合算しないでください。
~Usersで終わる指標とsessionsは重複排除された値です。ディメンションごとの行を合算すると、実際の合計を上回ります(ライブプロパティでの実測では、1か月分のactiveUsersを日別に合算した値は、真の合計を13%上回りました)。レートと平均値は別の理由で合算できません。重複排除された値ではなく、行をまたいで合計・平均を計算すること自体が無効です。レスポンスにnon_additive_metrics/noteが含まれている場合はこのルールが適用されます。そのnoteでは、すべての指標を重複排除のせいにするのではなく、指標ごとに該当する理由を説明します。合計が必要な場合は、同じ期間を指定して、dimensionsなしでもう一度クエリしてください。eventCountのようなカウント型の指標は安全に合算できます。 -
totalUsersとactiveUsersは同じ意味ではありません。totalUsersはイベントを記録したすべてのユーザーを数えますが、activeUsersにはエンゲージメントを示すシグナルが必要なため、一般に両者は異なります(ライブでの実測では、同じ期間で99対124となり、25%の差がありました)。GA4 独自の*PerUser指標(sessionsPerUserなど)はtotalUsersではなくactiveUsersで割ります。totalUsersを使って手計算した「ユーザーあたり」の値のほうが正確だと考えないでください。GA4 がすでに提供している指標を使うか、手計算で割る必要がある場合はactiveUsersを使ってください。 -
dauPerMau/dauPerWau/wauPerMauは、前述の「ディメンションなしなら安全に合計できる」というルールの例外です。 これらは日ごとに移動する比率であり、1日を超える期間では、GA4 が集計したディメンションなしの値は期間比率ではなく、日別の値の合計になります(ライブでの実測ではそのとおりでした。6日間のクエリのディメンションなしの合計は、同じ日数分を手計算で合算した結果と倍精度まで一致しました)。レスポンスにこれらのいずれかを示す note が含まれている場合は、1日分だけをリクエストするか、dateで分けて各日を個別に確認してください。 -
収益ベースの式指標は、比率ではなく元の収益値を返すことがあります。
totalRevenue/eventCount(平均注文額)のような式を単独で要求すると、totalRevenueもmetricsに含めない限り、totalRevenue自体が返されます(ライブでの実測では、収益指標が含まれた場合にのみ GA4 が式を評価します)。レスポンスにexpression_revenue_operandsが含まれている場合は、その収益指標を追加して再クエリしてください。大きな合計値のように見える「比率」は、この問題に該当します。収益以外の指標を使う式(eventCount/sessions)には影響しません。自動チェックの対象はRevenueで終わる指標だけです。その他の金額指標(itemRefundAmount、advertiserAdCost)にはフラグが付かないため、式と一緒に要求してください。 -
収益を示すときは、必ず通貨も明記してください。 レスポンスの
metadata.currency_codeは、そのプロパティのレポート通貨です。国や話している言語から通貨を推測しないでください。Asia/Seoulタイムゾーンのライブプロパティが USD でレポートする場合、数値をウォンとして読むと約1300倍の誤差になりますが、レスポンス内のほかの情報からは判別できません。metadata.time_zoneはプロパティのタイムゾーンであり、「今日」の基準となります。 -
metadataに、数値を引用できない理由が示されている場合があります。sampling: trueは一部のデータに基づく推定値であることを示します。その旨を伝え、小さな差を実際の差として扱わないでください。subject_to_thresholding: trueは、プライバシー保護のために GA4 が行を除外したことを示すため、合計は下限値です。data_loss_from_other_row: trueは、値が(other)にまとめられ、内訳の一部が不明なまま失われたことを示します。 -
サンプリングされた式は、元のオペランドの値を損なうことがあります。 サンプリングされたレスポンスに
expression_sampling_overlapが含まれている場合、式の中と生の値の両方で要求されたイベントスコープの収益指標(totalRevenue、purchaseRevenue。例:totalRevenue/eventCount)は、真の合計を大幅に下回る値になりました(約13倍のずれを実測)。このレスポンスの生の値の列は引用しないでください。式を使わずに再クエリするか、サンプリングが発生しないようクエリの範囲を絞ってください。(アイテムスコープのitemRevenueとカウント指標にはずれがなく、フラグも付きません。) -
日別(または月別)の系列では、行が欠けていることがあります。 要求したすべての指標が0の行は GA4 によって省略されるため、
dateごとの収益クエリでは売上がゼロの日が表示されません。同様に、1つ上の粒度であるyearMonthの内訳でも起こります(ライブでの実測では、12か月分のサブスクリプション収益クエリで12か月中4か月だけが返されました)。レスポンスにmissing_datesが含まれている場合、該当する行はデータの欠落ではなく実際に0です。平均を計算するときは含めてください(返された行だけで割ると高くなります)。また、トレンドラインがその日を飛ばしてつながらないようにしてください。 -
(not set)はカテゴリではありません。 レスポンスにunset_dimensionsが含まれている場合、GA4 は該当する行の値を受け取っていません。これを最上位の項目として報告しないでください。ライブプロパティで「収益別のクーポン上位」を調べると(not set)が1位になることがありますが、これは「クーポンが使用されなかった」ことを意味します。ディメンションがfully_unsetの下に記載されている場合、値を持つ行が一つもありません。イベントは発生しているものの、アプリまたはサイトがそのパラメーターを一度も付与していないため、内訳ではなく計測上の問題として報告してください。fully_unsetをトラッキングの欠落と判断する前に、プラットフォームを確認してください。 このプロパティのストリームに当てはまらないディメンションは、実装に問題がなくてもすべての行で(not set)になります。config.json のplatformsが記録されている場合、レスポンスは 24 個のディメンションにわたってこの確認をすでに行います。ウェブストリーム側は、9 個のページファミリー、browser/browserVersion、および 12 個すべての拡張計測機能ファミリー(離脱クリック、ファイルのダウンロード、動画、スクロール)です。アプリストリーム側はappVersionです。これらはunset_dimensions.platform_mismatchedに個別に記載され、noteにはアプリやサイトのせいにするのではなく、「想定どおりであり、トラッキングの欠落ではありません」と記されます。ただし、この確認で検出されない次の 3 つのケースでは、以下の考え方を自分で適用してください。
platformsがまったく記録されていない場合、unknownが含まれている場合(分類できないストリームがあると、リストだけでは完全な判断ができないため、ウェブ/アプリの判定は適用されません。上記のplatformsに関する注記を参照してください)、および上記 24 個以外のディメンションがすべて未設定の場合です(unifiedScreenNameも含まれます。これはクロスプラットフォームのため、そこで実際に欠落があってもフラグは立ちません。また、searchTermとcontentGroupファミリーも、どちらのプラットフォームでも手動計測が必要です)。ここには 2 つではなく 3 つのファミリーがあります。
pagePath、pageTitle、landingPagePlusQueryStringはウェブストリームのディメンション、appVersionはアプリストリームのディメンションです。そしてunified*ファミリー(unifiedScreenName。UI 上の名前は「ページタイトルとスクリーン名」です、unifiedScreenClass、unifiedPagePathScreen)はクロスプラットフォームで、ウェブストリームではページタイトル/パスを、アプリストリームではスクリーン名/クラスを保持します。両方をカウントする指標はscreenPageViewsです。screenNameディメンションはありません。これをリクエストすると、400 ... Field screenName is not a valid dimensionというエラーになり、リクエスト全体が失敗します。- アプリのみ:ページファミリーはすべての行で
(not set)になります。これはファミリーの選択が誤っているのであり、トラッキングの欠落ではありません。代わりにunified*ファミリーを使用してください。unifiedScreenNameもすべて未設定なら、アプリからスクリーン名パラメーターが送信されていません。一方、unifiedScreenClassには引き続き自動収集されたクラス名が含まれます(アプリのみのプロパティで実測したところ、unifiedScreenNameはすべて(not set)でしたが、unifiedScreenClassには実際のスクリーンが返されました)。ファネルの最初のステップはpage_viewではなくscreen_viewです。 - ウェブのみ:
unified*ファミリーには値が入っています。それらの行は実際のページタイトルとパスなので、アプリ由来のデータとして破棄したり、このファミリーを避けたりしてはいけません。実際に存在しないのはアプリスコープのデータです。appVersionとアプリのスクリーンパラメーターの送信元となるストリームがありません。 - 混在:アプリ側では
pagePathが(not set)、ウェブ側ではappVersionが(not set)になります。どちらも正しい状態なので、どちらも欠落として報告しないでください。プラットフォームをまたいだビューにはunified*ファミリーを使用してください。両方を分けて確認する必要がある場合は、platformディメンションで内訳を表示するか、一方に絞り込み、数値がどのプラットフォームを対象としているかを明記してください。
- アプリのみ:ページファミリーはすべての行で
-
ゼロは「未計測」を意味することがあります。 レスポンスに
uninstrumented_metricsが含まれている場合、その指標が 0 と表示されるのは、このプロパティでその指標の基となるイベントが一度も記録されていないためであり、何も起きなかったからではありません。トラッキングの欠落(「アプリまたはサイトからrefundイベントが一度も送信されていない」)として報告し、ビジネス上の結果(「返金はありませんでした」)として報告してはいけません。後者は、マーケターが行動に移すことになる誤った事実を伝え、会話を終わらせてしまいます。このキーには、その指標の値に反映される可能性のあるすべてのイベントが列挙されています。アプリでの購入はpurchaseではなくin_app_purchaseとして届くため、その一覧を引用してください。記録されているイベント一覧が古い場合、注記は「未計測の可能性があります」と断定を避け、更新を求めます。データで裏付けられない確実性を示すのではなく、その留保もそのまま伝えてください。 -
指標が 0 と表示されるのは、ここに該当するストリーム種別が存在しないための場合もあります。これは「未計測」とは異なる、3 つ目の解釈です。
scrolledUsers(および今後追加される同種の指標)は、アプリストリームには対応するイベントがない、ウェブ専用の GA4 拡張計測イベントに依存します。そのため、アプリ専用のプロパティでは常に 0 となります。イベントを追加すれば解消できるトラッキングの欠落でも、ビジネス上のゼロでもありません。レスポンスにplatform_mismatched_metricsが含まれている場合は、他の 2 つの解釈に当てはめず、その旨を明示してください。 -
購入数が 0 でも購入収益がある場合は、サブスクリプション収益です。
purchaseRevenue/grossPurchaseRevenueが 0 以外で、リクエストした購入数/購入者数の指標がすべて 0 の場合、レスポンスにはsubscription_revenueが含まれます。アプリストアのサブスクリプションアプリでは、GA4 はapp_store_subscription_*イベントを収益とtransactionsに計上しますが、購入数には計上しないため、ゼロは仕様どおりであり、データの欠落ではありません。収益は継続的なサブスクリプション収益として報告し、そこから平均注文額を計算してはいけません。この形式ではpurchaseRevenue/ecommercePurchasesは 0 となり、注文単価がゼロであるかのように見えてしまいます。 -
空のファネルは、コンバージョンがゼロなのではなく、データ保持期間が原因かもしれません。 保持期間の制限はファネルと探索には適用されますが、標準レポートには適用されません。そのため、保持期間を過ぎた期間を指定すると、
ga4_funnel.pyはエラーなしで 0 行を返しますが、ga4_query.pyは同じ期間を通常どおり返します。14 か月分のデータがあるプロパティで検証したところ、2025 年 1 月のファネルは何も返しませんでしたが、runReportはadd_to_cartを 783 件、purchaseを 136 件返しました。レスポンスにbeyond_retention_daysが含まれている場合は、ファネルではそこまで遡れないことを伝え、クエリでイベントを確認してください。コンバージョンがゼロだと報告してはいけません。この場合、steps_without_dataの注記自体もすでに表現を和らげており(「通常はユーザー数がゼロを意味する」と断定しなくなっています)が、欠落ステップの説明よりも先に、保持期間について説明してください。beyond_retention_daysがないからといって、問題がないとは限りません。保持期間の設定が一度も記録されていない場合にも、この項目はありません。その場合、空のファネルにはチェックを実行できなかったことを示す注記が含まれます。その内容を伝え、ゼロと報告するのではなくga4_query.pyで確認してください。ga-auth でプロパティを選び直すと、設定が記録されます。 -
ファネルの内訳には集計行が含まれます。 レスポンスに
reserved_total_row_indexesが記載されている場合、それらの行はカテゴリではありません。実際の内訳ディメンション(funnel_breakdown)では、RESERVED_TOTAL行は隣接する行の合計と同じなので、すべてを足し合わせると実際の合計の 2 倍を報告することになります。期間比較(date_rangesが 2 つ以上あり、dateRangeヘッダーがある場合)では逆のことが起きます。比較対象の複数期間でアクティブだったユーザーは合計では 1 回、各期間の行ではそれぞれ 1 回ずつ数えられるため、行の合計が合計値を上回ることがあります。どちらの場合も一致するとは限りません。提示するランキングや全体に占める割合の計算からは、集計行を除外してください。RESERVED_(other)行は 3 つ目のケースで、詳細を集約した残余分です。合計には含まれますが、さらに細分化することはできません。 -
直近 2 日間のデータはまだ変動しています。 GA4 は 24~48 時間にわたって処理を続けるため、
todayまたはyesterdayで終わる期間の数値は変わります。レスポンスにunsettled_rangesが含まれている場合、最近の落ち込みを実際の減少として報告してはいけません。データの処理がまだ完了していないと伝えるか、期間を2daysAgoまでにしてください。「昨日の収益が 30%減少しました」は典型的な例です。この数値は翌日には上がるのに、マーケターがキャンペーンを一時停止してしまいます。 -
期間比較:
date_rangesに 2 つの期間を指定すると、dateRange列に期間ごとの比較が表示されます。2 つの期間の長さをそろえ、直近の期間はtodayではなくyesterdayで終わるようにしてください。7daysAgo..todayは 8 日間である一方、14daysAgo..8daysAgoは 7 日間です。また、今日のデータはまだ確定していないため、両期間の「X%増減」には単に 1 日分の差が含まれてしまいます。期間の長さが異なる場合、レスポンスにはdate_range_lengthsが含まれ、警告が表示されます。さらにdateで内訳を取ると、GA4 は各日付をすべての期間について返し、それぞれの期間外の日付は0で埋めます。このゼロは「この期間に含まれない」という意味なので、返されたすべての行を対象に平均を計算してはいけません。 -
フィルター:
dimension_filter(複合条件、and/or/not、部分一致、リスト)、metric_filter(数値条件)。
リアルタイムスナップショット(過去30分)
「現在、アプリやサイトを利用しているユーザーは?」や「たった今何が起きた?」といったリアルタイムの質問には、別のエンドポイントである ga4_realtime.py を使用します。
echo '<request JSON>' | .ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_realtime.py
minute_rangesを指定すると対象時間を絞り込めます(過去30分を対象にする場合は省略します)。- リアルタイムで使用できるディメンション/指標は限られています(country、deviceCategory、eventName、minutesAgo など/activeUsers、eventCount、keyEvents、screenPageViews)。標準的なレポートで使用するディメンション/指標の多くは、リアルタイムでは使用できません。
- これらの指標のうち、
activeUsersはほかのどの指標とも組み合わせられません(eventCount、keyEvents、screenPageViews はいずれもactiveUsersと組み合わせると失敗しますが、これら同士は自由に組み合わせられます)。スクリプトはこの組み合わせをローカルで拒否します。リアルタイムクエリを2つに分け、数値を並べて報告してください。 - フィルター/並べ替えの構文は
ga4_query.pyと同じです(references/analysis-guide.md)。ただし、date_ranges/offsetは使用できません。指定するとエラーとして拒否されます(過去の期間にはga4_query.pyを使用してください)。
クロス集計(ピボットレポート)
「国 × デバイス別」や「チャネルとデバイスのクロス集計」など、2つ以上の軸によるクロス集計分析には ga4_pivot.py を使用します。
echo '<request JSON>' | .ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_pivot.py
pivots配列の各項目が1つの軸です(field_names、limit、order_bys、metric_aggregations)。軸のディメンションは、トップレベルのdimensionsにも指定する必要があります。GA4 ではすべての軸にlimitが必要です。省略すると、上限なしの結果ではなく400エラーになります。そのため、limitがない場合はデフォルト値が設定されます(軸が1つの場合はGA4推奨の10000、複数の軸がある場合は、すべての上限値の積がGA4の上限250000以下になるように縮小されます)。軸の上限を設定するには、明示的に値を指定してください(例:上位5件なら5)。軸の値が上限を超えると、pivot_axes[].truncatedにその旨が示されます。metric_aggregations(TOTAL、MINIMUM、MAXIMUM、COUNT)をリクエストすると、レスポンスにaggregates行(合計など)が追加されます。ただし、pivotsに2つ以上の項目がある場合に限られます。実際に確認したところ、ピボットが1つだけの場合、GA4 はエラーを返さずにaggregatesをまったく返しません。任意のディメンションで2つ目のピボットを追加すると、集計を利用できます。ピボットが1つだけの状態でmetric_aggregationsをリクエストすると、合計が暗黙に除外されたことと対処方法を示すnoteがレスポンスに含まれるようになりました。代わりに、合計を求めるために各行を手動で合算しないでください。この注記が理由を示すのは、軸が切り詰められている場合(よくあるケースです。pivot_axes[].truncatedを参照してください)は、そもそも行がすべての値を網羅していないためです。また、指標が重複排除されている場合(ユーザー数、セッション数)は、軸が切り詰められていなくても合計が実際より大きくなります。注記には、重複排除の問題を常に理由とするのではなく、実際に当てはまる理由が示されます。- レスポンスの
pivot_axesには、軸ごとの切り詰め情報(returned_values、total_row_count、truncated)がpivotsと同じ順序で含まれます。いずれかの軸が切り詰められている場合、トップレベルのtruncatedもtrueになります。そのため、その軸については「合計」ではなく「上位 N 件に基づく」と説明してください。returned_valuesは軸上の値の数であり、トップレベルのrow_count(直積の行数)とは異なります。軸に複数のディメンションがある場合、total_row_countは組み合わせの数です。説明方法についてはreferences/analysis-guide.mdを参照してください。 - フィルター構文は
ga4_query.pyと同じですが、並べ替えと行数の上限は軸ごとに指定します(pivots[].order_bys、pivots[].limit)。トップレベルのorder_bys/limitは使用できません。指定するとエラーとして拒否されます。
コホート(リテンション)レポート
「6月第1週に登録したユーザーのうち、週ごとに何人が戻ってくるか」のようなリテンションに関する質問には、ga4_cohort.py を使用します。
echo '<request JSON>' | .ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_cohort.py
簡易指定(単一コホート)の例:
{
"granularity": "WEEKLY",
"date_range": {"start_date": "2026-06-01", "end_date": "2026-06-28"},
"offsets": {"start": 0, "end": 4},
"dimension": "firstSessionDate",
"accumulate": false
}
granularity(DAILY/WEEKLY/MONTHLY)、date_range(コホートの獲得期間)、offsets(観測する経過期間、{start,end})は必須です。オフセットは獲得週(週0)を起点に数えるため、負の値にはできず、startは<= endでなければなりません — 範囲が逆転していると該当する週がなく、GA4 はエラーなしで0行を返すため、「リテンションなし」と解釈されてしまいます。どちらの条件もローカルで検出されるようになりました。dimension(デフォルトはfirstSessionDate)は任意です。accumulateは false のままにしてください —trueにするにはrunPivotReportが必要ですが、このスクリプトでは使用しないため、GA4 は常に拒否していました。現在はローカルで検出されます。累計を求めるには、オフセットごとのcohortActiveUsersを自分で合計してください。- 複数のコホートを一度に比較するには、詳細指定を使用し、
cohort_spec(cohorts、cohorts_range、cohort_report_settings)を直接指定します。 cohort/cohortNthDay/Week/Monthディメンションとデフォルト指標(cohortActiveUsers)は自動で追加されます。トップレベルのdate_rangesは使用できません — コホートではdate_range/cohort_specを使用します。- フィルター/並べ替えの構文は
ga4_query.pyと同じです(references/analysis-guide.md)。 - 日付には絶対日付(
2026-06-01)のみを指定してください。 他のレポートで使用できる相対日付(28daysAgo、today)は、コホートでは GA4 に拒否されます。 - 指定したオフセットの期間がまだ完全に経過していない場合、行がまったく返されないことがあります — ユーザーの再訪がゼロの場合と区別できません。この状況に該当する場合は、レスポンスの
noteに記載されます(例:週3がまだ進行中の週次コホートにおけるオフセット3)。最近のオフセットが返されないからといって、「リテンション率0%」と報告しないでください。
ファネル(コンバージョン/離脱)レポート
「page_view → add_to_cart → purchase の段階ごとのコンバージョン/離脱」のような順序付きステップの分析には、ga4_funnel.py を使用します。
echo '<request JSON>' | .ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_funnel.py
簡易指定の例:
{
"steps": [
{"name": "Page view", "event_name": "page_view"},
{"name": "Add to cart", "event_name": "add_to_cart"},
{"name": "Purchase", "event_name": "purchase"}
],
"date_ranges": [{"start_date": "28daysAgo", "end_date": "yesterday"}],
"funnel_breakdown": {"dimension": "deviceCategory", "limit": 5}
}
steps(2つ以上)の各ステップでは、event_name/field(+value|in_list)/filter_expression(詳細指定)のいずれか1つだけを定義します。funnel_breakdown(任意)では、特定のディメンション(デバイス、チャネルなど)ごとにステップの離脱を分割します。ブレークダウンの結果がすべて(not set)になることがあります — イベントは発生しているものの、アプリやサイトがそのパラメーターを付与していない状態です。サブレポートにunset_dimensions.fully_unsetが含まれる場合(またはトップレベルのnoteにトラッキングの欠落が記載されている場合)、そのブレークダウンから情報は得られません。コンバージョン結果ではなく、計測設定の欠落として報告してください。ブレークダウンに混在する集計RESERVED_TOTAL行はこの確認から除外され、reserved_total_row_indexesに列挙されます。funnel_visualization_type(デフォルトはSTANDARD_FUNNEL。時系列の推移にはTRENDED_FUNNELを使用)によって、funnel_visualizationにdate軸を含めるかどうかが決まります — どちらを選んでも、両方のサブレポートに値が入力されます — 詳細はreferences/analysis-guide.mdを参照してください。TRENDED ファネルの日次推移では、ステップごとに行が欠落することがあります。通常の日次系列でも発生する「GA4 がゼロの行を省略する」問題と同じです(上記の箇条書きを参照)。推移の平均を計算したりグラフにしたりする前に、funnel_visualization.missing_dates_by_step(またはトップレベルのnote)を確認してください。date_rangesに2つのエントリーを指定すると、ga4_query.pyと同様に2つの期間を比較できます — GA4 はdateRangeディメンションを追加し、集計行も含めてfunnel_breakdownとまったく同じように扱います(ライブ環境で確認済み)。RESERVED_TOTAL行が返されることを想定し、上記の「合計する前に除外する」という指針に従ってください。これとfunnel_breakdownの併用も可能です(ライブ環境で確認済み) — 2つの軸は直積(ステップ × 指定したブレークダウン × dateRange)になり、どちらかの軸でRESERVED_TOTALとなる行はreserved_total_row_indexesで正しく検出されるため、特別な処理は必要ありません。
ファイルの場所
config.json(property_id)とtoken.jsonは、ga-auth skillによって作成・管理されます。taxonomy.mdは、ga-taxonomy skillによって作成されます。GA4_DIR環境変数を設定すると、.ga4の場所を変更できます(デフォルト:<cwd>/.ga4)。