使用 NextAuth 与 Dub 集成在新用户注册时自动上报 Lead 转化事件【免费下载链接】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导读本文讲解如何在 Next.js 应用中将 NextAuth.jsAuth.js的登录流程与 Dub 的转化归因能力打通当用户通过你的营销短链例如dub.sh或自定义域名下的 Dub 链接第一次访问并完成注册时自动向 Dub 上报一条lead潜在客户转化事件。读完本文你将掌握完整的接入方案——从dub_idcookie 的产生原理、NextAuthsignIn事件中的上报代码到dub.track.lead各参数的语义以及如何清理 cookie 避免重复上报并了解该方案在开源仓库中的真实落地写法。一、整体思路Cookie 驱动的转化归因Dub 的归因链路可以概括为一条数据链用户点击你的 Dub 短链Dub 的 重定向中间件 会为该次点击生成一个全局唯一的clickId在源码中使用nanoid(16)生成见 link.ts。中间件把clickId以 cookie 形式写回浏览器cookie 名为dub_id_domain_key见 create-response-with-cookies.tsmaxAge为 1 小时用于点击去重同时在最终跳转 URL 的查询参数中附带dub_id见 get-final-url.ts。用户在落地页完成注册。此时你的应用读取 cookie 中的dub_id调用dub.track.lead上报将这次点击与“新用户注册”事件关联起来。上报成功后删除dub_idcookie。此时 Dub 已经把这个用户登记为 Customer后续所有事件都以customerExternalId你的系统里用户的唯一 ID为准不再依赖 cookie。这一点在官方指南中也明确说明Dub 在底层会把用户记录为 customer 并与来源点击事件关联用户唯一 ID 成为后续所有事件的唯一事实来源因此不再需要dub_idcookie。围绕这条链路仓库中还有对应的端到端测试佐证在 redirects/index.test.ts 中测试会断言短链重定向响应包含Set-Cookie: dub_id_*、cookie 值与 URL 查询参数中的dub_id一致且Max-Age3600。二、前置条件在动手编码前需要准备以下三样东西Dub 项目与 API Key在 Dub 控制台创建一个项目获取 API Key并配置环境变量DUB_API_KEYyour_api_key从仓库其他指南如 manual-track-lead.md可以看到Dub SDK 的token参数是可选的默认会读取DUB_API_KEY环境变量因此在 apps/web/lib/dub.ts 中项目自身的客户端只用了两行代码import { Dub } from dub; export const dub new Dub();一个开启了转化跟踪的 Dub 短链Dub 中间件只有在满足一定条件时才会缓存clickId见 link.ts链接开启了trackConversion转化跟踪或者是 Partner/联盟链接或者是 Singular / AppsFlyer 跟踪链接。所以请确认你的目标短链已开启转化跟踪track conversion。NextAuth 已接入项目本文假设你已经在 Next.js App Router 项目中使用 NextAuth且已有authOptions配置。提示若你使用的是 Clerk、Auth0、Supabase 等其它认证方案仓库的 guides 目录 下还提供了对应的clerk.md、auth0.md、supabase.md、appwrite.md等同主题指南思路完全一致。三、核心实现在 NextAuthsignIn事件中上报 Lead3.1 事件机制NextAuth 提供events配置项其中signIn事件会在用户每次登录时触发。回调参数message上带有isNewUser字段——仅当用户是新注册而非老用户再次登录时为true这正好对应 Dub 归因所需的“转化”语义。3.2 完整代码在app/api/auth/[...nextauth]/options.ts或你存放authOptions的文件中添加如下配置// app/api/auth/[...nextauth]/options.ts import type { NextAuthOptions } from next-auth; import { cookies } from next/headers; import { dub } from /lib/dub; export const authOptions: NextAuthOptions { ...otherAuthOptions, // your other NextAuth options events: { async signIn(message) { // if its a new sign up if (message.isNewUser) { // check if dub_id cookie is present const dub_id cookies().get(dub_id)?.value; if (dub_id) { // send lead event to Dub await dub.track.lead({ clickId: dub_id, eventName: Sign Up, customerExternalId: user.id, customerName: user.name, customerEmail: user.email, customerAvatar: user.image, }); // delete the dub_id cookie cookies().set(dub_id, , { expires: new Date(0), }); } } }, }, };3.3 字段含义与说明对照仓库中 trackLeadRequestSchemaDub API 服务端对track.lead请求的校验 Schema各字段语义如下参数是否必填说明clickId必填点击事件的唯一 ID即从dub_idcookie 读取的值。注意cookie 的真实名称是dub_id_domain_key如dub_id_dub.sh_landingDub 也支持在 cookie 与查询参数两种载体上读取。若你拿到的是具体域名/短链对应的带前缀 cookie请按实际名称读取。eventName必填事件名如Sign Up长度 1–255。它还可以作为后续/track/sale中leadEventName的唯一关联标识把一次注册和之后的下单串联成完整转化漏斗。customerExternalId必填用户在你的系统中的唯一 ID如数据库主键。Dub 将以此为准归因用户后续所有事件长度 ≤ 100。customerName可选用户姓名。不传时 Dub 会生成随机昵称如 “Big Red Caribou”。customerEmail可选用户邮箱需符合 email 格式。customerAvatar可选用户头像 URL。mode可选async默认不阻塞请求/wait等待 Dub 完整落库后再返回/deferred延迟到后续请求。eventQuantity可选事件数值如免费试用开通的席位数量设为 N 则事件按 N 次记录。metadata可选附加元数据上限 10,000 字符。dub.track.lead的返回值会包含click、link可能为 null和customer对象见 trackLeadResponseSchema可用于日志记录或后续二次处理。四、几个容易踩的坑与最佳实践4.1 cookie 命名dub_id还是dub_id_domain_keyDub 中间件实际写入的 cookie 名是dub_id_domain_key见 link.ts例如dub_id_dub.sh_landing。官方指南示例中使用cookies().get(dub_id)是通用写法——如果你的落地页位于 Dub 短链域名即访问dub.sh/xxx的同一域名下cookie 会以dub_id形式出现在查询参数或该作用域下而在跨域落地页场景下Dub 通过 URL 查询参数?dub_id...将 clickId 透传给落地页见 get-final-url.ts你可以同时兜底读取查询参数。建议同时检查 cookie 与查询参数双保险。4.2 只处理新用户避免重复上报务必以message.isNewUser true作为上报前置条件否则老用户每次登录都会再次上报 lead污染转化数据。仓库实际生产代码在 auth/options.ts 中还有更严格的判断它先查库确认用户确实在最近 15 秒内创建createdAt Date.now() - 15000才视为“新注册”从而避免历史数据回填导致的误报。4.3 上报后务必清理 cookie上报成功后用cookies().set(dub_id, , { expires: new Date(0) })立即过期该 cookie或在 Server Component 中调用cookieStore.delete。原因在指南末尾已说明一旦用户以customerExternalId被登记后续所有事件都以该 ID 为事实来源cookie 已无存在价值删除还能防止同一次注册被重复归因。4.4 不要阻塞登录流程dub.track.lead默认mode: async不会阻塞请求若你使用wait模式建议将上报逻辑放进waitUntil()异步执行避免拖慢用户登录。Dub 官方仓库自身的实现即采用此模式在 auth/options.ts 中trackDubLead(user)被包在waitUntil(Promise.allSettled([...]))中异步执行与欢迎邮件工作流并行。五、仓库里的工程化实现参考官方指南给出的是最小可用示例而 Dub 自己的生产代码在此基础上做了更工程化的封装值得借鉴独立工具函数track-dub-lead.ts 把“读 cookie → 上报 → 清理 cookie”封装为trackDubLead(user)单函数。注意它同时清理了两个 cookiedub_id与dub_partner_dataPartner 归因数据说明真实场景下还应考虑联动清理其它归因 cookie。统一 SDK 实例dub.ts 中export const dub new Dub()全局复用同一实例并提供了getDubCustomer(userId)帮助函数——通过dub.customers.list({ externalId: userId })反查用户在 Dub 侧的 customer 记录可用于在注册后主动同步用户画像。健壮的 cookie 判定trackDubLead在 cookie 不存在时直接console.log并跳过上报“No dub_id cookie found, skipping lead tracking...”说明没有 dub_id 时不报错、静默跳过是正确姿势——毕竟并非所有注册都来自 Dub 短链。测试保障redirects/index.test.ts 中assertRedirectWithDubIdCookie断言了重定向响应302、Set-Cookie中的dub_id_*cookie 与 URL 查询参数dub_id值一致、cookieMax-Age3600、Path/linkKey等关键行为。接入完成后你可以参照它为自己写一条集成测试验证“点击短链 → 读取 cookie → 上报 lead”全链路。六、验证接入是否成功接入完成后建议按以下顺序自测用无痕窗口点击开启了转化跟踪的 Dub 短链观察重定向后的落地页 cookie 中是否出现dub_id_*或 URL 中带?dub_id...。完成一次新用户注册确认请求日志中出现对 Dub API 的track.lead调用async模式下不会阻塞注册流程。回到 Dub 控制台的 Analytics → Leads或对应事件分析页查看是否出现Sign Up事件且来源 click 与短链正确关联。再次使用同一浏览器重复登录同一账号确认不会再次上报isNewUser为false或 cookie 已被删除。七、总结借助 NextAuth 的signIn事件把dub_idcookie 中的点击 ID 通过dub.track.lead上报给 Dub即可在十几行代码内完成“点击短链 → 新用户注册 → 转化归因”的完整闭环。核心要点是仅新用户上报、上报后清 cookie、以customerExternalId作为后续归因主键。Dub 官方仓库在 apps/web/lib/auth/ 与 apps/web/lib/middleware/ 中提供了可直接参考的生产级实现与测试用例接入时可按需对照使用。【免费下载链接】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),仅供参考