Correct product analytics cohorts and reporting
CI / verify (push) Has been cancelled
CI / publish (push) Has been cancelled

This commit is contained in:
Rocky
2026-08-21 17:50:35 +08:00
parent b25f5ae6e9
commit edd0d9feca
31 changed files with 1134 additions and 262 deletions
@@ -23,6 +23,7 @@ import { ComparisonBarChart } from "../../components/charts/comparison-bar-chart
import { FunnelChart } from "../../components/charts/funnel-chart";
import { FilterControl, ToggleFilter } from "../../components/filter-control";
import { Card, ErrorState, LoadingState, PageHeader, StatCard } from "../../components/primitives";
import { PeriodCaption } from "../../components/period-caption";
import { RangeControl } from "../../components/range-control";
import { SortControl } from "../../components/sort-control";
import { formatNumber } from "../../lib/format";
@@ -110,7 +111,12 @@ export function AnalyticsPage() {
eyebrow="CEO Dashboard"
title="产品增长与留存"
description="围绕成功使用 AI 的核心价值事件,观察增长质量、留存、消耗与付费。"
actions={<RangeControl value={range} onChange={setRange} />}
actions={
<div className="flex flex-col items-end gap-2">
<RangeControl value={range} onChange={setRange} />
<PeriodCaption from={data.period.from} until={data.period.until} />
</div>
}
/>
<section className="grid gap-4 sm:grid-cols-2 xl:grid-cols-4" aria-label="北极星指标">
@@ -151,7 +157,7 @@ export function AnalyticsPage() {
<Card className="overflow-hidden">
<SectionHeader
title="增长激活漏斗"
description="首次启动到首次 AI 成功,显示逐步及累计转化"
description="同一批已完成 24 小时观察的新安装,所有步骤必须在首次启动后 24 小时内完成"
icon={Target}
/>
<FunnelChart steps={data.growthFunnel} />
@@ -241,7 +247,7 @@ export function AnalyticsPage() {
<Card className="overflow-hidden">
<SectionHeader
title="活跃与消耗"
description="托管调用以服务端结算为准"
description="DAU / WAU / MAU 为截至统计截止时刻的滚动 1 / 7 / 30 日 AI 价值活跃用户"
icon={Activity}
/>
<ComparisonBarChart
@@ -335,20 +341,24 @@ export function AnalyticsPage() {
<section className="grid gap-6 xl:grid-cols-3">
<Card className="overflow-hidden">
<SectionHeader title="付费转化" description="StoreKit 已验证交易" icon={BadgeDollarSign} />
<SectionHeader
title="付费转化"
description="所选周期内完成 7 / 30 天观察窗的注册 cohort;购买以 StoreKit 验证为准"
icon={BadgeDollarSign}
/>
<ComparisonBarChart
items={[
{
label: "7 天免费转付费",
value: data.monetization.conversion7d.percent ?? 0,
value: data.monetization.conversion7d.percent ?? null,
},
{
label: "30 天免费转付费",
value: data.monetization.conversion30d.percent ?? 0,
value: data.monetization.conversion30d.percent ?? null,
},
{
label: "复购率",
value: data.monetization.repeatPurchaseRate.percent ?? 0,
value: data.monetization.repeatPurchaseRate.percent ?? null,
},
]}
primaryLabel="转化率"
@@ -367,9 +377,15 @@ export function AnalyticsPage() {
<Card className="overflow-hidden">
<SectionHeader
title="推荐增长漏斗"
description="分享打开、绑定、激活与奖励"
description="严格绑定 cohort分享打开仅作为独立方向信号"
icon={Target}
/>
<MetricRows
rows={[
["客户端分享信号", formatNumber(data.referralSignals.shared)],
["邀请打开信号", formatNumber(data.referralSignals.opened)],
]}
/>
<FunnelChart steps={data.referralFunnel} />
</Card>
@@ -379,11 +395,11 @@ export function AnalyticsPage() {
items={[
{
label: "客户端 AI",
value: data.guardrails.clientAiSuccessRate.percent ?? 0,
value: data.guardrails.clientAiSuccessRate.percent ?? null,
},
{
label: "托管请求",
value: data.guardrails.managedSuccessRate.percent ?? 0,
value: data.guardrails.managedSuccessRate.percent ?? null,
},
]}
primaryLabel="成功率"
@@ -399,6 +415,44 @@ export function AnalyticsPage() {
</Card>
</section>
<section className="grid gap-6 xl:grid-cols-2">
<Card className="overflow-hidden">
<SectionHeader
title="购买意向漏斗"
description="同一安装依次浏览、发起购买,并由 StoreKit 服务端验证"
icon={BadgeDollarSign}
/>
<FunnelChart
steps={data.monetization.purchaseFunnel}
emptyText="客户端购买事件暂无样本"
/>
<MetricRows
rows={[["取消购买用户", formatNumber(data.monetization.cancelledUsers)]]}
/>
</Card>
<Card className="overflow-hidden">
<SectionHeader
title="AI 终态延迟分布"
description="按客户端白名单耗时桶聚合;不推算虚假的精确分位数"
icon={Gauge}
/>
<ComparisonBarChart
items={data.guardrails.latencyBuckets.map((item) => ({
id: item.bucket,
label: latencyBucketLabel(item.bucket),
value: item.successful,
secondaryValue: item.failed,
}))}
primaryLabel="成功"
secondaryLabel="失败"
primaryTone="success"
secondaryTone="warning"
emptyText="客户端 AI 终态事件暂无样本"
/>
</Card>
</section>
<Card className="overflow-hidden">
<SectionHeader title="渠道质量" description="新增不是终点,重点比较 24 小时激活" icon={Users} />
<ChartToolbar label="渠道质量筛选与排序">
@@ -406,7 +460,7 @@ export function AnalyticsPage() {
value={channelSort}
order={channelOrder}
options={[
{ value: "installs", label: "新增安装" },
{ value: "installs", label: "已完成观察安装" },
{ value: "activated", label: "激活人数" },
{ value: "rate", label: "激活率" },
]}
@@ -425,7 +479,7 @@ export function AnalyticsPage() {
secondaryValue: channel.activated,
hint: `激活率 ${rateLabel(channel.activationRate)}`,
}))}
primaryLabel="新增安装"
primaryLabel="已完成 24h 观察安装"
secondaryLabel="24 小时激活"
emptyText="当前筛选条件下暂无渠道归因数据"
/>
@@ -535,3 +589,13 @@ function executionModeLabel(mode: string): string {
BYOK: "BYOK",
}[mode] ?? mode;
}
function latencyBucketLabel(bucket: string): string {
return {
LT_1S: "< 1 秒",
S1_TO_3: "13 秒",
S3_TO_10: "310 秒",
S10_TO_30: "1030 秒",
GTE_30S: "≥ 30 秒",
}[bucket] ?? bucket;
}