4.3 数据看板:预约转化漏斗

场景:林姐要的不是报表,是答案

系统跑了三个月,林姐提出一个灵魂问题:每十个点进小程序的人,最后有几个真的坐到店里?我们以前的回答是一堆分散的数字:浏览量一个、下单量一个、核销量一个。数字之间没有关系,也就没有答案。

她补了一句:我不缺数字,我缺的是知道哪一步跑了人。这句话基本定义了看板的全部设计目标:不是更多数据,而是数据之间的关系。

看板要做的就是把这些散点串成一条漏斗:从看到门店页面到最终核销,每一步的转化率是多少、在哪一步流失、哪家店流失最严重。这一节讲漏斗怎么定义、数据怎么算、看板怎么搭。

方案:六个节点的漏斗

漏斗的节点定义是这套数据的灵魂。节点太少看不出问题,太多数据噪声大。我们最终定了六个节点,每个节点都能从一个确定的事件取到:

节点 事件 数据来源
门店曝光 打开门店页 页面埋点
时段选择 点击某时段 埋点
提交订单 创建订单 t_booking
支付成功 支付回调 支付流水
到店核销 扫码核销 t_verify
复购 90 天内二次核销 会员表

六段之间还有一个隐含原则:每两段之间客人能做出别的选择(离开、改期、退款),漏斗不评判这些选择的坏,只记录它们发生在哪一段。 很多客人会取消,但取消不等于失败——约不上和约了不来是两种完全不同的事。

开评审会时这套原则救过一次场:有人提出把取消的单子从漏斗里剔除以让曲线好看。林姐当场否了,说生意做的是回头客,不是报表。这段花絮后来成了团队的一条不成文规矩:数据为决策服务,不为面子服务。

六段的转化率跑出来长这样:门店曝光到时段选择 42%,时段选择到提交订单 71%,提交到支付 88%,支付到核销 82%,核销到 90 天复购 35%。每一段都有名字,每一段都能下钻到分店、分时段。

整体拉直之后的全链路转化大约是 8%——每 100 个打开门店页的人里,最终有 8 位完成核销。这个行业里算是健康的数字,但每一段拆开看都有故事:支付到核销掉的 18% 里,七成是正常改期取消,三成是末段流失。能区分这两者,才是看板真正发挥价值的时刻。

最有价值的是第二段:从看到时段到提交订单之间掉了近三成客人。林姐一开始不信,后来按客诉日志一对,全是反馈看不到合适时间的人——时段被约满后页面不刷新,客人以为没位置就走了。一个刷新策略的改动把这一段拉回 52%。

这次的教训让我们定下一条原则:漏斗里任何一段显著低于行业常识,先怀疑产品体验,再怀疑数据。数据难看往往不是客人的问题,是我们的问题。后来我们把这段经验做成了每月一次的转化率评审会,每段异常都必须给出解释或行动项。

这次刷新策略的具体改动也很不起眼:从客人打开页面后 5 秒拉一次余量,改成进入时段列表就拉、每次滚动停顿时再拉。代码量加起来不超过三十行,但客人在页面上停留的每一秒看到的都是新鲜库存。

代码:离线聚合而不是实时查询

看板查询如果直接打在业务表上,三个月的数据 group by 就把 MySQL 拖垮了。我们建了一张按天聚合的统计表,每天凌晨把昨天的数据汇总写入:

CREATE TABLE t_funnel_daily (
  stat_date DATE NOT NULL,
  shop_id   INT NOT NULL,
  node      TINYINT NOT NULL COMMENT '漏斗节点 1 到 6',
  cnt       INT NOT NULL,
  PRIMARY KEY (stat_date, shop_id, node)
);

看板的所有查询都只读这张不到两万行的宽表,任意的同环比、分店对比都是毫秒级。聚合任务是一条存储过程,带重试和幂等:跑失败重跑,跑成功重跑数据也不变(用日期加门店先删后插)。

聚合表的行数是可以算出来的:3 店乘 6 节点乘 365 天约六千行一年,五年才三万行,MySQL 闭着眼睛查。选择离线聚合的另一个原因是业务表的高峰期本来就在白天,看板查询和下单查询抢同一台 MySQL 的连接,是给自己找麻烦。

前端看板是一张纯 H5,ECharts 画的漏斗图和趋势线,嵌进企微工作台给林姐和店长看。没有酷炫的大屏,因为林姐说在手机上看清楚比在电视上震撼重要。

