NEW

免费试用已开放

立即开始

私域 · 营销 · SCRM · 客户

企业微信客户生命周期怎么建模

更新于 2026-08-168 分钟

客户生命周期在多数系统里最后长成一个下拉框:新客、跟进中、意向、成交、流失,谁想起来谁改一下,半年后一半客户挂在跟进中再也不动。问题不在选项少了,在它被当成一个标签字段,而不是一台有进入条件、退出条件和流转规则的状态机。这篇讲阶段怎么切、流转由什么驱动、回退和并发怎么处理,实现按 wecomapi 的事件回调来写。

阶段是状态机,不是标签

标签和阶段在存储上可以长得一样,语义完全不同。标签是这个人具有某个特征,可以同时挂很多个,多打一个不算错;阶段是这个人现在处在哪一格,任何时刻有且只有一个值,多一个就是数据错误。

这条差别落成三个强制项:互斥单值、每次变更必须留痕、写入方唯一。站内讲标签体系那篇把阶段归为四层里唯一需要严格串行化的一层,原因就在这儿 —— 其它层允许被覆盖重算,阶段层重算会把历史流转记录抹掉,而那份记录是后面所有转化分析的原料。

  • 阶段值域封闭,加一格要走变更流程,不能由业务临时新增。
  • 同一时刻只允许一个写入方改同一个客户的阶段,冲突时拒绝而不是覆盖。
  • 阶段本身不携带业务数据。已报价是阶段,报价金额是另一个字段;混在一起的结果是每改一次金额就触发一次阶段变更。

怎么切阶段:按动作切,别抄销售漏斗

最常见的做法是把 CRM 的商机阶段抄过来。抄出来的模型在私域场景里粒度是错的:商机阶段服务于销售预测,一格可能持续几周;私域里客户状态一天变三次,你需要的是能直接决定今天该对他做什么的划分。

判断标准只有一条:如果两个阶段对应的运营动作完全一样,它们就该合并;一个阶段如果说不出处在这里的人唯一该做的事是什么,它就不该存在。按这条筛,起步四到五格通常就够。

  1. 1待承接:已通过但没有任何人开口。唯一动作是尽快发出第一句。
  2. 2已连接未响应:发过了,对方没回。唯一动作是换个角度再试一次,且次数有上限。
  3. 3沟通中:有过双向会话。动作是推进到明确的需求,或者明确的拒绝。
  4. 4意向确认:客户表达过具体需求。动作是给方案、报价、约时间。
  5. 5沉默:一段时间内没有任何互动。动作是低频维护,不是加大频次。

另一类常见错误是把客户属性塞进阶段:大客户、小客户、行业 A、行业 B。这些是维度,不是格子 —— 它们和阶段正交,一个大客户同样会经历待承接到沉默的全过程。混进来的结果是格子数量翻倍,而且每个客户的属性一变就得改阶段,流转记录立刻失去意义。

成交和流失可以是阶段值,但不该被当成终点格:进了这两格之后还得能出来。成交客户仍然要走复购、维护、再沉默这一圈,把他们移出生命周期,等于把最有价值的一批人从所有自动化里摘掉。

流转规则:前进靠事件,后退靠超时和人

流转必须有明确的驱动源,否则阶段迟早退化成手动下拉框。合法的驱动源只有两处:wecomapi 的事件回调送来的客户侧事实,和你自己系统里的业务动作(下单、签约、工单关闭)。除此之外的顺手改一下,都要在入口上堵掉。

  • 前进由事件驱动:通过、首次发出、收到回复、命中关键意图。这些都是客观事实,不需要人判断。
  • 后退只有两个合法来源:超时降级和人工修正。普通行为事件不该触发后退 —— 客户今天没回话,不代表退回上一格。
  • 跳级要允许。第一句就问价格的客户很常见,但每次跳级都要在流转记录里标出来:如果九成客户都跳过某一格,那一格该删。

并发是这里唯一的技术难点。同一个客户在同一秒收到消息事件、又被人工改了阶段,两条路径都会写。做法是带期望前态的条件更新:当前值等于期望值才写入,否则拒绝并重新推导一次。拒绝比覆盖安全,覆盖会产生一条看起来正常、实际跳过了中间状态的记录。

示意:带期望前态的流转与幂等javascript
// 示意逻辑,事件类型与字段以 wecomapi 文档为准
async function transit(customerId, evt) {
  const cur  = await store.stage(customerId);
  const next = rules.derive(cur, evt);        // 事实 -> 阶段,规则集中在这里
  if (!next || next === cur) return;

  const ok = await store.casStage(customerId, {
    from: cur, to: next, eventId: evt.id,     // 期望前态 + 事件 ID 幂等
  });
  if (!ok) return retry(customerId, evt);     // 冲突就重推,不覆盖

  await audit(customerId, cur, next, evt);    // 每次流转都留痕
  await effects.onEnter(next, customerId);    // 进入动作与流转本身解耦
}

