mcpField
G
ga-use

ga-use

github.com/ogaeng数据与数据库142 次安装9 周前更新
代码仓库

关于 ga-use

ga-use 面向营销人员,将自然语言分析需求转为 GA4 Data API 报告并解读结果。它用 Python 脚本处理确定性查询,并依据事件和字段信息映射分析请求。

主要功能

  1. 01自然语言提出 GA4 报告需求
  2. 02映射事件与参数
  3. 03执行 GA4 Data API 查询
  4. 04解读并整理结果
  5. 05检查分类表与事件活动

适用场景

  1. 01查看流量或事件指标
  2. 02分析转化漏斗与用户路径
  3. 03调查表现变化

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ogaeng/ga4-skill --skill ga-use

安装后在 Claude Code 中输入/ga-use确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

requirements.txt
references/
analysis-guide.md
analysis-recipes.md
scripts/
ga4_cohort.py
ga4_common.py
ga4_funnel.py
ga4_metadata.py
ga4_pivot.py
ga4_query.py
ga4_realtime.py
ga4_reporting.py

详细介绍

GA4 分析与查询技能(ga-use)

将营销人员的自然语言分析请求转换为 GA4 Data API 报告并作答。 确定性工作由 scripts/ 中的 Python 脚本完成;你负责将请求映射为查询, 并解读结果。

语言

使用用户的语言作答。如果用户用韩语提问,就用韩语作答; 如果用户用英语提问,就用英语作答。每个步骤都适用此规则,包括设置指导、 进度更新、结果和错误说明。

不得翻译:GA4 API 标识符(eventCount、sessionSource、runReport)、 文件和目录名称(.ga4/token.json)、shell 命令和 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;其他 Agent 使用各自的位置)。 请替换为实际路径。请从项目根目录运行命令。

第 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 查询即可)。实际情况是,31 个分类条目中有 14 个在过去 30 天内没有任何命中,有些即使在 90 天内也只有个位数——不了解这一点就构建漏斗,可能会令人信服地报告“3 项中完成 1 项 → 完成率 33%”这类毫无意义的数字。样本量较小时,报告原始计数而非百分比,并说明原因。
    • 如果不存在,分析之前先调查事件概况:使用 limit 50 或更高的值查询 eventName × eventCount/activeUsers,查看此属性包含哪些事件,然后再映射请求。如果响应中的 truncated: true,就提高 limit 并重新查询(缺失事件可能意味着缺少某项核心行为)。
  • 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 技能的第 4 步中的第 4 和第 5 项保存结果:保存操作会从头重建 config.json,因此必须在同一命令中再次传入币种、时区和保留期限,否则它们会变成 null——这会导致 ga-use 无法获知其报告收入所用的币种(实时响应完全不包含元数据),也会丢失空漏斗检查所依据的保留期限。
  • [] 表示该属性没有数据流——它没有收集任何数据。
  • unknown 条目表示某个数据流无法分类,因此列表并非完整答案。存在 unknown 时,不要把缺少 web 解读为“仅限应用”:应说明该属性无法分类,而不是据此判断其仅限 Web 或仅限应用。
  • 如果 platforms_age_days 大于 180,列表可能早于团队后来添加的平台。依赖该列表之前,请重新检查。
  • platforms 表示已配置的数据流;platform 维度表示实际到达的流量。已配置的数据流仍可能没有数据,因此不要把其中一种情况说成另一种。

