为Shopify的收件箱建立实时的买家信号数据管道
作者:Ashay Pathak和Selina Li
数以万计的商家使用Shopify Inbox作为单一的商业聊天应用程序,用于所有在线客户互动和员工沟通。2020年,Shopify Inbox上交流的对话超过400万次,而70%的Shopify Inbox对话是与做出购买决定的客户进行的。这促使Shopify数据团队问自己,"我们如何能帮助商家识别并将这些对话转化为销售?"
我们建立了一个实时的买家信号数据管道,在商家与他们的客户聊天时,将相关的客户背景--包括活跃的购物车活动和订单完成信息--浮现给商家。有了这些实时、高意向的客户信号,商家就知道买家在购物过程中的位置--从浏览网上商店的产品到下订单。商家可以提出更直接的问题,更好地回答客户咨询,并优先考虑更有可能转化的对话。
购物车事件的动画
我们将分享我们如何设计我们的管道,以及我们如何通过A/B测试发现对商家行为的洞察力。我们还将讨论我们如何解决流媒体解决方案的常见问题,通过利用各种Apache Beam功能处理复杂的用例,并通过实验来衡量成功。
概述
买家可以从许多不同的渠道给商家留言,如在线商店聊天、Facebook Messenger和苹果商务聊天。Shopify Inbox允许商家在一个商业聊天应用程序中管理来自不同消息渠道的客户对话。 虽然它是一个管理客户对话的伟大工具,但我们想更进一步,帮助商家优化现有对话的销售机会,并随着他们的发展优先处理对话。
Shopify Inbox的大部分对话是与做出购买决定的客户进行的。我们需要识别代表买家购买意图的信号,并在对话中的适当时间将其浮现出来。我们如何实现这一目标,是通过建立一个实时的Apache Beam管道,在Shopify Inbox中浮现高意向的买家信号。
当买家与商家有一个活跃的对话时,我们目前与商家分享两个买家信号。
- **购物车行动事件。**提供买家在购物车上的操作信息、产品细节以及购物车的当前状态。
- 订单完成事件。提供买家最近购买的信息,包括一个订单号码的URL,使商家能够在Shopify管理员(商家登录管理他们的业务的地方)中查看订单细节。
这些信号是以对话事件的形式共享的(如下图所示)。对话事件是向商家传达在对话时间内相关的背景或买家行为的手段。它们按时间顺序插入对话的信息流中,不会给商家增加大量的认知负荷。
对话事件的例子-Shopify Inbox中的购物车和订单完成事件
一般来说,购物车和订单完成事件会根据以下特点进行汇总和共享。
- 预先对话事件。发生在对话开始前14天的事件。
- 会话后事件。发生在对话开始后的事件。对话的生命周期为7天,我们将事件保持在状态,直到对话过期。
架构
为了及时向商户提供高质量的信息,我们的系统需要满足两个主要要求:低延迟和高可靠性。我们通过利用三个关键技术来做到这一点。
- Apache Kafka
- Apache Beam
- 谷歌云数据流
系统架构图
使用Apache Kafka的消息队列
对于这个管道,我们使用两种不同形式的Kafka事件。单轨列车和变化数据捕获。
单轨列车
Monorail是Shopify内部开发的一个抽象层,在生产Kafka之前,它为原始Kafka事件添加了结构。此外,该结构还支持版本控制,也就是说,如果模式产生了上游的变化,那么它就会产生更新的版本,而Kafka主题保持不变。在我们的案例中,版本控制很有用,因为它有助于确保数据的完整性。
变更数据捕获(CDC)
CDC使用binlogs和Debezium从MySQL数据库的变化数据中创建一个事件流,并支持大型记录的交付。我们管道的一些输入在本质上不是流,所以CDC允许我们通过将其转换为事件流来读取此类数据。
用Apache Beam进行实时流处理
Apache Beam是一个统一的批处理和流处理系统。Apache Beam不是用一个批处理系统来聚合几个月的旧数据,而是用一个单独的流处理系统来处理实时的用户流量,它将这些工作流程集中在一个系统中。对于我们的特定用例,即事件的性质是事务性的,重要的是系统要健壮,处理所有行为的方式,使结果总是准确。为了实现这一点,Apache Beam提供了各种功能的支持,如窗口化、定时器和有状态处理。
用于部署管道的谷歌云Dataflow
我们选择使用Google Dataflow作为Apache Beam模型的运行器。使用管理服务可以帮助我们专注于数据处理工作的逻辑组成,而不必过多地担心并行处理的物理协调问题。
高层次的系统设计
实时买方信号系统设计图
管道从CDC和Monorail摄取数据,而汇入点只写到Monorail主题。我们使用Monorail作为数据管道和依赖服务之间的标准化通信工具。下游消费者处理从我们的模型中产生的Monorail事件,构造这些事件并将其发送给Shopify Inbox的商家。
实时买家信号管道包括以下两个主要部分。
- 事件过滤工作。购物车和结账数据是交易性的,包括每个买家在购物车和结账上的互动快照。即使在非高峰期,我们每秒钟都会从购物车和结账源中读取数以万计的事件。为了减少管道的工作量并优化资源,这个工作只保留关键任务的事件(即只保留Shopify Inbox用户的相关交易事件)。
- 客户事件聚合作业。这 个工作为我们的数据管道提供了繁重的工作逻辑。它维护买家在网上商店活动的最新快照,包括最近的对话、已完成的订单和购物车的最新操作。为了确保这些信息在任何时间点都能被访问,我们依靠Apache Beam中的定时器和全局窗口的有状态处理。当买家开始对话时,事件发射规则被触发。
客户事件聚合作业是我们实时管道的核心,所以让我们深入了解这个作业的设计。
客户事件聚合任务
客户事件聚合工作的图示
如上图所示,我们在客户事件聚合作业中摄入了三个不同的输入集合,包括过滤后的对话、结账和购物车事件。所有的输入元素都是通过使用CoGroupByKey操作符_shopify_y(参见我们关于Shopify从访客设备中收集的信息的政策),对在线商店中的买家的唯一标识符进行键入。这使我们能够将所有的输入元素分组到一个单一的Tuple集合中,以方便下游处理。为了确保我们能够访问历史信息,我们利用Apache Beam中的状态,按每个键和窗口存储值,以访问最后看到的事件。由于状态会在窗口结束时过期,我们在一个全局窗口上维护密钥,这个窗口是不绑定的,包含一个单一的窗口,允许在任何时候访问状态。我们为每个客户事件流维护三个独立的状态:对话、结账和购物车状态。在新事件到来时,一个处理时间触发器被用来将一个窗口的当前数据作为窗格发射出来。接下来,我们通过PTransform中定义的逻辑来处理来自状态的最后一次事件和来自窗格的新事件。
在系统的这个阶段,在收到来自买方的新事件后,我们试图回答以下问题。
1.这个买家是否与商家有一个积极的对话?
这个问题决定了我们的管道是否应该发出任何输出,或者只是处理购物车/结账事件,然后将它们存储到其相应的状态。我们管道的业务逻辑是,只有当买家通过Shopify Inbox与商家开始对话时才会发出事件。
2.这些事件是发生在对话开始之前还是之后?
这个问题与我们如何聚集传入的事件有关。我们根据我们上面提到的两个特征来聚合事件。
- **对话前的事件:**我们显示买家在对话开始后发生的活动的交易数据。使用上面提到的同一个场景,我们向商家展示一个购物车添加事件和一个订单完成事件。
- 交谈后事件。我们展示买家在对话开始后所进行的活动的交易数据。使用上面提到的相同场景,我们向商家展示一个购物车添加事件和一个订单完成事件。
会话前事件(左)与对话后事件(右)的例子
3.买家在网上商店的最新互动是什么?
这个问题反映了我们管道的关键设计原则--我们与商家分享的信息应该是最新的,并且总是与对话有关。由于流媒体数据到达管道的性质以及购物车和结账之间的相互联系过程,它引入了我们系统中需要解决的主要问题。
在设计管道和其解决方案时,我们面临一些挑战。
购物车和结账的相互依赖性
从购物车到结账是买家购物旅程中一个紧密相连的过程。例如,当一个买家下了订单并返回到网上商店时,购物车应该是空的。这项工作的主要目标是在系统中模拟这个过程,确保在任何时候都能正确反映购物车的结账状态。挑战在于,购物车和结账事件来自不同的Monorail源,但它们相互之间有依赖关系。通过使用单一的PTransform函数,它允许我们访问所有可变的状态并在此基础上创建动态逻辑。这方面的一个例子是,当收到同一用户令牌的结账事件时,我们会清除购物车状态。
处理订单外的事件
由于我们在事件中分享的信息是累积性的(例如,购物车总价值),以正确的顺序分享买方信号事件对商家的积极体验至关重要。输出事件的顺序应基于买家与购物车和聊天互动发生的时间顺序。例如,移除物品应该总是在添加物品之后。然而,流媒体数据的常见问题之一是我们不能保证跨数据源的事件按顺序读取和处理。除此之外,购物车上的动作在源中并没有明确说明。因此,我们依靠比较交易事件之间的数量变化来提取购物车的动作。
这个问题可以通过利用Apache Beam的有状态处理来解决。状态是一个缓冲区,按每个键和窗口来存储数值。它是可变的,并随着时间和新传入的元素的变化而变化。通过使用状态,它允许我们访问以前的买方活动快照,并通过比较新事件和状态中的事件的时间戳来识别任何失序的事件。这确保了没有过时的信息被分享给商家。
垃圾收集
为了确保我们没有向状态过载数据,我们使用定时器来手动清理状态中过期或不相关的每键和窗口值。定时器被设置为使用event_time域来管理每个key和window的状态生命周期。我们用它来适应购物车的可延长的寿命。
在对话中分享买家的背景信息
对话和购物车cookies有不同的寿命。我们遇到的问题是,事件的特征可以跨时间演变。例如,一个对话后的购物车事件可以在对话到期后作为对话前的事件来共享。为了解决这个问题,我们在状态中引入了一个动态标签,以表明事件是否已经在对话中被共享。每当对话状态的定时器执行时,它将在购物车和结账状态中重置这个标签。
测试我们的管道
通过这个实时系统,我们希望通过为商家提供这些关于买家旅程的智能洞察力,使他们的对话体验更好。我们进行了一个实验,测量了对我们的KPI的影响,以验证这个假设。该实验采用了传统的A/B测试设置,我们将所有受众(使用Shopify Inbox的商家)分为两个平等的小组:对照组和治疗组。对照组的商户继续保持原有的行为,而治疗组的商户则在他们的Shopify Inbox客户端应用中看到实时的买家信号事件。我们使用以下指标来跟踪商家的体验。
-
响应率。买家对话中得到商家回复的百分比。我们观察到有两个百分点的显著增长。
-
**响应时间:**从第一个买家信息到第一个商家回复的时间。虽然我们看到响应率明显增加,但我们观察到响应时间没有明显变化,这表明商家正显示出更快的回复意向。
-
转换率。导致销售的买家对话的百分比。我们观察到0.7个百分点的明显增长。
我们的实验表明,随着这些新的买家信号被实时显示给商家,他们能够更好地回答客户的询问,因为他们知道买家在其购物旅程中的位置。更妙的是,他们能够通过回应已经在结账过程中的买家来确定对话的优先次序,帮助买家更快转化。总体而言,我们观察到对上述所有指标的积极影响。
构建实时买家信号管道的主要启示
建立一个实时买家信号数据管道来浮现相关的客户背景是一个具有挑战性的过程,但它对我们的商家产生了真正的影响。快速总结一下关键的收获。
- Apache Beam是一个适用于交易用例的系统像购物车,因为它提供了有用的功能,如状态管理和定时器。
- 处理订单外的事件是非常重要的对于这样的用例,需要一个强大的状态管理来实现。
- 受控实验是衡量主要功能变化的真正影响的有效方法并获得关于用户行为的有价值的洞察力。
Ashay Pathak是一名数据科学家,在Shopify的信息传递团队工作。他目前的工作是在对话中建立智能并改善商家的聊天体验。在此之前,他曾为一个智能产品工作,该产品使用ML向商家提供主动的营销建议。在Linkedln上与Ashay联系,进行交流。
Selina Li是信息团队的一名数据科学家。她目前的工作是在对话中建立智能,并改善商家的聊天体验。在此之前,她在自助团队工作,为Shopify帮助中心和Concierge的用户提供更好的搜索体验。请看她的上一篇博文《打造更智能的搜索产品》。评估搜索算法的3个步骤。如果你想和Selina联系,请在Linkedin上联系。
对解决具有挑战性的问题感兴趣,并能带来改变?请访问我们的数据科学与工程职业页面,浏览我们的空缺职位。
在您的收件箱中获得这样的故事!
来自构建和扩展Shopify的团队的故事。这个商务平台为全球数以百万计的企业提供动力。
电子邮件地址是的,给我登记
与我们分享您的电子邮件并接收每月的更新。
谢谢您的订阅。
您将很快收到免费的提示和资源。