@dxv-systems/metis-client

中文文档
0.16.1发布于 2026/11/10MITTypeScriptCommonJS零依赖近 30 天下载 5295

第十五届 Metis 转换跟踪 SDK — 点击ID 捕获和签名转换事件排放

中文使用文档
文档目录19 节
  1. 安装
  2. 上岗
  3. 客户端: 着陆时点击ID
  4. Cookie 编码
  5. 服务器侧: 发送购买事件
  6. 服务器侧: 发送线索事件
  7. 工作应用程序 : lead.kind (0.15.0) (中文(简体) )
  8. 服务器侧: 发送漏斗步骤( 0. 0.0)
  9. 博茨和应用程序提示 (0.16.0)
  10. 更多匹配密钥 (0. 14. 0)
  11. 同意
  12. 还没回答的访客
  13. 游客同意的平台(0.13.0)
  14. 服务器侧: 询问 Metis 哪些平台的横幅名称 (0. 13. 0)
  15. 付费触摸旗
  16. 用浏览器像素编程
  17. 设计可复制的事件 ID
  18. 公约
  19. 许可证

@dxv-systems/metis-客户端

DXV Metis转换跟踪SDK. 抓取点击 ID (gclid, (中文(简体) ), fbclid, (中文(简体) ), gbraid, (中文(简体) ), wbraid, (中文(简体) ), utm_*)在登陆和向 DXV Metis 中继端点发送签名的服务器侧转换事件时.

发表于 @dxv-systems/conversions 最高为0.3.0. 该名称被贬值;API是相同的,只有包名被更改了.

安装

npm install @dxv-systems/metis-client

上岗

当您的 Metis 账户建立后, DXV 给出三个值:

  • customerId — 整数, 在梅蒂斯识别客户记录
  • relaySecret - HMAC 签名密钥(作为证书处理)
  • relayUrl - 典型的梅蒂斯端点基座 https://metis.dxvagentic.com (较老的) https://marketing.dxvagentic.com 也还在工作)

在您的 Webshop 的部署中将这些存储为环境变量 。 以下实例 DXV_CUSTOMER_ID, (中文(简体) ), DXV_CONVERSIONS_RELAY_SECRET 财务报告和审定财务报表 DXV_CONVERSIONS_RELAY_URL。此软件包本身不读取:您将值传递到其中.

客户端: 着陆时点击ID

在您的登陆页面处理器(Next.js中件、Express处理器,任何地方):

import { CLICK_IDS_COOKIE, captureClickIds, parseClickIdsCookie, serializeClickIdsCookie } from "@dxv-systems/metis-client/client";

// On every request to a public page:
const url = new URL(request.url);
const captured = captureClickIds(url.searchParams);

if (captured) {
  // First-touch wins: don't overwrite an existing valid cookie.
  const existing = parseClickIdsCookie(request.cookies.get(CLICK_IDS_COOKIE)?.value);
  if (!existing) {
    response.cookies.set(CLICK_IDS_COOKIE, serializeClickIdsCookie(captured), {
      maxAge: 30 * 24 * 60 * 60, // 30 days
      httpOnly: false,           // intentionally readable from client (analytics)
      sameSite: "lax",
      secure: true,
    });
  }
}

CLICK_IDS_COOKIE (单位:千美元)"dxv_click_ids"从两者中导出) /client 财务报告和审定财务报表 /server,所以应用不再重复饼干名称. 饼干在0.7.0前写作(无 gbraid编号 :wbraid仍作解说.

parseClickIdsCookie 以任何你碰巧持有的形式持有的值 : 原始 %- 编码字符串 Cookie 页眉, 或已解码 字符串框架 cookie API 返回 。 你不必知道自己有哪个.

这在实践中很重要. next/headers cookies() 财务报告和审定财务报表 NextRequest.cookies.get() 解码信头本身,同时 NextResponse.cookies.set() 编码 你给它,所以一个饼干写 通过中间软件,在 serializeClickIdsCookie自己的编码,是 存储了双编码。 包含正文的值 % 联合国 utm_campaign 联 合 国 50%-korting仍然正确分析各种形式.

服务器侧: 发送购买事件

在您的订单中完成的处理器( Stripe webhook等) :

import { emitPurchase } from "@dxv-systems/metis-client/server";
import { parseClickIdsCookie } from "@dxv-systems/metis-client/client";

await emitPurchase({
  customerId: Number(process.env.DXV_CUSTOMER_ID),
  relaySecret: process.env.DXV_CONVERSIONS_RELAY_SECRET!,
  relayUrl: process.env.DXV_CONVERSIONS_RELAY_URL!,
  eventId: order.id,   // optional; see "Deduping with a browser pixel" below
  order: {
    id: order.id,
    totalCents: order.totalCents,
    currency: "EUR",
  },
  clickIds: parseClickIdsCookie(cookies.get(CLICK_IDS_COOKIE)),
  customer: {
    email: order.customer.email,    // plaintext; package hashes per Meta CAPI spec
    phone: order.customer.phone,
  },
  consent: {
    adUserData: consentState.adUserData,
    adPersonalization: consentState.adPersonalization,
  },
});

emitPurchase 在5xx上重复3次 以指数回放。 它扔出输入错误 :

  • InvalidConfigError ——失踪/空 relaySecret, (中文(简体) ), relayUrl,或 customerId,或无效字段。 在任何网络通话前被丢弃.
  • RelayBadRequestError - Metis 返回 4xx( 可能是 stale ) relaySecret 或错 customerId) (中文(简体) ). 未复审.
  • RelayUnavailableError ——梅蒂斯3次尝试后无法接触.