分析流程

  1. 确认需要进行哪种分析(指标、时间段、细分维度、过滤条件)。
  2. 如果这是一个复合问题(对应配方中的问题类型——转化分析、路径/旅程、效果摘要(概览)、变化诊断、内容效果或行为重要性比较),请先阅读 references/analysis-recipes.md 并规划查询(要组合什么、为什么组合、如何组合)。 对于目标数量可能较少的分析(转化、细分),先检查规模,并根据 references/analysis-recipes.md 中的样本量门槛设定分析深度。
  3. 将请求映射到实际事件/参数名称——使用步骤 0 收集的信息 (taxonomy.md,如果没有则使用查询到的事件列表)。
  4. 如果不确定维度/指标,请查询元数据——使用 --search 缩小范围:
    .ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_metadata.py get-metadata --search item
    
    一个属性公开约 400 个维度和约 120 个指标,因此未筛选的转储约有 12k 个 token;使用 --search 查询单个字段约有 150 个 token。--search 可重复使用 (保留匹配任意搜索词的条目),并会匹配 API 名称或 UI 名称。--kind dimension|metric 会移除另一个列表。筛选后的响应会包含一个 filtered 键,其中列出 未筛选结果的总数——如果存在该键,说明你看到的并非完整目录。
  5. 构建扩展 JSON 规范并执行查询(格式见 references/analysis-guide.md):
    echo '<request JSON>' | .ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_query.py
    
  6. 将结果整理为表格或摘要并作答。若结果为空或出现错误,请根据 references/analysis-recipes.md 中的重试循环进行处理。 如果 truncated 为 true,你看到的只是顶部的一部分——不要将其描述为“总数”;应提高 limit 并重新查询,或注明这是“基于前 N 项”的结果。 如果漏斗结果包含 steps_without_data,则该步骤在响应中没有对应的行 (GA4 会省略触达量为零的步骤,因此通常意味着零——但不要自行推断,请原样传递)。

工作原则(关键)

目标受众是非技术营销人员:

  • 将工作拆分成小步骤,并在每一步用一句话说明“做什么/为什么”。
  • 尽可能自行处理文件放置和命令执行。
  • 将自然语言转换为 JSON 规范是 Claude 的工作——绝不要要求营销人员提供 JSON。