onEnter 这一行值得单独说:进入某一格要做的事(发消息、建任务、通知归属人)不要写进流转函数。流转是数据变更,进入动作是业务副作用,两者混在一起,以后任何一次数据修复都会重新发一遍消息。

每一格都要有停留时长上限

没有 TTL 的生命周期模型,半年后一定变成一个巨大的沟通中。给每格配一个停留时长上限、超过之后必须发生点什么,这是模型不腐烂的唯一保证。

超时的含义不是这个客户失败了,是继续按这一格对待他已经不合适。超时动作三选一,按格来定:自动降级到低频格、生成一条待人工确认的记录、或者只打一个标记不做别的。第三种看起来什么都没做,但它让卡住这件事变得可统计。

  • 各格人数分布加平均停留时长,是这套模型最有价值的两张图。哪一格越堆越多,哪一格就是当前瓶颈。
  • 停留时长要按来源渠道拆开看。同一格里不同渠道来的人停留时长差三倍,说明问题在获客不在跟进。
  • TTL 初值不用算准,取一个明显偏短的值先跑,看超时率再调。偏长的 TTL 不会报错,只会让你晚三个月发现问题。

有一个超时动作要单独排除掉:自动补一条挽回消息。它看起来是最自然的反应,实际是拿频次去补内容和时机的问题,站内讲自动触达那篇给的判断也一致 —— 连续无响应是负反馈,正确的反应是降频而不是加码。超时该触发的是重新分类,不是再发一条。

事件和阶段之间要隔一层

最容易返工的写法,是在回调处理函数里直接写「收到这个事件就把阶段改成 X」。判据一旦要改,你得改采集代码,而且历史数据没法重算。

正确的结构是三段:事件先落成事实流水(原样存,不解释),规则从事实推导阶段,阶段变更再触发动作。用 wecomapi 的事件回调订阅关系与消息事件,收到后先快速 ACK 再异步入队,消费时只做一件事 —— 把它翻译成一条带时间戳的事实记录。推导规则跑在事实之上,改判据只改规则,历史随时可以重放。

  • 事实流水保留原始报文,别只存解析后的几个字段。半年后想加一条新判据,靠的就是当初多存的那些内容。
  • 推导规则写成纯函数:输入当前阶段和一批事实,输出下一格。纯函数才能在历史数据上重跑并对比新旧结果。
  • 重放要能只算不写,先出一份差异报告让人看,确认无误再落库。

隔了这一层之后,还要加一个定时的全量重推。事件会丢、消费会失败、有些改动发生在客户端上不一定有对应事件,只靠增量推导,阶段一定会慢慢漂。做法是低峰期按事实流水把一批客户的阶段重算一遍,和当前值比对,差异要么自动纠正、要么进人工队列。这件事只有在推导规则是纯函数的前提下才成立,这也是上一条的实际用处。

落地顺序与验收

  1. 1先建阶段字段和流转日志表,什么动作都不挂。空跑两周,看分布是否合理。
  2. 2再挂只读的观测:各格人数、停留时长、超时率。这一步暴露出来的划分问题,改起来还很便宜。
  3. 3自动动作放到最末尾,而且按格逐个挂,一次一格,每挂一个观察几天。

存量客户的初始化容易被草率处理。把所有人一次性塞进第一格,第二天所有欢迎序列会同时触发;塞进沉默格,又会把正在谈的客户一起降频。可行的做法是按最近一次双向会话的时间反推初始格,推不出来的单独放一个待归类值,让人分批处理 —— 这个值可以长期存在,比强行猜一个格子诚实。

验收标准是一句话:随便点开一个客户,你能说出他为什么在这一格、上一格什么时候离开的、由哪条事实推导出来的。答不上来,说明留痕不够,先补留痕再谈别的。

本文讲的是阶段建模与流转结构。可订阅的事件类型、字段定义与调用约束以 wecomapi 线上文档为准,示意代码只表达结构,不代表任何接口的实际行为。

常见问题

阶段和标签能不能用同一套存储?
存储可以共用,写入路径不能共用。阶段需要互斥校验、期望前态和审计记录,标签不需要;把两者塞进同一个写入函数,早晚会出现一个客户同时挂着两个阶段。省下的那点代码,远不够后面对账花的时间。
阶段划分几格合适?
起步四到五格。判据是每一格都能说出处在这里的人唯一该做的事,说不出就合并。格子多的模型看起来精细,实际结果是大量客户长期停在中间格,因为连运营自己都分不清相邻两格的区别。
客户删了好友又加回来,阶段该怎么算?
客户主体保留,阶段重置到最前一格,但历史流转记录不要清。删好友是一次强负反馈,按老阶段接着推进通常会再触发一次流失。用 wecomapi 的关系变更事件把两次关系的起止时间都记下来,这段间隔本身就是判断该不该重新推进的依据。

准备好动手了?

精确字段、鉴权与端点以线上文档为准;可在控制台创建密钥后联调。

相关文章