服务器侧: 发送线索事件

对于格式填充/ 注册转换, 没有附加命令( 引号请求、 联系表、 演示预订) :

import { emitLead } from "@dxv-systems/metis-client/server";
import { parseClickIdsCookie } from "@dxv-systems/metis-client/client";

await emitLead({
  customerId: Number(process.env.DXV_CUSTOMER_ID),
  relaySecret: process.env.DXV_CONVERSIONS_RELAY_SECRET!,
  relayUrl: process.env.DXV_CONVERSIONS_RELAY_URL!,
  eventId: submission.id,   // optional; see "Deduping with a browser pixel" below
  lead: {
    id: submission.id,
    valueCents: 0,   // optional; omit if the lead has no estimated value
    currency: "EUR", // optional; only meaningful alongside valueCents
  },
  clickIds: parseClickIdsCookie(cookies.get(CLICK_IDS_COOKIE)),
  customer: {
    email: submission.email,
    phone: submission.phone,
  },
});

emitLead 共享配置验证、 PII 散列、 签名和重试行为 emitPurchase ——同打出错误,同打出5xx重试/4xx-脂肪规则. 只有输入形状不同: lead (无) order),以及 lead.id 是唯一需要的字段.

Metis存储了主导事件,并征得同意后将其转发至购买等广告平台.

工作应用程序 : lead.kind (0.15.0) (中文(简体) )

一个职业页面发送一个工作应用程序作为线索 kind: "application"数字 :

await emitLead({ /* ... */, lead: { id: application.id, kind: "application" } });

梅蒂斯计算申请,除了询问和 从不转发 给Meta、Google或Pinterest,不管访客同意什么:一个向申请人传授的广告平台找到申请人而不是客户。 它没有为它们提供散列识别器. kind: "lead" 这跟不说一样 任何其它值抛出 InvalidConfigError 在发送任何信息之前 需要知道球场的Metis(2026年10月后);一个更老的球会忽略了它.

服务器侧: 发送漏斗步骤( 0. 0.0)

emitFunnelEvent({ event: "view_content" | "add_to_cart" | "initiate_checkout", eventId, funnel?: { valueCents?, currency?, items?: [{ id, quantity, priceCents? }] }, clickIds, customer, consent, context }) metis只向Meta 报告浏览步骤. eventId 需要:通过浏览器像素所用的一个,所以Meta去除它们. 只有在双方同意的信号都是真实的且访客决定的情况下,梅蒂斯才保留该步骤,从不算作转换. context.actionSource 也许只有 website使用的大多数场地 @dxv-systems/measurement是因为 funnelRouteHandler 换句话说.

博茨和应用程序提示 (0.16.0)

isBotUserAgent(userAgent) 财务报告和审定财务报表 BOT_USER_AGENT_TOKENS (从) ./server) 名称已知bots, crawers, 链接预览器, 无头浏览器和脚本 HTTP 客户端(Googlebot, AdsBot, bingbot, facebook externalhit, Headless Chrome, 卷曲, wget, python- requests and more), 匹配为小写子串. 只有明确的名字:一个赤裸的"机器人"也会匹配真实的手机. 缺席不是机器人. @dxv-systems/measurement 在发送前从这些漏斗步骤中去掉,而梅蒂斯使用相同的列表再次以摄取的方式去掉. 采购和线索从不过滤.