常见请求模式

  • Top-N:order_bys(desc)+ limit。例如,按计数统计事件数前 10 名。(透视表按轴分别设置,因此应使用 pivots[].order_bys / pivots[].limit。)

  • 按 dimension 排序采用的是 GA4 的字典序,而不是数值或日历顺序。 hour/minute 不会补零,因此此脚本会自动为这两个维度请求 NUMERIC 排序类型,无需额外操作。dayOfWeekName 和 appVersion 也有同样的问题,且服务端无法修复(前者是文本,后者是多段字符串;NUMERIC 排序类型同样无效——两者均经实时测量确认),因此会通过 note 发出警告:对于 dayOfWeekName,请按 dayOfWeek(0=Sunday..6=Saturday)排序,并保留名称用于显示;对于 appVersion,没有可替代的维度——请自行解析每个版本号中以点分隔的部分,将其作为整数对返回的行排序。其他任何看起来像数字的维度(包括自定义维度)也可能存在同样的问题——安全维度的完整列表请参见 references/analysis-guide.md。

  • 不要通过对各行求和来获取总计。 以 ~Users 结尾的指标和 sessions 都是去重值——对各维度的行求和会使结果高于真实总值(在实时资源中测量:将一个月的每日 activeUsers 相加,结果比真实总值高出 13%)。由于另一个原因,费率和平均值也不适合求和:它们从未去重,对各行进行加总或平均在算术上都不成立。如果响应包含 non_additive_metrics/note,则此规则适用——注释会说明每项指标适用的具体原因,而不是把所有情况都归咎于去重。如果需要总计,使用相同的时间段再次查询,但不指定 dimensions。像 eventCount 这样的计数型指标可以安全求和。

  • totalUsers 和 activeUsers 不可互换。 totalUsers 统计记录过事件的所有用户;activeUsers 则要求存在互动信号,因此两者通常不同(实时测量:同一时间段内分别为 99 和 124,相差 25%)。GA4 自带的 *PerUser 指标(sessionsPerUser 等)除以的是 activeUsers,而不是 totalUsers——不要用 totalUsers 手动计算“人均”数据后声称结果更准确;请使用 GA4 已提供的指标,或者在必须手动计算时使用 activeUsers。

  • dauPerMau/dauPerWau/wauPerMau 不适用上述“无维度 = 安全总计”规则。 这些是逐日滚动比率;当时间段超过一天时,GA4 自带的无维度聚合值是每日数值之和,而不是整个时间段的比率——经实时测量确认,结果完全一致(6 天查询的无维度总值与手动求和的同日数值相同,精确到双精度)。如果响应中的注释提到这些指标,请改为请求单日指标,或按 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/eventCount)请求的事件级收入指标(totalRevenue、purchaseRevenue)返回值会远低于真实总值(实测相差约 13 倍)。不要引用此响应中的原始数据列——请在不包含表达式的情况下重新查询,或缩小查询范围以避免触发抽样。(商品级的 itemRevenue 和计数型指标不会偏移,也不会被标记。)

  • 按日(或按月)统计的序列可能缺少行。 如果某行中的所有请求指标均为零,GA4 就会丢弃该行,因此按 date 查询收入时,零销售额的日期会消失;yearMonth 维度的粒度高一层,也会发生同样的情况(经实时测量:12 个月的订阅收入查询只返回了其中 4 个月)。如果响应包含 missing_dates,这些行表示实际值为零,并非数据缺失——计算平均值时请将它们纳入(仅除以返回的行数会导致结果偏高),也不要让趋势线跨越这些日期直接连接。

  • (not set) 不是一个类别。 如果响应包含 unset_dimensions,表示 GA4 未收到这些行对应的值。切勿将其报告为排名第一的项目——在一个实时资源中,“按收入统计排名最高的优惠券”将 (not set) 排在首位,意思是“未使用优惠券”。如果某个维度列在 fully_unset 下,则所有行都没有值:事件已触发,但应用或网站从未附加该参数,因此应报告为追踪缺口,而不是展示细分结果。 在将 fully_unset 判定为追踪缺口之前,请先检查平台。 如果某个维度不适用于此属性的数据流,那么即使实现完全正确,它也会始终返回 (not set)。只要 config.json 中记录了 platforms,响应就会自行完成这项检查,涵盖 24 个维度:Web 数据流一侧包括 9 个成员的页面维度系列、browser/browserVersion,以及完整的 12 个成员的增强型衡量系列(出站点击、文件下载、视频、滚动);应用数据流一侧则包括 appVersion。这些维度会分别列在 unset_dimensions.platform_mismatched 下,且 note 会说明“这是预期情况,不是追踪缺口”,而不会归咎于应用或网站。

    不过,以下三种情况下检查不会给出提示,因此仍需自行应用上述判断:完全没有记录 platforms;其中包含 unknown(无法分类的数据流意味着列表并不完整,因此不会据此判断 Web/应用平台——请参阅上文关于 platforms 的说明);以及这 24 个维度之外完全未设置的维度(包括 unifiedScreenName——它是跨平台维度,因此其中真实存在的缺口不会被标记;searchTerm 和 contentGroup 系列也一样,因为这两个平台都需要手动埋点)。

    这里有三个系列,而非两个。pagePath、pageTitle 和 landingPagePlusQueryString 是 Web 数据流维度;appVersion 属于应用数据流;而 unified* 系列——unifiedScreenName(其 UI 名称为“页面标题和屏幕名称”)、unifiedScreenClass、unifiedPagePathScreen——是跨平台维度:在 Web 数据流中承载页面标题/路径,在应用数据流中承载屏幕名称/类别。screenPageViews 是同时统计两者的指标。不存在 screenName 维度:请求该维度会直接失败,返回 400 ... Field screenName is not a valid dimension。

    • 仅应用:页面维度系列在每一行都为 (not set)——这属于维度系列不匹配,而非追踪缺口。请改用 unified* 系列。如果 unifiedScreenName 也完全未设置,说明应用没有发送屏幕名称参数,而 unifiedScreenClass 仍会包含自动收集的类别名称(在一个仅应用的线上属性中测得:unifiedScreenName 完全为 (not set),而 unifiedScreenClass 返回了实际屏幕)。在漏斗中,第一步是 screen_view,而非 page_view。
    • 仅 Web:这里的 unified* 系列有值——这些行是真实的页面标题和路径,切勿将其误认为应用产生的数据而丢弃,也不要绕开该系列。真正缺失的是应用范围的数据:appVersion 和应用屏幕参数都没有可供其取值的数据流。
    • 混合平台:应用部分的 pagePath 为 (not set),Web 部分的 appVersion 为 (not set),而且两者都正确——都不应报告为缺口。若要查看跨平台数据,请使用 unified* 系列;若要分别查看两部分,请按 platform 维度细分(或筛选至单个平台),并说明数据涵盖的是哪个平台。
  • 0 可能表示“从未跟踪”。 如果响应包含 uninstrumented_metrics,该指标的读数为 0,是因为此媒体资源从未记录过其背后的事件——而不是因为没有发生任何事情。应将其报告为跟踪缺口(“应用或网站从未发送过 refund 事件”),切勿将其报告为业务结果(“没有退款”)。后一种说法会用一个错误事实结束对话,营销人员还会据此采取行动。该键会列出所有可能填充此指标的事件——请引用这份列表,因为应用上的购买事件会记为 in_app_purchase,而非 purchase。如果存档的事件清单已经过时,说明会采用保留措辞(“可能表示未跟踪”)并要求刷新清单;请保留这种不确定性,不要报告数据无法支持的确定结论。

  • 指标也可能因为此处不存在对应的流类型而读数为 0——这是第三种情况,与“从未跟踪”不同。 scrolledUsers(以及未来任何类似指标)依赖仅适用于 Web 的 GA4 增强型衡量事件,且没有对应的应用流事件,因此在仅有应用流的媒体资源中,它只能是 0——这不是添加事件就能修复的跟踪缺口,也不是业务上的 0。如果响应包含 platform_mismatched_metrics,请明确说明这一点,不要套用前两种说法。

  • 购买次数为 0 时仍有购买收入,说明这是订阅收入。 如果 purchaseRevenue/grossPurchaseRevenue 不为 0,而所有请求的购买次数/购买者指标均为 0,响应会包含 subscription_revenue。在应用商店订阅类应用中,GA4 会将 app_store_subscription_* 事件计入收入和 transactions,但不会计入购买次数,因此这些 0 是设计如此,并非数据缺口。请将这笔收入报告为定期订阅收入,不要据此计算平均订单价值:这种情况下 purchaseRevenue/ecommercePurchases 会返回 0,看起来就像订单价格为 0。

  • 漏斗为空可能是数据保留期限所致,而非转化次数为 0。 保留期限会限制漏斗和探索,但不会限制标准报告,因此对于超出保留期限的时段,ga4_funnel.py 会无报错地返回 0 行,而 ga4_query.py 对同一时段则能正常作答。在一个 14 个月的媒体资源上进行测量时,2025 年 1 月的漏斗没有返回任何数据,而 runReport 返回了 783 个 add_to_cart 和 136 个 purchase。如果响应包含 beyond_retention_days,请说明漏斗无法查询那么久之前的数据,并用查询核实事件——绝不要报告为转化次数为 0。适用于此情况时,steps_without_data 说明本身已经使用了委婉表述(不再断言“通常意味着用户数为 0”),但仍应优先说明保留期限,而不是先提缺失步骤。没有 beyond_retention_days 并不代表一切正常——如果从未记录保留期限设置,该字段同样不会出现。此时空漏斗会附带一条说明,指出无法执行检查;请转述这一点,并用 ga4_query.py 核实,而不是报告为 0。使用 ga-auth 重新选择媒体资源即可记录该设置。

  • 漏斗细分结果包含汇总行。 如果响应列出了 reserved_total_row_indexes,这些行不是类别。对于实际的细分维度(funnel_breakdown),RESERVED_TOTAL 行已经等于其相邻行的总和,因此把所有行相加会使实际总数翻倍。对于时段对比(2 个或更多 date_ranges,且包含 dateRange 表头),情况则相反:在多个对比时段内都活跃的用户会在总计中只计一次,但会在相邻的每个时段行中分别计数,因此各行总和可能超过总计——无论如何都不要预期两者相等;只需在展示排名或总量占比时排除汇总行。RESERVED_(other) 行属于第三种情况——它表示折叠后的长尾数据,应计入总量,但无法进一步细分。

  • 最近两天的数据仍在变化。 GA4 需要 24–48 小时完成处理,因此结束于 today 或 yesterday 的时段数据还会变化。如果响应包含 unsettled_ranges,绝不要将近期下滑报告为真实下降——应说明数据仍在处理中,或将时段结束日期设为 2daysAgo。“昨天的收入下降了 30%”就是典型例子:营销人员可能会因为一个明天就会变高的数字而暂停营销活动。

  • 时段对比:给 date_ranges 传入两个时段,dateRange 列就会显示各时段的对比。两个时段长度必须相同,且较新的时段应结束于 yesterday,而非 today——7daysAgo..today 有 8 天,而 14daysAgo..8daysAgo 只有 7 天;并且今天尚未结束,因此两者之间的“上升/下降 X%”部分只是多了一天造成的。响应会包含 date_range_lengths,并在时段长度不同时发出警告。如果还按 date 进行细分,GA4 会为每个时段返回每个日期,并将各时段之外的日期填为 0——这些 0 表示“此时段不包含该日期”,因此绝不要对返回的所有行取平均值。

  • 筛选器:dimension_filter(复合与/或/非、部分匹配、列表)、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 配对时都会失败,而这些指标彼此之间可以自由组合)。脚本会在本地拒绝此类配对——请拆分为两个实时查询,并并列报告数值。
  • 筛选/排序语法与 ga4_query.py 相同(references/analysis-guide.md),但不存在 date_ranges/offset——传入这些参数会被拦截并报错(查询过去时段请使用 ga4_query.py)。

