留存分析
问题
什么是留存分析?如何计算留存率?留存分析有哪些常见方法?
答案
什么是留存分析
留存分析衡量用户在初始行为之后是否持续活跃。留存率越高,说明产品"黏住"了用户。
拉新花钱获取 100 个用户,如果次月只剩 20 个在用 → 次月留存率 20%
留存率类型
| 类型 | 定义 | 适用场景 |
|---|---|---|
| N-day 留存 | 第 N 天回来的用户占比 | 次日留存、7 日留存 |
| Unbounded 留存 | 第 N 天及之后任一天回来 | 长期留存趋势 |
| Bracket 留存 | 某时间段内回来的占比 | 第 1-7 天、第 8-14 天 |
| 加权留存 | 给不同天数赋权计算 | 综合留存指标 |
N-day 留存 SQL 实现
计算次日留存、7日留存、30日留存
WITH first_visit AS (
-- 每个用户的首次访问日期
SELECT
user_id,
MIN(event_date) AS first_date
FROM user_events
GROUP BY user_id
),
retention AS (
SELECT
f.user_id,
f.first_date,
DATEDIFF(e.event_date, f.first_date) AS day_diff
FROM first_visit f
JOIN user_events e ON f.user_id = e.user_id
)
SELECT
first_date,
COUNT(DISTINCT user_id) AS cohort_size,
-- 次日留存
COUNT(DISTINCT CASE WHEN day_diff = 1 THEN user_id END) AS day1,
ROUND(COUNT(DISTINCT CASE WHEN day_diff = 1 THEN user_id END) * 100.0
/ COUNT(DISTINCT user_id), 1) AS day1_rate,
-- 7日留存
COUNT(DISTINCT CASE WHEN day_diff = 7 THEN user_id END) AS day7,
ROUND(COUNT(DISTINCT CASE WHEN day_diff = 7 THEN user_id END) * 100.0
/ COUNT(DISTINCT user_id), 1) AS day7_rate,
-- 30日留存
COUNT(DISTINCT CASE WHEN day_diff = 30 THEN user_id END) AS day30,
ROUND(COUNT(DISTINCT CASE WHEN day_diff = 30 THEN user_id END) * 100.0
/ COUNT(DISTINCT user_id), 1) AS day30_rate
FROM retention
GROUP BY first_date
ORDER BY first_date;
留存曲线
典型留存曲线呈"L 型"——前几天快速下降,然后趋于平稳:
留存率
100%|●
| ●
50%| ● ●
| ● ● ● ● ● ●
20%| ● ● ● ● ●
|__________________________________
D0 D1 D3 D7 D14 D30
留存曲线的三个关键位置
- 振荡期(Day 0~3):快速下降,与新用户体验强相关
- 选择期(Day 3~14):用户决定是否长期使用
- 稳定期(Day 14+):存活用户基本稳定,是产品"真实"留存
行业留存基准
| 行业 | 次日留存 | 7日留存 | 30日留存 |
|---|---|---|---|
| 社交 App | 35~50% | 20~30% | 10~20% |
| 电商 | 20~30% | 10~15% | 5~10% |
| 游戏 | 30~45% | 15~25% | 5~15% |
| 工具类 | 40~60% | 25~40% | 15~25% |
| SaaS(B2B) | - | 80~95%(周) | 70~90% |
信息
以上为粗略参考,不同产品阶段和用户定义会有很大差异
提升留存的策略
| 阶段 | 策略 | 示例 |
|---|---|---|
| 新用户激活 | 优化 Onboarding,让用户尽快到达 Aha Moment | Twitter 引导关注 5 人 |
| 短期留存 | Push 触达、签到奖励 | 外卖 App 连续登录红包 |
| 中期留存 | 社交关系绑定、个性化推荐 | 微信朋友圈 |
| 长期留存 | 习惯养成、迁移成本 | 笔记 App 数据积累 |
常见面试问题
Q1: 次日留存下降了,怎么排查?
答案:
- 数据校验:埋点有没有问题?日活定义变了吗?
- 时间维度:从哪天开始下降?是否对应版本发布、运营活动结束?
- 用户维度:新用户 vs 老用户?哪个渠道的留存下降了?
- 行为维度:留存用户和流失用户的行为差异(用了哪些功能?)
- 外部因素:竞品促销、节假日效应、应用商店排名变化
Q2: 留存率和流失率是什么关系?
答案:
流失率 = 1 - 留存率(同一时间窗口下)- Day 7 留存率 25% → Day 7 流失率 75%
- 但注意:留存率讲的是回来的,流失率讲的是没回来的
Q3: 什么是 Aha Moment?和留存有什么关系?
答案:
- Aha Moment:用户第一次感受到产品价值的时刻
- 经典案例:Facebook 发现"7 天内加 10 个好友"的用户留存显著更高
- 分析方法:对比留存用户和流失用户的早期行为,找到差异最大的特征
- 找到 Aha Moment 后,产品引导用户尽快完成该行为
Q4: N-day 留存和 Unbounded 留存的区别?
答案:
| 类型 | 计算 | 特点 |
|---|---|---|
| N-day | 恰好第 N 天回来 | 精确但波动大(周末效应) |
| Unbounded | 第 N 天或之后回来 | 平滑但偏高 |
- N-day 适合日常监控
- Unbounded 适合向上汇报(数字更好看且更稳定)
Q5: 如何用 SQL 计算留存矩阵?
答案:
留存矩阵(Cohort × Day)
WITH first_visit AS (
SELECT user_id, MIN(event_date) AS cohort_date
FROM user_events
GROUP BY user_id
)
SELECT
f.cohort_date,
COUNT(DISTINCT f.user_id) AS cohort_size,
-- 每个 day_diff 的留存率
ROUND(COUNT(DISTINCT CASE WHEN DATEDIFF(e.event_date, f.cohort_date) = 1
THEN e.user_id END) * 100.0 / COUNT(DISTINCT f.user_id), 1) AS d1,
ROUND(COUNT(DISTINCT CASE WHEN DATEDIFF(e.event_date, f.cohort_date) = 3
THEN e.user_id END) * 100.0 / COUNT(DISTINCT f.user_id), 1) AS d3,
ROUND(COUNT(DISTINCT CASE WHEN DATEDIFF(e.event_date, f.cohort_date) = 7
THEN e.user_id END) * 100.0 / COUNT(DISTINCT f.user_id), 1) AS d7,
ROUND(COUNT(DISTINCT CASE WHEN DATEDIFF(e.event_date, f.cohort_date) = 14
THEN e.user_id END) * 100.0 / COUNT(DISTINCT f.user_id), 1) AS d14,
ROUND(COUNT(DISTINCT CASE WHEN DATEDIFF(e.event_date, f.cohort_date) = 30
THEN e.user_id END) * 100.0 / COUNT(DISTINCT f.user_id), 1) AS d30
FROM first_visit f
LEFT JOIN user_events e ON f.user_id = e.user_id
GROUP BY f.cohort_date
ORDER BY f.cohort_date;