首页 / 资讯中心 / 文章详情

从 Salesforce 收购 Braze 谈起:客户互动平台的核心架构——事件驱动触发引擎与多触点归因

从 Salesforce 收购 Braze 谈起:客户互动平台的核心架构——事件驱动触发引擎与多触点归因 ★ FEATURED ARTICLE
一、为什么行业愿意为客户互动层付 57 亿美元抛开交易细节本篇不做交易解读也不涉及任何厂商对比这个收购案传递的行业信号值得技术人员关注营销技术的价值重心正在从内容生成转向链路编排。一个典型的增长系统包含四层用户数据层身份 / 行为 / 标签 ↓ 触发编排层事件 → 规则 → 旅程 ← 收购案指向的正是这一层 ↓ 触达通道层SMS / Email / WhatsApp / Push / RCS ↓ 归因与度量层触点 → 转化 → LTV很多团队的现状是四层都有工具但层与层之间靠人肉导表和定时脚本连接。数据的时效是 T1触发的时效是运营同学上班后归因的口径是最后一次点击。客户互动平台的工程本质就是把这四层之间的连接自动化、实时化、可度量。下面拆两个最核心的模块。二、事件驱动的触发引擎2.1 事件模型一切触发的起点是行为事件。统一的事件模型是整个体系的地基{eventId:evt_01HXY...,userId:u_88231,anonymousId:anon_5f2a,// 未登录阶段的行为也能关联event:cart_updated,properties:{cart_value:86.50,currency:USD,items:[{sku:lipstick-07,qty:1}],country:US},timestamp:2026-10-28T03:15:42Z,source:web// web / app / store_pos / crm}两个容易踩坑的设计点source字段必须保留线下 POS、门店扫码产生的事件与线上事件走同一条管道才能支撑线下获客、线上复购的链路anonymousId与userId的合并identity resolution用户先匿名浏览、后注册登录两段行为要能归到同一个人否则触发会漏、归因会错。2.2 触发规则声明式而非硬编码触发逻辑不要写死在业务代码里用声明式规则描述运营可配、系统可审计fromdataclassesimportdataclass,fieldfromdatetimeimportdatetime,timedeltaimportredis,json rdbredis.Redis(decode_responsesTrue)dataclassclassTriggerRule:name:strevent:str# 监听的事件类型condition:callable# 事件属性过滤delay_seconds:int# 触发延迟channels:list[str]# 渠道尝试顺序cooldown_key:str# 冷却键防骚扰cooldown_hours:int24CART_ABANDONTriggerRule(namecart_abandon_v3,eventcart_updated,conditionlambdap:p.get(cart_value,0)30,delay_seconds7200,# 2 小时channels[whatsapp,email,sms],cooldown_keycart_abandon,cooldown_hours48,)2.3 消费事件 → 判定触发defon_event(evt:dict,rule:TriggerRule):ifevt[event]!rule.eventornotrule.condition(evt.get(properties,{})):returnuser_idevt[userId]cooldownftrigger:cd:{rule.cooldown_key}:{user_id}# 1) 防骚扰冷却期内不重复触发NX 原子操作ifnotrdb.set(cooldown,1,nxTrue,exrule.cooldown_hours*3600):return# 2) 延迟触发延迟期内用户完成下单则取消cancel_keyftrigger:cancel:{rule.name}:{user_id}rdb.setex(cancel_key,rule.delay_seconds,1)schedule_delayed(rule.name,user_id,evt,rule.delay_seconds)defexecute_trigger(rule_name:str,user_id:str,evt:dict,rule:TriggerRule):延迟到期后的实际执行再次校验取消标记与静默时段。ifrdb.exists(ftrigger:cancel:{rule_name}:{user_id}):return# 用户已下单不骚扰ifin_quiet_hours(evt[properties][country]):reschedule(rule,user_id,evt,to_local_morning)# 顺延到当地上午send_via_fallback_chain(user_id,rule.channels,templateftpl_{rule.name},vars_evt[properties])defon_order_paid(evt:dict,rule_name:str,user_id:str):下单事件到达时撤销未执行的触发。rdb.delete(ftrigger:cancel:{rule_name}:{user_id})2.4 三个生产环境的硬约束冷却必须先于一切发送同一用户同一场景在冷却期内只能触发一次SET NX保证并发下也不重复静默时段quiet hours按用户本地时区计算而不是服务器时区——深夜发送营销消息是合规与体验的双重事故取消语义要覆盖所有出口用户在延迟期内完成下单、退订、账号注销任何一条都应该让 pending 的触发失效。三、旅程编排从单点触发到状态机单点触发只解决一条消息真正的客户互动平台要编排一段旅程。新客欢迎序列是典型的状态机WELCOME_JOURNEY{start:{on:user_registered,next:day1_intro,wait_h:0},day1_intro:{action:send_intro,next:day3_tips,wait_h:48},day3_tips:{action:send_tips,next:day7_offer,wait_h:96,skip_if:lambdau:u.get(has_purchased)},# 已购买则跳过day7_offer:{action:send_offer,next:None},}defadvance_journey(user_id:str,state:str,user:dict):nodeWELCOME_JOURNEY[state]ifnode.get(skip_if)andnode[skip_if](user):statenode[next]andnext_state(state)ifnode.get(action):send_with_consent(user_id,node[action])# 每一步都过授权校验ifnode.get(next):schedule(statenode[next],delay_hnode[wait_h])旅程设计的三条原则每个节点都可跳过skip_if用户行为好于预期时旅程要让路而不是照本宣科每个动作都过授权校验营销类节点必须验证授权状态撤回立即生效旅程有终点所有序列必须有明确的退出条件完成购买、N 天无互动退场避免无限续命的消息轰炸。四、多触点归因别让报表骗了你4.1 为什么最后一次点击是错的简报里提到的 LinkedIn B2B 转化追踪讨论本质是归因问题B2B 与高客单价场景中决策链条长、触点多、决策人不止一个。只按最后一次点击归因会系统性地低估内容与早触点的贡献。典型场景用户先看了教程视频内容触点、加了 WhatsApp 咨询对话触点、收到弃购提醒自动化触点、最后搜索品牌词下单搜索触点。last-click 归因会把 100% 功劳记给搜索于是预算被砍向内容与自动化——恰恰是真正推动转化的部分。4.2 触点表与归因实现CREATETABLEtouchpoints(id BIGSERIALPRIMARYKEY,user_idVARCHAR(64)NOTNULL,touch_time TIMESTAMPTZNOTNULL,channelVARCHAR(24)NOTNULL,-- search / social / email / whatsapp / sms / storecampaignVARCHAR(64),content_idVARCHAR(64),interactionVARCHAR(24)NOTNULL-- view / click / reply / form_submit / visit);CREATEINDEXidx_tp_user_timeONtouchpoints(user_id,touch_time);-- 多触点归因对比last-click vs 线性 vs 位置加权40/20/40WITHjourneysAS(SELECTuser_id,channel,ROW_NUMBER()OVERw_descAStouch_desc,-- 从后往前ROW_NUMBER()OVERw_ascAStouch_asc,-- 从前往后COUNT(*)OVER(PARTITIONBYuser_id)ASn_touchesFROMtouchpointsWHEREtouch_time:period_startANDtouch_timeconversion_time WINDOW w_descAS(PARTITIONBYuser_idORDERBYtouch_timeDESC),w_ascAS(PARTITIONBYuser_idORDERBYtouch_timeASC)),weightedAS(SELECTchannel,SUM(CASEWHENtouch_desc1THEN1.0ELSE0END)ASlast_click,SUM(1.0/n_touches)ASlinear,SUM(CASEWHENtouch_desc1ORtouch_asc1THEN0.4ELSE0.2/GREATEST(n_touches-2,1)END)ASposition_basedFROMjourneysGROUPBYchannel)SELECTchannel,ROUND(last_click,3)ASlast_click_credit,ROUND(linear,3)ASlinear_credit,ROUND(position_based,3)ASposition_credit,-- 两种口径的差距越大说明 last-click 误导越严重ROUND(position_based-last_click,3)ASmisattribution_gapFROMweightedORDERBYmisattribution_gapDESC;misattribution_gap是这个查询真正的产出差距大的渠道就是被 last-click 报表系统性低估的渠道——通常是内容、WhatsApp 咨询、自动化触达这些中间触点。4.3 归因落地的三个务实建议先做触点采集的完整性再谈归因模型线上事件埋点容易WhatsApp 对话、线下扫码、门店 POS 这些触点经常缺失缺触点的归因是精确的错误多模型并排看不迷信单一模型last-click / linear / position-based 一起输出看趋势与差距而不是绝对值归因结果驱动预算而不是汇报每季度按多触点口径重新分配一次渠道预算跑两轮后与 last-click 口径的结果对比。五、疲劳度控制被大多数自建系统忽略的模块触发引擎与旅程编排上线后最容易出的事故不是 bug而是过度触达用户同时命中三条旅程 两个触发规则一天收到五条消息。defcan_deliver(user_id:str,scene_priority:int)-bool:每日触达上限 场景优先级豁免。day_keyffreq:{user_id}:{datetime.utcnow():%Y%m%d}countint(rdb.get(day_key)or0)ifscene_priority1:# OTP / 支付 / 物流不占额度returnTruereturncount3# 营销类每日上限 3 条defmark_delivered(user_id:str,scene_priority:int):ifscene_priority1:rdb.incr(ffreq:{user_id}:{datetime.utcnow():%Y%m%d},1)rdb.expire(ffreq:{user_id}:{datetime.utcnow():%Y%m%d},172800)配套的监控指标单用户日均触达条数分布P95 不超过上限、多旅程并发命中率命中即提示旅程设计冲突、退订率按场景拆分哪条旅程在赶走用户。六、小结收购案的价值判断留给市场但对技术团队的启示很明确——客户互动平台的护城河不在某个单点功能而在链路的完整与实时事件层统一模型 线下触点接入 身份合并编排层声明式触发规则 冷却/静默/取消三件套 可跳过的旅程状态机度量层完整触点采集 多模型归因并排 用归因差距修正预算守护层疲劳度控制与退订率监控防止系统性地把用户触达走。这四层做扎实无论外部工具生态怎么变你的增长基础设施都在自己手里。本文为工程实践总结代码为通用示意涉及交易报道处据 MarTech 10 月 22 日报道请以官方公告为准。全渠道触达与自动化编排能力可参考環球觸達Universal Touch通信 API 与 Reach2Sell 平台文档。
阅读完成 · 觉得有帮助?
咨询建站