每一次发射,和 fetchConsentPlatforms选项 appId (应用程序的ID在梅蒂斯, 一个正整数, 否则 InvalidConfigError) (中文(简体) ). 发件人: X-DXV-App-Id,所以Metis先尝试该应用程序的秘密,而不是每个组织的秘密(或者,为了 consent-platforms 无 customerId每个应用程序。 这只是个提示:签名仍然为应用程序取名,没有标题的Metis忽略了它.

Metis每分钟限制每个app的接力事件(600个漏斗台阶,120个购买和线索). 超过极限,它回答 429,这是一个 RelayBadRequestError 而不复试.

更多匹配密钥 (0. 14. 0)

customer 还要 externalId (店主的客户或领导身份), firstName, (中文(简体) ), lastName, (中文(简体) ), city, (中文(简体) ), postalCode 财务报告和审定财务报表 country (ISO 3166-1 alpha-2,例如:. "NL"),所有可选和简写. 他们像电子邮件一样,是正常的,是散发的:

外地发送为正常化为
externalIdexternalIdSha256已修剪, 案件保存( 标识不透明)
firstName, (中文(简体) ), lastNamefirstNameSha256, (中文(简体) ), lastNameSha256NFC,小写,无平分,单内空格("Jean-Luc" →) jeanluc,"Zoë" – (中文(简体) ) zoë(中文(简体) )
citycitySha256小写字母和数字,重音会下降(''s-Hertogenbosch' →) shertogenbosch(中文(简体) )
postalCodepostalCodeSha256小写,没有空格或破折号(“1234 AB”) − 1234ab); 一个美国代码保留了5个数字
countrycountrySha256小写 α-2 (nl(中文(简体) )
postalCode, (中文(简体) ), countrypostalCode, (中文(简体) ), countryCode, (中文(简体) ), 简单修剪后, 大写1234 AB, (中文(简体) ), NL(中文(简体) )

平原对之所以存在,是因为Google的"数据管理器"取了一个地址的邮政和地区代码未覆盖(只有名称被散列). 一个空地,或者一个不是两个字母的国家,被排除在外,从不作为空字符串而散去. IP 和用户代理端保持无阴影 context和以前一样.

梅蒂斯寄给Meta(external_id, (中文(简体) ), fn, (中文(简体) ), ln, (中文(简体) ), ct, (中文(简体) ), zp, (中文(简体) ), country),将Google作为地址(黑名、平原地区和邮政编码)和Pinterest(external_id, (中文(简体) ), fn, (中文(简体) ), ln, (中文(简体) ), ct, (中文(简体) ), zp, (中文(简体) ), country),每个都只有在访客同意的情况下,如电子邮件. 需要了解字段的梅蒂斯版本:一个更年长的人接受尸体并放下.

captureClickIds 还抓取 ttclid (TikTok语), msclkid (微软)和 epik (兴趣)进入相同的先触 dxv_click_ids 饼干,和 detectPaidTouch 算作付费点击。 Metis 向前移动 epik 利息; ttclid 财务报告和审定财务报表 msclkid 是为后来的转发者保存的.

两者 emitPurchase 财务报告和审定财务报表 emitLead 接受选项 consent 字段 :

consent: {
  adUserData: boolean;        // Google Consent Mode v2 "ad_user_data"
  adPersonalization: boolean; // Google Consent Mode v2 "ad_personalization"
  decided?: boolean;          // has the visitor answered the banner? absent = yes
  platforms?: ("google" | "meta" | "pinterest")[]; // what the banner named (0.13.0); absent = not recorded
}

在实践中,这不是可选的. Metis 存储每个事件, 不管怎样, 但是它的 Meta CAPI / Google 离线转换转发器失败了 关闭: 一个没有连接到的事件 consent 对象从不转发,只存储。 如果你想让转换实际到达Meta或Google,就必须通过 consent 从您的商店前端已经运行的 同意管理平台( CMP, 饼干横幅, 自己的首选店) 读取. adUserData 财务报告和审定财务报表 adPersonalization 当对象存在时需要; 没有部分形式.

还没回答的访客

decided (加到0.7.0)让梅蒂斯告诉一个从未回答过的人拒绝的访客. 缺席意味着决定的,所以现有的发送者保持其意义. 当来访者尚未回答旗帜时,请发:

consent: { adUserData: false, adPersonalization: false, decided: false }

这与其它任何未同意的情况一样, 奥米 consent 完全只有当你的融合没有任何同意信息时; Metis报告作为一个发送漏洞,这与"未决定"不同. decided 一定是一个布尔当场.

游客同意的平台(0.13.0)

consent.platforms 列出访问者回答时命名的横幅的广告平台; Metis只转发给那些。 名字来自 CONSENT_PLATFORMS (单位:千美元)google, (中文(简体) ), meta, (中文(简体) ), pinterest从 /client 财务报告和审定财务报表 /server),每个最多一次;任何其他投出 InvalidConfigError。当旗帜没有记录一个列表时,将其删除.

服务器侧: 询问 Metis 哪些平台的横幅名称 (0. 13. 0)

import { fetchConsentPlatforms } from "@dxv-systems/metis-client/server";

const answer = await fetchConsentPlatforms({ relayUrl, relaySecret, customerId });
// { platforms: ["google", "meta"], version: "3f2a9c1b7d4e" } or null

它发出 GET {relayUrl}/api/relay/v1/consent-platforms?customerId={customerId},以中继 POST 形式在空出的身体上签名: X-DXV-Signature 是HMAC-SHA256的六分位数 `${timestamp}.` 带着接力的秘密, X-DXV-Timestamp 同样的毫秒印出. customerId 是可选的;没有它,Metis会尝试针对每个活动应用程序的秘密. 它从未丢出: 任何失败( 网络、 默认3 s 的超时、 非-2xx 、 错误的答案) 返回 null。删除未知的平台名称。 选项 : fetchImpl, (中文(简体) ), timeoutMs使用的大多数场地 @dxv-systems/measurement是因为 consentPlatformsHandler 相反,它会缓存答案 并回到每个平台.

付费触摸旗

detectPaidTouch(input) (从) /client 或者说 /server,在0.8.0中添加)返回 true 当一个着陆URL说访问来自一个广告:任何 gclid, (中文(简体) ), fbclid, (中文(简体) ), gbraid 或者说 wbraid 有并非空地,或 utm_medium (trimmed, case- 不敏感) 是其中之一 cpc, (中文(简体) ), ppc, (中文(简体) ), cpm, (中文(简体) ), cpv, (中文(简体) ), paid, (中文(简体) ), paidsocial, (中文(简体) ), paid_social, (中文(简体) ), paid-social, (中文(简体) ), paidsearch, (中文(简体) ), paid_search, (中文(简体) ), paid-search, (中文(简体) ), display它接受 URLSearchParams、查询字符串、完整 URL 字符串或 URL。 。 。 .

