尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
使用 Dub 将 Stripe 自定义客户创建流程与点击归因关联:dubCustomerExternalId 与 dubClickId 元数据实战指南
使用 Dub 将 Stripe 自定义客户创建流程与点击归因关联dubCustomerExternalId 与 dubClickId 元数据实战指南【免费下载链接】dubThe modern link attribution platform. Loved by world-class marketing teams like Framer, Perplexity, Superhuman, Twilio, Buffer and more.项目地址: https://gitcode.com/GitHub_Trending/du/dub导读本文面向使用 Stripe 但不走 Checkout Session 标准创建流程、而是自行调用stripe.customers.create/stripe.customers.update管理客户的开发者讲解如何在 Stripe 客户对象上写入 Dub 归因元数据dubCustomerExternalId、dubClickId让 Dub 在客户产生购买后自动把订单金额、币种等信息回填到用户最初点击的链接Click Event上从而实现完整的点击 → 线索 → 销售归因闭环。读完本文你将掌握 Dub Stripe 集成的客户侧接入方式、元数据字段的确切语义以及 Dub 服务端 Webhook 处理这些元数据时的完整解析与关联逻辑。一、为什么要在 Stripe 客户上写入 Dub 元数据Dub 的 Stripe 集成核心机制是通过 Webhook 监听 Stripe 侧的事件再把事件中的金额、币种等销售信息关联回 Dub 侧已经记录的点击事件。而关联的锚点就是 Stripe 客户对象上的metadata字段。在标准流程stripe-checkout.md中你只需在checkout.sessions.create时把用户 ID 写入metadata.dubCustomerExternalIdDub 就能在checkout.session.completed事件到达时完成归因。但如果你不使用 Checkout Session而是直接在服务端创建 Stripe 客户例如自有支付页面、自定义订阅管理、B2B 记账等场景就必须在客户创建/更新流程中主动传递归因信息——这正是本文所依托文档 stripe-customers.md 的适用场景。二、核心概念两个元数据字段在 Stripe 客户对象的metadata字段中需要写入两个 Dub 约定的键元数据键含义来源用途dubCustomerExternalId你数据库中该用户的唯一用户 ID你的业务数据库如user.id让 Dub 在本地Customer记录与 Stripe 客户之间建立一一对应关系dubClickId用户在落地页产生点击事件时下发的dub_idHTTP 请求头dub_id由 Dub 的点击跟踪脚本或服务端 SDK 下发让 Dub 把新客户关联回最初带来该访客的链接与点击事件需要特别说明的是只有dubCustomerExternalId是必须的dubClickId的作用是在客户首次出现时找到对应的点击事件从而把客户挂到某个链接/合作伙伴上。从 sync-customer.ts/api/stripe/integration/webhook/utils/sync-customer.ts#L82-L96) 的源码可以看到如果 metadata 中没有dubClickIdWebhook 会返回Click ID not found in Stripe customer metadata, skipping...并跳过新客户创建而对于已存在的 Dub 客户即使没有dubClickId也能正常更新。三、获取点击 IDdub_iddub_id是 Dub 在每次链接点击事件中生成的唯一标识通过请求头dub_id随用户请求一起下发到你的服务端。在 Node.js 服务中读取方式如下const dub_id req.headers.get(dub_id);它通常配合你现有的会话体系Cookie、JWT 等一起使用用户在落地页被 Dub 跟踪后后续到达你的支付/注册接口时请求头中就会携带该用户来源对应的dub_id。四、在 Stripe 客户创建流程中写入元数据当你的后端调用stripe.customers.create创建客户时将用户 ID 作为dubCustomerExternalId、请求头中的dub_id作为dubClickId一起写入metadataimport { stripe } from /lib/stripe; const user { id: user_123, email: userexample.com, teamId: team_xxxxxxxxx, }; const dub_id req.headers.get(dub_id); await stripe.customers.create({ email: user.email, name: user.name, metadata: { dubCustomerExternalId: user.id, dubClickId: dub_id, }, });email、name可保持你原有逻辑不变dubCustomerExternalId建议使用数据库中的主键字符串如user_123保证全局唯一、稳定不变dubClickId直接透传请求头dub_id即可缺失时 Dub 端会跳过新客户创建详见下文源码解析。五、在 Stripe 客户更新流程中补充元数据如果你的应用是先创建 Stripe 客户、后补录归因信息例如用户在注册后一段时间才通过推广链接完成转化可以在stripe.customers.update中补齐同样的两个字段import { stripe } from /lib/stripe; const user { id: user_123, email: userexample.com, teamId: team_xxxxxxxxx, }; const dub_id req.headers.get(dub_id); await stripe.customers.update(user.id, { metadata: { dubCustomerExternalId: user.id, dubClickId: dub_id, }, });由于 Stripe 的metadata是整体合并写入的更新时只需携带归因相关键即可不会覆盖你已有的其他业务元数据。六、源码级原理Dub 如何消费这些元数据6.1 Webhook 入口与事件类型Dub 的 Stripe 集成 Webhook 位于 apps/web/app/(ee)/api/stripe/integration/webhook/api/stripe/integration/webhook)其中sync-customer.ts专门处理customer.created与customer.updated两类事件。这两个事件正是触发客户关联的时机客户创建/更新时Dub 会读取客户对象上的metadata。6.2 外部 ID 的解析优先级在 get-dub-customer-external-id-from-metadata.ts/api/stripe/integration/webhook/utils/get-dub-customer-external-id-from-metadata.ts#L8-L21) 中Dub 从 metadata 解析外部 ID 的顺序是dubCustomerExternalId本指南推荐的主键字段dubCustomerId旧版/兼容字段user_idLemon Squeezy 客户迁移到 Stripe 后的兼容字段解析结果为空字符串或null时返回undefined随后sync-customer.ts会返回External ID not found in Stripe customer metadata, skipping...直接跳过。6.3 客户查找、更新与创建的完整流程sync-customer.ts的实际处理链路如下从事件对象中取出stripeCustomer.metadata解析dubCustomerExternalId与dubClickId用OR条件在 Dub 数据库中查找客户(projectId externalId)或stripeCustomerId若已存在直接更新该客户的stripeCustomerId、projectConnectIdStripe Account ID、externalId并在 Stripe 提供非空值时才覆盖name/email若不存在必须存在dubClickId才会继续——通过 Tinybird 查询点击事件getClickEvent校验该链接归属同一 workspace然后调用getOrCreateCustomer创建 Dub 客户cus_前缀 ID并继承点击事件中的linkId、programId、partnerId、clickId、clickedAt、country等字段新客户创建成功后记录一条名为New customer的 Lead 事件同时递增链接的leads计数、workspace 的usage并异步触发工作流leadRecorded、合作伙伴 Postbacklead.created、workspace Webhooklead.created与 Google Ads 转化上传。并发场景下若两个 Webhook 同时创建同一客户getOrCreateCustomer的findMode: first逻辑会保证只创建一个另一个走更新分支。6.4 客户创建/更新后的销售归因当客户在后续产生购买时Dub 通过另外两个处理器完成销售归因checkout.session.completedcheckout-session-completed.ts/api/stripe/integration/webhook/checkout-session-completed.ts)读取 Checkout Session 的 metadata 或已关联客户找到该客户的 Lead 事件后记录 Saleinvoice.paidinvoice-paid.ts/api/stripe/integration/webhook/invoice-paid.ts)先用stripeCustomerId反查 Dub 客户查不到时再回连 Stripe 获取客户 metadata 中的dubCustomerExternalId通过(projectConnectId, externalId)复合唯一键更新客户并补记stripeCustomerId最后记录订阅续费/发票支付类型的 Sale 事件。两个处理器都会在 Redis 中以trackSale:stripe:invoiceId:{invoiceId}为键做 7 天幂等去重避免同一张发票被重复计入销售额。这也解释了为什么文档强调当客户产生购买时Dub 会自动将购买详情发票金额、币种等关联到原始点击事件——正是这套 Webhook 链路在背后完成关联。七、集成后的数据流全景整个归因链路可以概括为用户点击 Dub 短链 → Dub 生成dub_id点击事件并记录到 Tinybird用户在你的站点完成注册/支付请求头携带dub_id你的服务端创建/更新 Stripe 客户把dubCustomerExternalId用户 ID与dubClickIddub_id写入metadataStripe 触发customer.created/customer.updatedWebhookDub 在本地创建或更新Customer并记录New customerLead 事件客户后续支付触发checkout.session.completed/invoice.paidDub 记录 Sale 事件金额、币种、发票号递增链接sales/saleAmount/conversions必要时为合作伙伴生成佣金并发送 Postback。八、最佳实践与注意事项用户 ID 必须稳定唯一dubCustomerExternalId一旦确定就不要变更它是 Dub 客户记录与 Stripe 客户长期绑定的主键若 ID 变化会导致历史归因断裂。保持幂等Webhook 对同一发票做了 Redis 去重你侧重复调用customers.update不会产生副作用可以放心重试。非 USD 币种自动换算销售金额会统一换算为 USD 记录convert-currency.ts不需要你自行处理币种转换。免费试用与折扣控制工作区可在 Stripe 集成设置中配置freeTrials是否将订阅免费试用记录为 Lead与discountCodeRestrictions仅首次交易可使用折扣码配置模式见 schema.ts。订阅场景的元数据优先级若同时使用了 Checkout Session 流程Dub 会优先读取 Checkout Session 的metadata其次才是已连接客户对象上的metadata两种方式互不冲突。通过本文的接入方式即使你的支付流程完全自定义、不经过 Stripe Checkout也能让 Dub 精确地把每一笔销售回溯到最初的点击来源为链接转化率分析、合作伙伴佣金结算和 Google Ads 转化回传提供准确的数据底座。【免费下载链接】dubThe modern link attribution platform. Loved by world-class marketing teams like Framer, Perplexity, Superhuman, Twilio, Buffer and more.项目地址: https://gitcode.com/GitHub_Trending/du/dub创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

