大部分弃购挽回靠邮件。电话的做法不一样,因为电话是唯一需要判断的分寸。给已经 买了的人发封邮件,无伤大雅;给这个人打电话,对双方都是糟糕的一分钟。
所以这篇指南的大部分内容不是讲怎么拨号,而是讲在此之前必须成立的每一件事: 确实存在一笔结账、对方确实没买、现在不是对方的深夜、对方从未要求你别再打来、 而且你对名字的了解足够用来开场。
预留半小时。大部分时间花在 Shopify 上,不在这里。
简短版
- 创建一个 Shopify 应用,勾选四个权限,并安装它
- 从 Shopify 复制两个不同的密钥
- 把两个都作为连接保存到 Omni Octo
- 让 Octo 搭建流程
- 复制 webhook 地址,粘贴到 Shopify,贴两次
- 用一分钟等待时间做测试
卡住人的是第 1 步和第 5 步。它们各有单独的章节。
第 1 步 — 创建 Shopify 应用并安装
在 Shopify 中:设置 → 应用和销售渠道 → 开发应用 → 创建应用。起一个你 以后认得出来的名字。
勾选这些权限
打开配置 → 后台 API 集成 → 配置,授予:
| 权限 | 用途 |
|---|---|
read_orders | 查明这位购物者最终有没有下单 |
read_all_orders | 对超过 60 天的订单做同样的核查 |
read_customers | 对方的姓名和电话号码 |
read_products | 读取购物车里有什么 |
你会想找一个结账权限,但找不到。 read_checkouts 确实存在,但 Shopify
把它列为受保护权限:它不在你能勾选的列表里,申请它需要 Shopify 本身的审批。
如果没有它就去调用结账 API,Shopify 会回答:
This action requires merchant approval for
read_checkoutsscope.
这没关系,而这正是本流程从不读取结账的原因。它改问一个更好的问题 —
有没有出现订单? — 这只需要 read_orders。
安装它
这一步所有人都忘。 配置应用不会有任何效果,直到你在应用的 Overview 页面 按下安装应用。在那之前,没有可复制的后台 API 访问令牌,后续每一步都会 失败,而且失败的样子像是别的东西坏了。
复制两个密钥,别搞混
你需要两样不同的东西,而且它们都长得像随机字符串,很容易混淆。
| 东西 | 在哪里 | 作用 |
|---|---|---|
| 后台 API 访问令牌 | 应用的 API 凭据标签页,安装之后。以 shpat_ 开头 | 让 Omni Octo 向 Shopify 提问 |
| Webhook 签名密钥 | 设置 → 通知 → Webhook,页面底部 | 让 Omni Octo 验证 Shopify 发来的消息 |
一个用来和 Shopify 对话。一个用来核实消息真的是 Shopify 发的。把它们弄混是 整套配置里代价最高的错误,而且症状和原因毫无相似之处 — 见 当什么都没有发生时。
第 2 步 — 把两个密钥都保存到 Omni Octo
进入连接页面,一次添加一个。
后台 API 访问令牌。 按新建连接,选”其他”下的 HTTP / API 密钥
卡片。粘贴 shpat_ 令牌。给连接起一个在列表里认得出的名字 — “Shopify 后台
API 令牌”比”Shopify”好。
Webhook 签名密钥。 再按一次新建连接,选 Signing secret,然后粘贴 通知页面上的密钥。表单上写着值得记住的那句话:
The secret the sender signs with, not a key you call them with.
两个连接,两个方向。在搭建任何东西之前,把两个都保存好。
第 3 步 — 让 Octo 搭建流程
自动化不是你写的。打开聊天,把想要的东西描述出来,包括把购物者保存为联系人 那部分:
当有人在我的 Shopify 店里弃购时,等大约三十分钟再打电话。先把这个人保存为 联系人,带上姓名和电话号码,让智能体能直呼其名地打招呼。用我的 Shopify Cart Recovery 智能体,从 +1 555 0100 打出。
联系人那部分要说出声。 不说的话,Octo 也会搭出一个能跑的流程,但智能体 开场会是「你好」而不是「你好,Sarah」— 因为问候语里的名字取自你的联系人记录, 而不是 Shopify 的消息。多说这一句,就是挽回电话和陌生推销电话的区别。
Octo 会读取你的连接、找到你的智能体,如果你保存了不止一个签名密钥,它可能 会问用哪一个。回答签名密钥,不是后台令牌。
然后确认它显示为活动中。 仍标记为草稿的流程会拒绝 Shopify 发来的一切, 而 Shopify 的投递日志里会堆满看起来像地址写错了的失败。
第 4 步 — 把地址交给 Shopify
打开流程,在图上方找到 Webhook endpoint 卡片。它显示地址和一个状态:
- Ready — 已上线,且已保存签名密钥
- Inactive — 已暂停或仍是草稿,所以 Shopify 的消息会被拒绝
按 Copy。然后在 Shopify 里进入设置 → 通知 → Webhook → 创建 Webhook,创建两个,都粘贴同一个地址:
| 事件 | 格式 | 原因 |
|---|---|---|
| 结账创建 | JSON | 有人进入结账时触发 |
| 结账更新 | JSON | 有人填入更多信息时触发 |
为什么要两个,说白了
有人刚开始结账,Shopify 就会通知你 — 而那往往还在对方输入电话号码之前。 对方每填一项,Shopify 就再通知一次,而后来的某条消息通常就是带号码的那条。
只订阅第一条,你的流程启动时没有人可打。两条都订阅,就有人可打。
同一个下拉菜单里还有购物车创建,听着对,其实不是。购物车只是个篮子 — Shopify 没有它的邮箱、电话和姓名,所以无人可打。只有当你想要一个无害的信号 来确认 webhook 确实在到达时,才用它。
这些 webhook 要在 Shopify 后台的这一页手工创建。 不要通过 Shopify API 创建。两种我们都测过:在这一页创建的大约三十秒内就到了;通过 API 创建的, 一个多小时里一条也没到,而且 Shopify 两种情况都不报错。
在其中一条上按发送测试。一分钟内,流程的运行列表里应该出现点什么。这 一次点击是证明链路通了最快的方式,而且不花一分钱。
第 5 步 — 一分钟内测试
让 Octo 把等待时间改成一分钟。
先把你自己的电话号码放到一条客户记录上。 在 Shopify 中:客户 → 选一个用你邮箱的客户,或新建一个 → 添加你的电话号码并保存。
要在下单之前做这件事。只在结账页面里输入电话号码不行 — Shopify 的单页 结账在付款之前没有提交它的步骤,你在那里输入的号码可能根本到不了 Shopify。 我们为此浪费了一个晚上。客户记录上的号码从第一条消息起就随结账一起传递, 这才让测试成立。
然后:
- 以该客户身份登录你的店面
- 把商品加入购物车
- 进入结账,让页面加载出来
- 关闭标签页
Shopify 送出消息后大约一分钟,你的手机应该会响。你不需要在结账表单里填写 任何东西。
然后让 Octo 把等待时间改回三十分钟。 停留在一分钟,流程会打给那些还在 输入卡号的人。
当什么都没有发生时
这一节就是我们当时希望手边有的。按顺序往下查 — 每一条都是真实阻止过一次 测试的东西。
流程根本没收到东西
你按安装应用了吗? 配置权限不等于安装。
webhook 是在 Shopify 后台建的,不是通过 API? 见上文。这一条让我们 花的时间远超其他所有。
流程是活动中吗? 草稿会拒绝一切。
你是刚刚创建或编辑了流程? 给它几分钟。全新的流程在被接管的短暂时间里 会回应「尚未就绪」,而 Shopify 会自行重试。
先查 Shopify 自己的投递日志,就在你创建的那条 webhook 上。如果 Shopify 没有显示投递,问题在线路的那一侧,Omni Octo 里没有任何东西能解释它。
Shopify 发了,但流程拒绝了
几乎总是密钥用错了。用哪个密钥签名取决于 webhook 是怎么创建的,而这并不 直观:
| webhook 创建方式… | 用什么签名 |
|---|---|
| 在通知页面上手工创建 | 同一页面上的签名密钥 |
| 由某个应用通过 API 创建 | 该应用自己的 API 密钥 |
如果你照着本指南做,你要的是第一行。把流程指向第 2 步的签名密钥连接。
流程启动了,但没人被呼叫
有电话号码吗? 打开这次运行,看看到达了什么。没有号码就没有电话,这是 设计使然。
只加入购物车不够。 购物车本身什么都不会告诉 Shopify。对方必须到达结账 页面,而且 Shopify 必须有联系对方的途径 — 来自登录的账号,或来自对方填写的 内容。
输入电话号码不等于提交了它。 Shopify 的单页结账在付款前没有「继续」 按钮,所以别人输入的号码可能根本到不了 Shopify。可靠的解决办法是下一条。
在客户记录上放一个电话号码。 在 Shopify 中:客户 → 那个人 → 添加电话。登录中的购物者的号码会从第一条消息起就随结账传递,上面那些问题 就都不重要了。让我们自己的测试跑通的,就是这一个改动。
用短信登录不算数。 如果 Shopify 是发短信验证码让人登录的,那个号码属于 Shopify 的登录系统。它永远不会进入你的客户记录,你也用不了它。
在试用店或密码保护的商店上测试
你需要店面密码才能在自己的店里购物,在在线商店 → 偏好设置 → 密码 保护。
不要把 onlineStoreUrl 当作商品已发布的标志。 在密码保护的商店里,
Shopify 对每一件商品都把它报告为空,无论发布与否。我们把已经发布的商品
又发布了一遍,白白浪费时间。带上密码打开商品页面,亲眼看一下就好。
什么会拦下一通电话
四道核查。每一道都是运行安静而正确地结束的地方,而不是失败。之后你看到的 样子各不相同,所以分清哪个是哪个是值得的。
对方买了。 等待结束后,我们问 Shopify 那笔结账现在有没有对应订单。如果 有,运行停止。等待存在的全部理由就是这个:Shopify 在有人输入邮箱的那一刻 就把结账计为弃购,而那一刻对方往往还在摸自己的卡。
我们无法判断。 如果这道核查失败 — 令牌过期、权限被移除、网络问题 — 运行会不打电话就停止。往另一个方向猜,就会打给已经付过款的人。
这两种都发生在第一步之前,因为核查是触发器的一部分。所以这样停止的运行会 显示为已完成、没有运行任何步骤 — 什么都没保存,也没拨任何号。今天,运行 界面还无法写明是这两种中的哪一种;如果运行不断以无步骤完成而你期待的是电话, 先检查后台 API 连接。
那是对方的深夜。 可拨打时段来自号码的国家代码,而我们无法放入某个时区的 号码,就是一个我们不会拨的号码。跨多个时区的国家,必须每一处都是白天。
对方要求你别再打。 该号码的免打扰条目会在拨号之前拦下电话,运行记录的是 拒绝,而不是失败。
这套东西不会做什么
它不会替你创建 Shopify 的 webhook。 地址要你自己粘贴,贴两次。
它不会编造电话号码。 没有号码,就没有电话。
把挽回电话当作「至少一次」,而不是「恰好一次」。 购物者每改动一样东西, Shopify 就发一条消息,每条都启动自己的一次运行。这些运行会被归并,所以通常 只产生一通电话,但消息之间隔得够久时,仍可能出现第二通。把它指向真实客户 之前,值得先知道这一点。
保持 API 版本是新的。 后台 API 连接记录着要使用的 Shopify API 版本。 Shopify 对每个版本大约支持一年,然后不声不响地改用旧版本回应你,而不告知。 如果已经过了一年,去更新它。