import { detectPaidTouch } from "@dxv-systems/metis-client/client";

const paidTouch = detectPaidTouch(window.location.search); // keep in a variable
await emitLead({ /* ... */, paidTouch });

两者 emitPurchase 财务报告和审定财务报表 emitLead 接受选项 paidTouch: boolean,作为顶级域发送。 Metis的同意监视器将它算作将被拒绝和未决定的访客分为付费和有机;它从未被转发给Meta或Google. 当您不知道时( 缺席意味着未知) , 把它放出来 。 它一定是一个布尔当场.

将结果保存在记忆中. 永远不要写到饼干,本地Storage或任何其他存储器上:那是未经同意的设备存储. 完全重装或回访应当给出"未知"(omt the flag),而不是猜测.

用浏览器像素编程

如果你的站点 (单位:千美元) 从浏览器中报告此转换( a Meta 像素) Purchase编号 :Lead 事件, a gtag 转换事件),通过相同 eventId 对像素调用和 emitPurchase编号 :emitLead. Meta和Google通过匹配事件名称外加共享事件ID来对服务器事件去除浏览器事件——没有它,一旦Metis开始转发服务器事件后,双方报告的转换就会被计算出两次.

eventId 是可选的 —— 如果您没有用于此转换的浏览器边对应器, 请省略 。 当提供时, 它必须是最多为 256 个字符的非空字符串( 只拒绝空白字符串 ) ; 使用您在像素和服务器呼叫( a) 之间已经共享的 ID nanoid,命令参考,UUID).

设计可复制的事件 ID

如果您的浏览器像素和服务器侧放出不共享进程状态—— 常见的情况, 因为像素在确认页面上起火, 服务器在稍后从 Webhook 中放出火来, 您需要一种方法来获取 不变 在两边从他们都已经知道的东西, 像顺序号:

import { purchaseEventUuid } from "@dxv-systems/metis-client/client"; // or /server

const eventId = purchaseEventUuid(order.number);
// Pass this to both the pixel call (fbq('track', 'Purchase', {}, { eventID: eventId })
// or posthog.capture(..., { uuid: eventId })) and to emitPurchase's `eventId` field.

