React 与 Vue
@track-business/sdk-react 和 @track-business/sdk-vue 为 @track-business/sdk-web 提供框架适配。它们只负责框架 Context、Router、指令/Hook 和错误边界;身份、授权、Session、队列、上传和诊断由 Web SDK 管理。
安装与边界
从 Web SDK 下载页下载离线包并解压到项目的 libs/。安装 Web SDK 和所需框架适配包;React、Vue 和 Router 由宿主项目管理。
# React 项目
npm install ./libs/track-business-web-sdk-2026.11.0/packages/track-business-sdk-web-1.0.0.tgz ./libs/track-business-web-sdk-2026.11.0/packages/track-business-sdk-react-1.0.0.tgz
# Vue 项目
npm install ./libs/track-business-web-sdk-2026.11.0/packages/track-business-sdk-web-1.0.0.tgz ./libs/track-business-web-sdk-2026.11.0/packages/track-business-sdk-vue-1.0.0.tgz使用框架 Router 时,把 autoPage 设为 manual,由 Router Adapter 负责页面事件。不要同时启用自动页面采集,否则一次导航可能生成两个 $pageview。普通 Vanilla SPA 可继续使用 autoPage: true 或 'history'。
const sdk = TrackBusinessSDK.create({
endpoint,
projectKey,
autoPage: 'manual',
});React 18/19
Provider 与 Hooks
import { StrictMode, useRef } from 'react';
import { TrackBusinessSDK } from '@track-business/sdk-web';
import {
TrackBusinessProvider,
useIdentity,
useTrackEvent,
useTrackExposure,
} from '@track-business/sdk-react';
const sdk = TrackBusinessSDK.create({ endpoint, projectKey, autoPage: 'manual' });
function ProductCard() {
const identity = useIdentity();
const ref = useRef<HTMLDivElement>(null);
const onClick = useTrackEvent('product_clicked', { sku: 'SKU-1' });
useTrackExposure(
ref,
'product_card',
{ sku: 'SKU-1' },
{
threshold: 0.5,
minVisibleMs: 1000,
},
);
return (
<div ref={ref} onClick={onClick}>
{identity?.userId ?? 'anonymous'}
</div>
);
}
root.render(
<StrictMode>
<TrackBusinessProvider client={sdk}>
<ProductCard />
</TrackBusinessProvider>
</StrictMode>,
);useIdentity() 订阅身份变化。useTrackExposure 的第二个参数是曝光标识,产生 $sdk_exposure。使用 React StrictMode 时,请验证开发环境不会重复采集。
React Router
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import type { RouteObject } from 'react-router-dom';
import { TrackBusinessReactRouter } from '@track-business/sdk-react/react-router';
const routeObjects: RouteObject[] = [
{ path: '/', id: 'home' },
{ path: '/orders/:orderId/detail', id: 'order-detail' },
];
<BrowserRouter>
<TrackBusinessReactRouter
routes={routeObjects}
routeName={(matches) => matches.at(-1)?.route.id}
/>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/orders/:orderId/detail" element={<OrderDetail />} />
</Routes>
</BrowserRouter>;适配器将动态路径映射为路由模板,并移除当前页面 URL 的 query 和 fragment。若来源页、落地页或业务属性可能包含敏感信息,请按 Web 安全与隐私配置清洗规则。
Error Boundary
import { TrackBusinessErrorBoundary } from '@track-business/sdk-react';
<TrackBusinessErrorBoundary fallback={<ErrorPage />}>
<App />
</TrackBusinessErrorBoundary>;错误会被有界脱敏后记录为 $sdk_exception,并继续经过 Consent、Tracking Plan 和 Outbox;上报失败不会替换宿主 fallback。
Vue 3 / Vue Router 4
import { createApp } from 'vue';
import { TrackBusinessSDK } from '@track-business/sdk-web';
import { createTrackBusinessPlugin } from '@track-business/sdk-vue';
const sdk = TrackBusinessSDK.create({ endpoint, projectKey, autoPage: 'manual' });
const tracking = createTrackBusinessPlugin({
client: sdk,
router,
trackPageViews: true,
trackAppErrors: true,
});
const app = createApp(App);
app.use(router);
app.use(tracking);
app.mount('#app');业务组件可使用组合式 API 与声明式指令。v-track-exposure 中的 event 是曝光标识,生成的事件名为 $sdk_exposure:
<script setup lang="ts">
import { useIdentity, useTrackBusiness } from '@track-business/sdk-vue';
const sdk = useTrackBusiness();
const identity = useIdentity();
</script>
<template>
<button v-track-click="['checkout_started', { source: 'cart' }]">结算</button>
<article
v-track-exposure="{
event: 'product_card',
properties: { sku: 'SKU-1' },
threshold: 0.5,
minVisibleMs: 1000,
}"
>
{{ identity?.userId ?? 'anonymous' }}
</article>
</template>插件忽略失败导航,并在安装时读取当前页面。trackAppErrors 默认关闭;开启后保留宿主已有的错误处理器。微前端卸载时调用 tracking.dispose()。
SSR / Next.js / Nuxt
服务端不得创建 Web Client。服务端渲染时向 Provider 注入 null:
<TrackBusinessProvider client={null}>{children}</TrackBusinessProvider>注入 null 时,事件 Hook 不执行采集,useIdentity() 返回 null;useRequiredTrackBusiness() 会抛出接入错误。客户端挂载后再创建并注入真实 Client。
- Next.js App Router:在带
'use client'的组件中使用useEffect创建 Client,并在清理函数中销毁。Client Component 仍可能参与服务端预渲染,不要在模块顶层或 render 阶段创建 Web SDK。 - Nuxt:只在浏览器创建 Client;
.client.ts插件只限制执行环境,并不保证水合一致。VueuseIdentity()的初次快照统一为null,挂载后才读取与订阅,卸载后忽略迟到通知。组合函数应在组件 setup 中使用,首屏保留相同的空身份占位。Nuxt 的具体插件时机和宿主验证须单独确认。 - 不要把 SDK Client 或身份快照写入 SSR payload、Pinia hydration 数据或 HTML。
Consent 与销毁
默认 Consent 与其他客户端 SDK 一致,为 GRANTED + MINIMAL。需要授权前零身份、零存储和零网络时显式传入:
const sdk = TrackBusinessSDK.create({
endpoint,
projectKey,
autoPage: 'manual',
initialConsent: { status: 'PENDING' },
});
// 仅在宿主或 CMP 确认用户授权后执行。
await sdk.grantConsent('STANDARD');授权后,Router 适配器可记录当前页面,不补报授权前的历史导航。
History 路由默认按路径区分页面;Hash 路由需设置 pageRouting: 'hash',见下文。查询参数和同路径重装不会产生新页面标识。
HMR、微前端卸载或应用 teardown 时调用 await sdk.destroy() 并执行框架插件的 dispose();不要在组件 render/setup 中重复创建 Client。
验证与上线自检
在实际宿主中验证:
- SSR 页面和客户端首次渲染保持一致;客户端 SDK 在浏览器挂载后创建。
- 每次路由导航只产生一条预期的
$pageview,点击和曝光绑定各记录一次。 - 按数据校验核对接收结果,并在目标浏览器验证存储与队列恢复。
Hash 路由
使用 createWebHashHistory 时,在 TrackBusinessSDK.create 中配置 pageRouting: 'hash';使用 createWebHistory 时保持默认 history。框架接管页面采集时使用 autoPage: 'manual'。同一 SDK 实例的页面标识、停留和离开插件会采用相同逻辑路径;URL query 和路径后的锚点不产生新页面。动态参数只用于内存内导航判断,输出路径仍应通过 pagePrivacy.sanitizePath 映射为业务模板。