基于 FastMCP 构建带交互界面的 QR Code MCP App:工具、`ui://` 资源与 CSP 配置实战

基于 FastMCP 构建带交互界面的 QR Code MCP App:工具、`ui://` 资源与 CSP 配置实战

基于 FastMCP 构建带交互界面的 QR Code MCP App:工具、ui:// 资源与 CSP 配置实战 【免费下载链接】fastmcp 🚀 The fast, Pythonic way to build MCP servers and clients. 项目地址: https://gitcode.com/GitHub_Trending/fa/fastmcp 导读 本…

📅 2026/9/12 1:47:00
WezTerm `anti_alias_custom_block_glyphs` 配置详解:控制自定义块字符的抗锯齿渲染

WezTerm `anti_alias_custom_block_glyphs` 配置详解:控制自定义块字符的抗锯齿渲染

WezTerm anti_alias_custom_block_glyphs 配置详解:控制自定义块字符的抗锯齿渲染 【免费下载链接】wezterm A GPU-accelerated cross-platform terminal emulator and multiplexer written by wez and implemented in Rust 项目地址: https://gitcode.com/GitHub…

📅 2026/9/12 1:47:00
Simulink建模在VCU开发中的核心技术与实践

Simulink建模在VCU开发中的核心技术与实践

1. VCU整车Simulink模型概述在新能源汽车开发领域,VCU(Vehicle Control Unit)作为整车控制的核心大脑,其开发效率和可靠性直接影响着车辆性能。Simulink模型化的开发方式已经成为行业主流,相比传统手写代码&#xff0c…

