Brevo 数据导出与迁移:如何把数据搬进来或搬出去
从 Brevo 导出联系人、统计数据和日志,弄清哪些内容根本无法转移,并按照分步清单完成任一方向的迁移。
“brevo data export migration to another platform”这类搜索词背后只有一个担忧:积累下来的数据放进去容易,拿出来难。关于 Brevo,诚实的答案是:大部分数据能干净地导出,一部分导出后形态需要重建,还有一小部分虽然重要却根本搬不走。
本文覆盖两个方向。它逐项列出哪些能导出、哪些不能,给出账号规模超出界面承载能力时该用的 API 调用,以及一份把抑制名单和发送信誉当作头等大事而非事后补丁的迁移清单。
你真正能从 Brevo 导出什么
| 数据 | 导出方式 | 格式 |
|---|---|---|
| 联系人和属性 | Contacts 页面导出,或 POST /v3/contacts/export | CSV |
| 列表归属 | 按列表逐个导出,或使用 _listIds 元数据字段 | CSV |
| 订阅状态 | 导出任务上的 exportSubscriptionStatus | CSV |
| 营销活动统计 | 营销活动报告导出,或 GET /v3/emailCampaigns | CSV、PDF、JSON |
| 事务性事件日志 | GET /v3/smtp/statistics/events 或批量导出任务 | JSON、CSV |
| 模板 | GET /v3/smtp/templates 返回 htmlContent | JSON |
| 公司和商机 | 从对应的 CRM 页面导出 | CSV |
联系人和属性
界面路径是 CRM,然后 Contacts。要导出整个数据库,确保没有加载任何列表或客户细分,也没有应用筛选条件。要导出某一个列表或客户细分,先点击“Load a list or segment”并选中它。
接着选择要包含哪些标准属性和自定义属性。EMAIL、最后修改日期和创建日期默认选中,其余需要你自己勾选,这一步也是最常出错的地方。选好 CSV 字段分隔符,分号或逗号,还可以打开“Send export by email”,让下载链接发到账号所有者的邮箱。点击“Start export”,然后从账号名称旁边的通知铃铛处下载文件。
列表和客户细分
列表以归属关系的形式导出:按列表逐个导出,或者在一次完整导出里包含 _listIds 元数据,之后再拆分文件。GET /v3/contacts/lists 会给出列表名称、id 和文件夹 id,方便你在另一端重建结构。
客户细分是另一回事,这也是第一个真正的缺口。GET /v3/contacts/segments 只返回 id、segmentName、categoryName 和 updatedAt。定义客户细分的筛选条件并不对外暴露。你可以导出某个时间点上客户细分的成员,但产生这些成员的规则只能从屏幕上读出来,再在新工具里手动重建。注销账号之前,把每一个客户细分都截图存档。
营销活动统计
在营销活动报告里,你可以把数据导出为 CSV,邮件和短信报告还提供 PDF 版本,便于分享或打印。要做完整的历史拉取,GET /v3/emailCampaigns 接受 statistics 参数,取值为 globalStats、linksStats 或 statsByDomain,再配一组 startDate 和 endDate,跨度最长两年。
事务性日志
两条路径,窗口不同。
GET /v3/smtp/statistics/events 按类型返回单条事件(delivered、opened、clicks、hardBounces、spam、unsubscribed 等)。日期范围不能超过 90 天,如果既不传范围也不传 days 参数,默认取过去 30 天。
批量方面,POST /v3/webhooks/export 会针对过去 7 天的原始事件创建一个导出任务,每 7 天周期上限 20 个导出任务。它返回一个 processId,完成后回调你的通知 URL,并交付包含 date、email、event、message-id、reason、sending_ip、subject、tag 和 template_id 等列的 CSV。数据量大时会以多个 CSV 文件的压缩包形式送达。
实际后果是:如果你想要超过 90 天的事务性历史,那本来就应该一直按计划导出。现在就把这个任务建起来,别等到决定离开的那一周。
哪些东西带不走
这是大多数迁移指南跳过的部分。
- 自动化工作流的结构。 API 可以通过事件触发自动化,但没有任何有文档记载的端点能反向读出工作流的分支、延迟和条件。每一条工作流都要在新平台上手动重建。
- 客户细分的筛选条件定义。 同上,只有名称和当前成员可以取回。
- 完整的单个联系人互动历史。 你可以在导出端点上用
customContactFilter导出某次营销活动的打开者、点击者、未打开者、退订者、硬退信或软退信。拿不到的是一份整齐的“这个联系人有史以来的每一次打开和点击”文件,因为原始事件端点被限制在 90 天内。 - 模板的渲染还原度。
htmlContent能干净导出,但拖拽区块、合并标签语法和退订链接占位符都是平台专有的。导出的 HTML 是起点,不是成品模板。请为在新编辑器里重新测试每一个模板留出时间。 - 送达率信誉。 发件人信誉存在于发送 IP 和经过认证的域名上。新平台意味着新 IP 池、新预热。保留同一个域名和 DKIM 配置能保住信誉的域名侧,这确实有实质帮助,但带不走 IP 侧。
- 表单、着陆页和跟踪标识。 注册表单、着陆页和跟踪脚本都带有平台专有 id。嵌在你网站上的东西都要替换,绑定这些 id 的分析在切换时会全部失效。
大账号的脚本化导出
大约 10 万联系人以上,界面导出会变得又慢又别扭,而且你本来就需要一个可重复执行的任务。联系人导出端点是异步的:它接受一个筛选条件,返回一个进程 id,完成后把 CSV 交给你。
curl --request POST \ --url https://api.brevo.com/v3/contacts/export \ --header 'accept: application/json' \ --header 'content-type: application/json' \ --header 'api-key: YOUR_API_KEY' \ --data '{ "customContactFilter": { "actionForContacts": "allContacts" }, "exportMandatoryAttributes": true, "exportAttributes": ["FIRSTNAME", "LASTNAME", "SMS", "COUNTRY"], "exportMetadata": ["_listIds", "ADDED_TIME", "MODIFIED_TIME"], "exportSubscriptionStatus": ["email_marketing", "sms_marketing"], "exportDateInUTC": true, "notifyUrl": "https://example.com/hooks/brevo-export" }'调用成功会返回 HTTP 202,响应体里带一个 processId。exportMandatoryAttributes 默认为 true,覆盖 EMAIL、ADDED_TIME 和 MODIFIED_TIME,所以自定义字段要写在 exportAttributes 里。设置 exportSubscriptionStatus 才会把邮件和短信的营销授权状态写进文件,漏掉它是人们产出一份对合规迁移毫无用处的导出文件的头号原因。
如果你更愿意分页拉取而不是等待任务,GET /v3/contacts 支持 limit 最大 1000 配合 offset,还有 modifiedSince 和 createdSince 用于增量拉取。每个联系人会带回 emailBlacklisted、smsBlacklisted、listIds、listUnsubscribed 和 consentGroups,重建授权状态所需的一切都在里面。
写脚本时留意速率限制。标准套餐下联系人端点允许每小时 36,000 次请求、每秒 10 次,Professional 和 Enterprise 层级翻倍,而大多数其他端点是每小时 100 次。按每页 1000 条分页拉取一百万联系人是 1000 次请求,在联系人预算里绰绰有余,但在循环里猛敲营销活动或模板端点就不行了。
为什么抑制名单必须最先迁移
在搬任何东西之前,先把退订名单搬过去。
法律上的道理很简单。退订的联系人撤回的是对你的品牌的授权。这项撤回不会因为你换了供应商而重置。在 GDPR 下,授权及其撤回的记录是你作为控制者的义务;在 CAN-SPAM 下,退订必须在十个工作日内生效,并且永久有效。在迁移中弄丢这份名单不是技术事故,而是一次留有书面痕迹、直指你的合规失败。
送达率上的道理在实践中更糟。被抑制的地址里,投诉过、硬退信过或者主动要求退出的人占比极高。用一个毫无信誉的全新 IP 给他们发信,是让全新发送配置在第一周就被限流或封禁的最快已知方法。几千个被回收的垃圾邮件陷阱地址和投诉者,就能毁掉一个月的谨慎预热。
所以要明确导出被抑制的人群,而不是指望它们被隐含带上。在导出端点上,actionForContacts 接受 unsubscribed 表示以任何方式被屏蔽的联系人,unsubscribedPerList 表示退出某一个具体列表的联系人。硬退信要按营销活动单独再跑一遍。进入新平台时,把这份文件导入它的抑制名单,而不是可发送列表。
Brevo 也处理反向场景:它支持导入被屏蔽联系人的名单,导入 API 接受 emailBlacklist 和 smsBlacklist 布尔值,让导入的文件直接落成抑制状态。注意 Brevo 坚持的一处不对称,而且它是对的:联系人不能被批量解除屏蔽,因为批量重新订阅一个要求别打扰他的人是违法的。抑制很容易添加,被刻意设计成很难移除。请把这当作正确行为,而不是障碍。
迁移清单,从 Brevo 搬出
- 盘点。 清点联系人、列表、客户细分、活跃的自动化、模板和集成。写下哪些集成会往 Brevo 里写数据,因为那些正是你必须重新接线的管道。
- 导出。 带全部属性和订阅状态的联系人,每个列表一个文件或一个带
_listIds的单文件,抑制人群作为独立文件,营销活动统计,90 天窗口允许范围内的事务性事件,以及模板 HTML。 - 归档会过期的东西。 任何有时间边界的数据(原始事件、日志)在窗口滚过后就没了。现在就存进你自己的数据仓库或对象存储。
- 清洗和映射。 去重,统一日期和电话格式,为新平台写一份明确的列到字段映射。这也是顺手删掉一年没有互动的地址的自然时机,比花钱预热一堆死重量便宜得多。我们的邮件列表清理指南讲了具体阈值。
- 先加载抑制名单。 把退订和硬退信导入新平台的抑制名单,核对数量与导出一致,然后才加载可发送联系人。
- 预热。 从互动最活跃的客户细分开始,逐步加量,每天盯住退信率和投诉率。我们的邮件送达率指南有详细的节奏安排。
- 并行运行。 让 Brevo 继续在线并发送关键的事务性邮件,同时让新平台承担越来越大比例的营销发送。不要两边同时切换。
- 验证。 核对联系人数量,逐字段抽查二十个联系人,用一次测试发送确认被抑制的联系人确实被抑制,并把一周的发送量与旧平台对比。
- 切换并保留回滚方案。 在有人盯着的时间窗口内修改 DNS 和集成端点。切换之后,至少再让 Brevo 账号保持有效并付费一个完整计费周期,同时把导出的文件存放在两个平台之外。这,而不是供应商的承诺,才是你真正的回滚方案。
从其他平台迁入 Brevo
同一份清单反过来跑,另有三点与 Brevo 相关的注意事项。
从原有供应商那里拿到一份真正的导出。 大多数平台会把联系人及其自定义字段给你,格式是 CSV。要专门索取抑制名单和退信名单,它们常常在一份单独的导出里,而人们经常忘了要。如果你来自按联系人计价的模型,用我们的 Brevo 价格指南比一比迁入之后实际要付多少钱。
上传之前先做字段映射。 Brevo 的属性是有类型的(文本、数字、日期、布尔、类别),日期落进文本属性之后就没法用来筛选了。先用正确的类型创建属性,再导入。
有点规模就走 API 导入。 POST /v3/contacts/import 接受 fileBody 里的内联 CSV、jsonBody 里的 JSON 数组,两者上限约 10 MB,或者通过 fileUrl 指向远程文件,另外还有 listIds 或一个 newList 对象。updateExistingContacts 默认为 true,按邮箱匹配。先跑一次把 emailBlacklist 设为 true 的导入处理抑制文件,再跑第二次导入可发送联系人。完整可用的脚本在我们的用脚本把 CSV 联系人导入 Brevo指南里。
然后重建那些没能转移的东西:自动化、客户细分、表单和模板。在给任何真实用户发信之前,先向几家邮箱服务商发一轮种子测试。
别让下一次迁移又变成悬崖
平台迁移之所以像跳崖,是因为平台已经变成了记录系统。订单历史、订阅者状态和营销活动结果都住在同一家供应商里面,搬走就等于一次撤离。
另一条路是自己保有事实来源,让发送平台成为一个目的地而不是保险库。如果你的店铺数据、授权状态和互动事件持续同步进自己的系统,那么切换或新增一个渠道就是一次配置修改,而不是一个项目。这正是 Tajo 在 Brevo 和商家技术栈之间做的事:让数据双向流动,使平台永远不是唯一的副本。
无论如何,上面描述的导出任务现在就值得按计划跑起来,不管你是否打算离开。最便宜的迁移,是当你决定要走的时候,数据早已在平台之外。