看板第一次给店长们看的场景记得很清楚:三家店的漏斗并排摆在屏幕上,A 店核销率 82%,B 店只有 71%。B 店店长当场表示不服,说自家客流结构不同。下钻之后发现差异出在下午时段的核销——B 店下午常被周边工地噪音影响,客人临时改期多。一个月后 B 店换了隔音窗,核销率追到 79%。数据让竞争变得有依据,而不是有情绪。

那天回家路上我想:一个看板最贵的部分不是 ECharts 也不是 SQL,是让三家店长愿意一起看同一张图的那股劲。

配置:看板的三个视角

同一张漏斗给三种角色看,视角不同下钻深度不同:

角色 默认视角 可下钻
老板 全部门店汇总 到单店
店长 本店当月 到时段段
前台 本店本周 到员工

权限体系和看板共用一套 shop_id 过滤,看板里看到的数据范围和后台完全一致。这本来是理所应当的事,但很多 SaaS 看板把权限做在看板外侧,出了一堆越权事故之后,我们把看板查询也统一过了 scope 层。

店长视角的漏斗里还藏着一个小功能:本店与全司均值对比线。谁也不想当平均线以下的那一个,这条线上线后,B 店的转化率先涨了 4 个百分点。竞争可视化是最便宜的管理工具。

老板视角里最常用的是同环比:上周和这周对齐、去年同月和本月对齐。过年那几天数据断崖,环比口径要按营业日而不是自然日对齐,否则春节周对比全是惊吓。

林姐看板的固定动作是每天早上的三分钟:先看昨日总单量,再点开分店对比,最后拉到时段段看高峰饱满度。这三个动作后来被做成了看板首页的三张卡,她现在连早餐都没吃完就刷完了。

踩坑:看板现场的四个坑

第一个坑是埋点定义不清。门店曝光是页面 onload 还是 onshow?同一客人切店来回切算几次?这些边界没写文档,前后端各自实现,第一版漏斗的曝光量虚高 60%。后来埋点字典进了代码仓库,任何埋点变更走 PR review。

第二版埋点统一成 onshow 加 3 秒停留才算有效曝光,数据立刻冷静下来。曝光量的水分挤掉之后,全链路转化率从虚的 5% 变成实的 8%,林姐说这个数字她才敢信。

第二个坑是订单状态多次变更算重。提交订单节点如果按订单创建时间,取消再改期会产生两条记录,漏斗里同一位客人被算两次。修正方式是按唯一 book_id 去重,节点计数口径统一为设备加去重。

去重逻辑上线那天,第三段提交订单的数字掉了 9%,第一次看到的时候心都凉了——还以为出 bug 了。核对半小时才确认这才是真实数字:之前的 9% 全是重复计数造成的幻觉。数据清洗往往让数字更难看,但难看的真相比好看的数据值钱。

第三个坑是聚合任务静默失败。有一周聚合任务凌晨崩了没人知道,看板数据原地停了七天,林姐在例会上拿着过期数据讲策略。从那以后聚合任务加完成回调告警,周表未更新六点前必报警。

告警上线后第二周就抓到一次真凶:聚合任务在 t_verify 关联时遇到一张时区错乱的记录(核销时间存了 UTC,显示成了隔天),group by 之后整段对不上。数据质量问题通常藏在这种边界角落,聚合任务是最好的放大镜。时区问题后来统一解决:所有时间字段一律存 MySQL 的 timestamp 自动本地化,应用层再按门店时区展示,从根上杜绝同一条记录两个解释。

第四个坑是看板数据对不上财务。漏斗里的支付成功按支付回调计数,财务按对账单计数,中间差了退款和补单。两个口径都对,但摆在一起就打架。最终看板里加了一条备注:本看板口径为业务转化,财务口径以对账单为准,并在帮助页写清差异来源。

这层窗户纸捅破之后反而无事:大家按各自口径开会,差值不超过 3% 就算正常。数据和财务的和平靠的是一张备注页,不是更精确的计数。

小结

漏斗看板是整个系统里最不技术但最被依赖的部分。它把散落的数字串成一条有因果的线,让林姐从凭感觉做决策变成看着数据做决策。第二段转化率从 42% 提到 52% 那次改动,没有改一行代码逻辑,只是让页面更勤快地刷新时段余量——数据看到的问题,解法常常朴素得不像技术方案。

做看板最大的经验是别等数据完美再上线:先用能拿到的数把漏斗画出来,边跑边校准口径。我们的第一版只有三个节点,照样救了一次业绩。

再看一眼那组数字:42、71、88、82、35。任何一段往下挖都够开三次会,但所有段的共性只有一条——让客人下一步动作更容易。看板不产生增长,看板指出增长的方向,剩下的仍是一双一双在做美甲的手。

延伸阅读