📅 2026/9/12 1:47:00
MORE NEWS

更多资讯

📰

YOLOv8农业落地实践:水稻虫害识别开箱即用系统

简介:本资源是一套基于YOLOv8的农田虫害智能监测系统完整实现方案,面向计算机、人工智能、农业信息化等方向的本科生及教师,专为毕业设计、课程设计与项目实践打造,解决农业场景下害虫目标检测与可视化分析的实际问题。压缩包共8个…

📰

Python实战声纹识别:预处理、模型选型与EER评估

简介:面向毕业设计、课程设计与项目开发场景,一个基于Python的声纹识别项目集成了EcapaTdnn、ResNetSE、ERes2Net、CAM等主流模型,并支持MelSpectrogram、Spectrogram、MFCC、Fbank等多种音频预处理方式,同时引入ArcFace&#xff…

📰

开发者高效求助与问题定位方法论

1. 问题背景与求助场景分析"求大佬解惑"这个标题背后反映的是一个典型的开发者求助场景。在实际工作中,无论是刚入行的新人还是有一定经验的从业者,都会遇到各种技术难题。这类问题通常具有以下特征:问题描述不够具体,提…

📰

TMS320F28335三相逆变器SVPWM实战:从CCS配置到IR2130驱动调测

简介:本资源是一套面向电力电子与电机控制方向嵌入式开发者的完整三相逆变器DSP工程实践套件,聚焦TMS320F28335数字信号处理器与IR2130驱动芯片协同设计,解决电机驱动系统中SVPWM算法实现、硬件驱动适配及实时控制调试等核心问题。压缩包含20…

📰

工业污泥深度脱水技术突破与工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

三相DC-AC变换器工程级参数设计全链路指南

1. 项目概述:从实验室台架到工程落地的三相DC-AC变换器设计全链路拆解“上交大三相DC-AC变换器参数设计及其他问题(更新版)”——这个标题背后不是一份简单的课程作业或仿真报告,而是一套完整覆盖拓扑选型→主电路参数计算→驱动与…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