purchaseEventUuid 以及更普遍的 deterministicEventUuid 纯函数 两者 /client 财务报告和审定财务报表 /server ——浏览器需要一台来计算其像素调用时的ID,服务器需要相同的功能来在后期为中继放出时重算出同一种ID,而无需两者协调. 定点论是整点:一个随机的每事id在事实发生后无法被复制,而Meta/PostHog通过匹配该id来对准它的浏览器对应器来去dupe一个服务器事件——把它弄错了,并且每一个转发的转换双数,沉默地.

输出还被塑造为有效的 RFC-4122 uuid 而不是像可读字符串 purchase:ORD-0001,因为这个链条中的几个平台(PostHog including)只接受一个有效的uuid作为事件id,并且静悄悄地以一个随机的交换,否则——再次没有出错,只是一个悄悄地停止工作的解脱.

用于铅转换 leadEventUuid(lead.id) 相同方式(等于 deterministicEventUuid("lead:" + lead.id)),所以是一个浏览器 Lead 像素和 emitLead 共享一个事件 id.

双方必须使用它,否则解脱无效. 如果您的存储前缀的像素以一个方式获得其id,而服务器则从另一个方式(或者一方使用随机的ID)获得,Meta/PostHog无法告诉这两个事件是相同的转换,一旦Metis向上转发服务器边事件,就会得到两次计数.

公约

  • 钱入一分钱(一分). Metis 验证 totalCents > 0。 。 。 .
  • 货币作为ISO 4217(例如. EUR, (中文(简体) ), USD) (中文(简体) ).
  • PII(电子邮件、电话、外部身份证、姓名、城市、邮政编码、国家) 记忆中的散列 网络调用前; 纯文本从不退出进程, 但邮政和国家代码 Google 采取平原 (0. 14.0) 。 Metis只将散列保留在它可能转发的一行(同意,或经认证的下线销售)上,一旦不再可能,即可清除.
  • 电话在已知国家时被两次散开(+31…, (中文(简体) ), 0031…,或 phoneCountryCode: "31": phoneSha256 作为国家代码(Meta)和 phoneE164Sha256 与 + (谷歌声). 没有国家,只有数字 phoneSha256 和以前一样发送.
  • phoneE164(phone, countryCode?) 财务报告和审定财务报表 phoneWithCountryCode 从 ./client 也 (0. 12. 0) , 因此浏览器可以像服务器那样将手机格式化 .
  • Gmail 或 Google 邮件地址, 日期之前有点 @ 也作两次散列( 0.11.0 ): emailSha256 已键入( Meta) 和 emailGoogleSha256 没有点(Google 匹配它那样). 任何其他地址发送 emailSha256 只有这个.
  • context (0.9.0) 携带客户端IP,用户代理,页面 URL和 actionSource (单位:千美元)website,或 phone_call 编号 : email 编号 : chat 编号 : physical_store 编号 : other 销售人员进入). clickIds 可能携带Meta的 _fbc 编号 : _fbp 饼干作为 fbc 编号 : fbp。 。 。 .
  • 点击ID cookie 是 先触后取胜 如果一个有效的饼干已经存在, 请不要覆盖 .

许可证

麻省理工学院

版本与发布记录

@dxv-systems/metis-client 共发布 15 个版本,首次发布于 2026/09/06;过去 12 个月发布了 15 个版本。

版本发布日期距今
0.16.1latest2026/11/103 天前
0.16.02026/10/3113 天前
0.15.02026/10/3113 天前
0.14.02026/10/3113 天前
0.13.02026/10/2816 天前
0.12.02026/10/2716 天前

关于 @dxv-systems/metis-client 的常见问题

@dxv-systems/metis-client 是什么?

第十五届 Metis 转换跟踪 SDK — 点击ID 捕获和签名转换事件排放

如何安装 @dxv-systems/metis-client?

在项目目录运行 npm install @dxv-systems/metis-client,或使用 pnpm add / yarn add / bun add。

@dxv-systems/metis-client 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dxv-systems/metis-client 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@dxv-systems/metis-client 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@dxv-systems/metis-client 可以商用吗?

@dxv-systems/metis-client 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dxv-systems/metis-client 的下载量有多少?

根据 npm 官方下载统计,@dxv-systems/metis-client 在 2026/10/13 – 2026/11/11 这 30 天内被下载 5,295 次,日均约 177 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dxv-systems/metis-client 还在维护吗?

最新版本 0.16.1 发布于 2026/11/10(3 天前);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/09/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。