快速上手
@tripo3d/trace 的核心 API 只有两步:new TripoTrace(params) 创建实例,await trace.initLanding() 完成 device id 加载与渠道归因。
完整流程
ts
import { TripoTrace } from '@tripo3d/trace';
const trace = new TripoTrace({
baseUrl: 'https://api-cn-test.tripo3d.com',
onError: (err, ctx) => console.warn('[trace]', ctx, err),
});
// 一次性完成:
// 1. 加载 device id(首次:从 fingerprint 现算并写 localStorage;后续:直接读缓存)
// 2. 检测当前 URL 渠道(v0.1 仅 bd_vid)
// 3. 命中且当日未报 → POST {baseUrl}/v2/attribution/landing
await trace.initLanding();为什么 initLanding 是异步的
device id 来自 FP.load() —— 内部用 requestIdleCallback 等一帧空闲,保证 Canvas/WebGL 等特征渲染稳定。这一步只在首次访问时跑一次,之后命中 localStorage 缓存。
TripoTraceParams
| 字段 | 类型 / 默认 | 说明 |
|---|---|---|
baseUrl | string(必填) | 归因服务 base URL,例如 https://api-cn-test.tripo3d.com |
channels | ChannelName[] / 全部已注册 | 启用的渠道白名单。v0.1 只有 baidu 一个 |
deviceIdOverride | string | 业务自管 device id 时显式传入,跳过指纹计算 |
fetch | typeof fetch / globalThis.fetch | 注入自定义 fetch,Nuxt 项目可传 $fetch |
onError | (err, ctx) => void | 错误回调;ctx.phase 是 init 或 report,便于定位 |
onReport | (payload, channel) => void | 上报成功钩子,便于业务做埋点链路监控 |
实例属性 / 方法
| 名称 | 签名 | 说明 |
|---|---|---|
trace.deviceId | string | 当前 device id;未 init 或 SSR 下为 '' |
trace.headers | Record<string, string> | { 'x-tripo-device-id': string };无 id 时为 {},安全合并 |
trace.initLanding() | () => Promise<void> | 加载 device id + 渠道检测 + 命中上报。幂等,可重复调用 |
没有公开的 reportLanding
归因上报是 SDK 内部行为,不暴露给调用方。业务方需要做的只有 new + await initLanding() 两步。
Nuxt 接入
步骤 1:runtimeConfig
ts
// nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
attributionBaseUrl: 'https://api-cn-test.tripo3d.com',
},
},
});步骤 2:客户端 plugin
app/plugins/05.trace.client.ts(.client 后缀让 Nuxt 仅在客户端执行,避免 SSR 阶段执行 fingerprint):
ts
import { TripoTrace } from '@tripo3d/trace';
export default defineNuxtPlugin(async (nuxtApp) => {
const config = useRuntimeConfig();
const trace = new TripoTrace({
baseUrl: config.public.attributionBaseUrl as string,
onError: (err, ctx) => console.warn('[trace]', ctx, err),
});
// 加载 device id + 渠道检测 + 命中则自动上报 landing
await trace.initLanding();
// SPA 路由变化时再触发一次(已有当日去重保护,无副作用)
const router = useRouter();
router.afterEach(() => {
void trace.initLanding();
});
return {
provide: { trace },
};
});步骤 3:业务请求拦截器
ts
// composables/useApi.ts 或 plugins/api.ts
export const apiFetch = $fetch.create({
baseURL: useRuntimeConfig().public.apiBase,
onRequest({ options }) {
if (import.meta.client) {
const { $trace } = useNuxtApp();
Object.assign(options.headers ||= {}, $trace.headers);
}
},
});后续所有用 apiFetch(...) 发出的请求都会自动带上 x-tripo-device-id。
SSR 行为
ts
// SSR 阶段
const trace = new TripoTrace({ baseUrl: '...' }); // ✅ 构造器不读 window,安全
await trace.initLanding(); // ✅ 立即 resolve(no-op)
trace.deviceId // === ''
trace.headers // === {}业务侧用 .client.ts plugin 后缀就能保证只在客户端执行;即便忘加,库也不会爆错。
下一步
- 高级用法 — 自定义渠道、错误处理、自定义 fetch
- Playground — 在浏览器实测