交叉表(透视报告)

对于两个或更多轴的交叉表分析,例如“按国家 × 设备”或“按渠道和设备交叉统计”,请使用 ga4_pivot.py:

echo '<request JSON>' | .ga4/venv/bin/python {SKILLS_DIR}/ga-use/scripts/ga4_pivot.py
  • pivots 数组中的每一项代表一个轴(field_names、limit、order_bys、metric_aggregations)。轴维度也必须列在顶层的 dimensions 中。GA4 要求每个轴都设置 limit——省略会返回 400 错误,而不是不设上限的结果——因此缺少 limit 时会自动设置默认值(单个轴:GA4 建议的 10000;多个轴:会相应调低,以使所有 limit 的乘积保持在 GA4 的 250000 上限内);也可以显式设置,以限制某个轴(例如,设置为 5 以获取前 5 项)。如果某个轴的值超过其 limit,pivot_axes[].truncated 会说明这一点。
  • 请求 metric_aggregations(TOTAL、MINIMUM、MAXIMUM、COUNT)会在响应中添加 aggregates 行(总计等)——但仅当 pivots 至少有 2 项时才会添加。实际测试确认:只有一个透视轴时,GA4 会静默地不返回任何 aggregates(也不会报错)。添加一个任意维度的第二个透视轴即可启用此功能。如果在单个透视轴上请求 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 月第一周注册的用户中,有多少人每周都会回来”这类留存问题,请使用 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 会以零行且不报错的方式响应,这会被理解为“没有留存”;现在这两种情况都会在本地捕获。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)。 GA4 不接受其他报告支持的相对日期 (28daysAgo、today)用于群组报告。
  • 如果请求的偏移量对应的窗口尚未完全经过,响应中可能完全没有该行 — 这与回访用户数为零无法区分。出现这种情况时,响应的 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}
}
  • 至少需要 2 个 steps,且每个步骤必须恰好定义以下其中一项:event_name / field(+value|in_list)/ filter_expression(完整控制模式)。
  • 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。趋势漏斗的每日趋势可能会缺少某些步骤的行,这与普通每日序列的“GA4 删除零值行”问题相同(见上文要点)— 在计算平均值或绘制趋势图之前,请检查 funnel_visualization.missing_dates_by_step(或顶层 note)。
  • 包含 2 个条目的 date_ranges 会比较两个时间段,与 ga4_query.py 相同 — GA4 会附加一个 dateRange 维度,并将其视为 funnel_breakdown (经实时验证),包括汇总行:请预期会出现 RESERVED_TOTAL 行,并应用上文相同的“汇总前排除”指导。也可以同时使用此项和 funnel_breakdown(经实时验证)— 两个轴会生成交叉组合(步骤 × 你的细分维度 × dateRange),而且 reserved_total_row_indexes 会正确捕获在任一轴上属于 RESERVED_TOTAL 的行,无需特殊处理。

文件位置

  • config.json(property_id)和 token.json 由 ga-auth 技能创建和管理。
  • taxonomy.md 由 ga-taxonomy 技能创建。
  • GA4_DIR 环境变量可以更改 .ga4 的位置(默认值:<cwd>/.ga4)。

评论

支持 Markdown