外呼CRM系统:名单进来到线索出去,中间不能有黑箱
一份 Excel 发到群里,从那一刻起名单就没有状态了。这一页讲名单怎么被校验、去重、分池、按策略取出,意向怎么分档,结果怎么回写到现有系统,以及并发取号为什么会重复拨打。
问题的起点
同一份名单,被五个人各打了一遍
这不是管理疏忽,是工具的问题。一份 Excel 发到群里, 从发出去的那一刻起,它就没有状态了 —— 谁打过、打到什么程度,只在各人的记忆里。
把场景写具体。市场部导出一份两千条的名单,发到销售群。五个业务员各自下载, 各自从头开始打。客户在一天里接到同一家公司的五个电话,五个人问的问题一模一样, 第五个人还得再问一遍「请问您是本人吗」。
后果有三层。第一层在客户侧:他会标骚扰,或者直接在电话里发火。 第二层在内部:A 记下了「客户要求不要再打」,但这个信息在 A 的表格里, B 第二天照打不误 —— 退订在文件体系里不会传播。
第三层最隐蔽:线索归属会打架。谁先打的算谁的,于是没人愿意花时间做长线跟进, 所有人都去抢最容易出结果的那几十条,难啃的永远躺在表格底部。名单看起来有两千条, 实际被认真跟过的可能只有两百条。
所以外呼 CRM 系统要解决的不是「存名单」,而是让一条线索在任何时刻只有一个明确的状态、 一个明确的归属人。一条线索至少有这些状态:未拨、在拨、已拨未接、已接通、 已约时间、已拒绝、已退订。这些状态必须落在一个地方,并且在多人同时操作时不能出错。
文件做不到这件事,不是因为它不好用,是因为它没有锁、没有事务、没有历史。 下面按「名单进来 → 线索出去」的八个步骤讲,重点讲三个最容易做错的地方。
工位是空的,名单却在五个人手里同时被拨。
退订信息不传播,是最容易踩的合规坑
客户在 A 那通电话里说了「不要再打」,这句话如果只存在于 A 的记录里, 下一次外呼、下一次导入、下一个业务线都会重新打到这个号码。
退订必须以号码为单位、跨业务线生效,并且在导入环节就做比对 —— 而不是等到拨打时才发现。
全流程
从导入到跟进,八个步骤
每一步都写清了「不做会怎样」。这些不是流程洁癖,是返工的具体来源。
导入校验
号码格式与归属地、号段合法性、空号预筛、必填字段、来源与授权标记。 校验不通过的行进隔离区并给出原因 —— 两万行里错三行,直接退回整个文件是最差的做法。
去重
同批内去重,并与历史库比对。比对用的是号码摘要,不是明文。 还要先定一件事:同一号码在不同业务线,算一条线索还是两条。
分池
按来源、地区、产品线、优先级分池。池与池之间不交叉取号, 否则优先级形同虚设 —— 高优先池的号码会被低优先池的坐席先拿走。
择出队
取号策略要同时考虑:池优先级、已重试次数、上次拨打间隔、坐席技能匹配、允许拨打的时段。 只按导入顺序取号,等于把策略交给 Excel 的行号。
拨打
并发控制、单号码频次上限、同一号码的最小间隔。频次上限要按号码算, 不是按名单算 —— 同一个号码出现在三份名单里,仍然是同一个客户。
意向分级
按可解释的维度给档,输出的是档位加判定依据,不是一个无法追溯的分数。
回写
按字段映射写回你现有的系统,带幂等键,失败可重试且重试不会产生重复记录。 回写失败要告警,不能静默丢。
跟进提醒
已约时间的生成待办、到点提醒、超时未跟进回收。 回收之后线索回到池里,而不是变成某个人的死号。
导入这一步,决定了后面所有统计的可信度
最常见的偷懒是把「来源」当成一个自由文本字段,于是同一个渠道在库里写成七八种样子: 「展会」「展会A」「某展会」「线下活动」。三个月后你想算各渠道的接通率,发现算不出来。
来源必须是字典项,并且带上两个跟合规相关的标记:这批数据的获取方式, 以及有没有留下客户同意的记录。这两个标记在导入时不写,后面任何一次检查都补不回来。
分池的粒度不要太细
池子按业务逻辑分,常见的维度是来源、地区、产品线三个。分成十几个池之后, 每个池的号码量撑不起一个坐席的日拨打量,取号会跨池,优先级就失效了。 宁可少分几个池,把优先级放在池内部用权重做。
重试不是重复拨打
未接通要重试,但重试必须记在号码上,并且计入频次上限。 一个号码今天被拨了五次(不同名单、不同人),在客户看来就是五次骚扰, 在系统里却是五条互不相干的记录 —— 这是最典型的「系统看着没问题、客户已经在投诉」。
并发
「取出即出队」不是性能优化,是正确性
这一节是整页最技术的一段,但它决定了一件事:两个坐席会不会同时拨同一个号码。
冲突一定会发生
三十个坐席同时在线,每个人完成一通就取下一个。两个请求落在同一毫秒是常态, 不是偶发。如果实现是「先查询、再更新」——先选出 status 为未拨的第一条, 再把它改成在拨 —— 两个请求会在查询阶段读到同一条记录,然后各打一遍。
这个问题在测试环境几乎发现不了,因为测试时没有三十个人同时点。
把判定和占用放进同一条语句
正确做法是让数据库来保证互斥:更新时把「仍然是未拨」作为条件, 影响行数为 1 才算取到,为 0 就换下一条。或者用支持跳锁的查询语义 (行级锁加跳过已锁定行),一次取一批。两种做法都能保证一条线索在同一时刻只属于一个会话。
占用要带租约,不能永久
坐席取到号码之后没拨出去、浏览器崩了、临时被叫走 —— 这条线索会永久卡在「在拨」状态, 谁也不会再碰到它。所以占用必须带到期时间,例如九十秒;到期自动回到可拨队列, 同时把重试次数加一。没有租约的锁,迟早会把名单啃出一个洞。
跨系统的并发最容易被漏掉
业务员在 CRM 里手动点拨打,系统同时在自动外呼。两条路径如果各写各的状态, 重复拨打照样发生,而且日志里看不出冲突 —— 因为两次操作都是「合法的」。 手动拨打也必须走同一个占用逻辑。
重复拨打的三种表现
客户侧:同一家公司连续来电,间隔几分钟,接线的人还不同。
监管侧:这就是骚扰投诉的典型证据,而且系统里查不出「为什么打了两次」。
内部:两个业务员都认为自己先打的,归属争议从这一刻开始, 后面所有的绩效统计都会被质疑。
判断实现对不对,有个简单测法
用二十个并发会话同时对同一批一千条线索取号,取完之后统计: 有没有任何一条被取走两次、有没有任何一条被漏掉。两个数都应该是零。
这个测试比读代码快,也比等客户投诉便宜。
意向分级
分档的依据要说得出口
分级不是为了好看,是为了决定下一通电话由谁打、什么时候打、说什么。
客户的明确表达
主动问价格、问实施周期、问合同条款、要求发资料。这是最强的信号, 因为它是客户说的,不是系统猜的。这类表达要原话记录,不要只留一个标签。
追问的深度
问「多少钱」是浅层,问「按坐席数还是按通话量计费、超额怎么算」是深层。 追问到第二层、第三层,说明他在评估而不是敷衍。深度比次数更有意义。
拒绝理由的可挽回性
「已经有供应商,合同明年到期」可挽回;「不要再打给我」不可挽回; 「现在忙」是时间问题。三种必须分开,混成一档会让跟进策略全错。
关键字段的完整度
意向城市、预算区间、决策人是否本人、期望的时间窗口。缺其中任何一项, 下一步动作都定不下来 —— 有预算没时间窗口,你不知道该不该催。
复述确认过的信息
系统复述后客户明确点头的字段,权重高于单次提及。电话里听错一个区名、 一个金额,后续所有判断都建立在错的前提上。
通话轮次与时长只做辅助
拿时长定档会反向激励:话说得越多档越高,于是话术越来越长,客户越来越烦。 时长可以作为异常检测(过短多半是拒接),不适合作为主要判据。
允许人工改档,但必须留痕
业务员比系统更懂具体客户,改档是合理的。但改档要记录三件事:改前、改后、理由, 并且被改过的记录要自动进入抽检样本。没有这一步,分级会在三个月内退化成人情档 —— 每个人都把自己的线索往上调一档,分级就失去了区分能力。
另一个约定是「谁改谁负责」:改档之后如果线索最终没成交,复盘时要看当初改档的依据是什么。
系统对接
和你现有系统对接的三种方式
没有哪一种是「更好的」,只有哪一种匹配你现在的系统条件与团队能力。
| 对接方式 | 实时性 | 开发量 | 故障影响 | 字段灵活性 | 适用场景 |
|---|---|---|---|---|---|
| 接口双向同步 | 秒级 | 中,需按对方接口开发与联调 | 接口不可用时两边不同步,但各自仍可运行 | 高,按字段映射配置 | 有开放接口的成熟 CRM |
| 中间库(视图或表) | 分钟级 | 低,约定表结构即可 | 库不可用则两边都停 | 中,改字段要动表结构 | 内网环境、同厂商私有化系统 |
| 文件导入导出 | 小时或天级 | 最低,几乎为零 | 无,人工可兜底 | 低,字段全靠模板约定 | 无接口的老系统、过渡期 |
为什么优先选接口
只有接口能做到「一通电话结束,结果立刻回到对方的客户卡片上」。 中间库差几分钟,看起来不多,但如果业务员是在通话结束后立刻要接着打下一通, 这几分钟就足以让他看到过期状态,然后重复拨打。
接口的代价是要处理失败:超时、限流、字段校验不过。这些必须写进设计里, 而不是等上线后靠人工补录。
什么时候中间库更合适
对方的系统在内网、不开放接口、厂商又不给改,这时候中间库是唯一可行的实时方案。 前提是双方能约定表结构与写入时序,并且明确谁负责建表、谁负责清理历史数据。
文件方式只建议作为过渡。它的问题不在于慢,在于它把「同步」这件事变成了某个人的每周例行工作, 而任何依赖人记住的流程,都会在某次休假时断掉。
字段映射
一张真实的映射示例
映射不是「字段名对字段名」,中间至少要处理三件事:脱敏、枚举转换、时区。
| 本系统字段 | 类型与格式 | 目标字段 | 转换规则 | 必填 |
|---|---|---|---|---|
| lead_id | 26 位字符串 | external_id | 原样写入,同时作为幂等键 | 是 |
| phone_digest | HMAC-SHA256,64 位十六进制 | phone_hash | 不传明文;对方确需明文时走单独授权通道 | 是 |
| phone_masked | 字符串 | mobile_display | 中间四位替换为星号,用于界面展示 | 是 |
| source_channel | 枚举 | source | 按来源字典表映射,未命中写 other 并告警 | 是 |
| intent_level | 枚举 A / B / C / D | level | A 到 D 依次映射为 1 到 4;对方无此字段则不写 | 否 |
| call_result | 枚举 | last_result | 接通、未接、占线、空号、拒接;空号标记后不再重试 | 是 |
| last_call_at | ISO 8601 带时区 | last_contact_time | 统一转成对方时区,默认东八区 | 是 |
| next_follow_at | ISO 8601 | next_task_time | 空值表示不生成待办,不要写当前时间 | 否 |
| agent_id | 字符串 | owner | 按坐席对照表映射;离职坐席的线索回公共池 | 否 |
| consent_flag | 布尔 | do_not_call | 为真时对方必须置为不可拨打,且不可被后续导入覆盖 | 是 |
幂等键为什么必须有
回写失败重试是常态。如果没有幂等键,一次超时重试就会在对方系统里生成两条同样的记录, 而这两条记录会被当成两条线索分给两个人 —— 于是又回到重复拨打。
退订标记不能由导入覆盖
最后一行是最容易出事的地方。新一批名单导入时,如果字段缺失或默认为空, 退订标记会被「更新」掉。规则必须写成单向:退订只能被人工解除,不能被同步覆盖。
常见疑问
采购前最实际的五个问题
这几个问题的答案决定了项目的边界,也决定了你会不会买到一个「只做拨号」的东西。
我们已经有 CRM 了,还需要这套系统吗?
需要的是能力,不是又一个系统。多数 CRM 的强项是记录客户与商机, 弱项是批量拨打、并发取号、频次控制、意向自动分级。这几件事恰好是外呼的核心。
合理的关系是:这套系统负责「拨与判」,你的 CRM 负责「存与跟」, 两边通过字段映射双向同步。不要求你把 CRM 换掉,也不建议两边都存一份完整客户档案。
名单能帮我们找吗?
不能。名单必须是你合法持有的客户数据,买卖个人信息在国内是刑事风险,不是商务问题。 我们能做的是把已有名单洗干净:格式校验、空号预筛、跨库去重、退订比对。
如果你手上没有名单,这套系统帮不上忙 —— 它是提升存量名单利用率的工具,不是获客渠道。
一条线索能不能让两个业务员同时跟?
技术上可以,业务上不建议。两个人跟同一条线索,最常见的结局是客户接到两个版本的说法, 然后对两家都失去信任 —— 在他眼里这就是两家公司。
如果确实需要协作(例如售前加售后),做法是分角色而不是分人: 主负责人唯一,协作人只能看和加备注,不能发起拨打。
意向分级准不准,还要人工复核吗?
分级的作用是排序,不是定论。它回答「先打哪一批」,不回答「这单能不能成」。 所以判定标准要能解释:这一档是因为客户问了价格、约了时间,还是只说了「再看看」。
人工改档保留,但要留痕并进抽检。跑一段时间之后,用成交结果反查分级的区分度: 如果 A 档和 C 档的成交率差不多,说明判定维度选错了,不是坐席不努力。
客户要求退订,怎么保证以后真的不打?
退订要以号码为单位记录,并且在三个环节生效:导入时比对、取号时排除、拨打前再校验一次。 三处都做,是因为任何一处漏掉都会真的拨出去。
还有一个细节:退订标记必须是单向的,不能被后续同步或批量导入覆盖。 这一条要在字段映射里写死,不能只靠操作规范。