# @aranova/tracking-react 中文文档

规范地址：https://npmcn.com/package/%40aranova/tracking-react/

版本：1\.21\.0
npm 元数据更新时间：2026-11-07T01:49:51.291Z
中文译文更新时间：2026-11-07T02:19:55.965Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40aranova/tracking-react
原文对照：https://npmcn.com/package/%40aranova/tracking-react/?lang=original
项目主页：https://github.com/AranovaIO/aranova_internal/tree/master/packages/tracking-react
源码仓库：https://github.com/AranovaIO/aranova_internal

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：3.9 MB，34 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：2 个
- peer 依赖：react \>=18\.0\.0
- 首次发布：2026-04-10T07:47:06.498Z
- 最新版本发布：2026-11-07T01:49:51.131Z
- 近 30 天下载量：2069（2026-10-07 至 2026-11-05，npm 官方下载统计）
- 已发布版本数：84（近 12 个月 84 个）

## 中文简介

Aranova客户网站的反应跟踪和同意设施

## 安装

```sh
npm install @aranova/tracking-react
```

也可以使用：`pnpm add @aranova/tracking-react`、`yarn add @aranova/tracking-react`、`bun add @aranova/tracking-react`

## README

# @aranova/ 跟踪- 反应

Aranova客户网站的反应跟踪和同意设施.

## 安装

```bash
npm install @aranova/tracking-react
```

## 设置

创建共享跟踪模块并导入范围 `TrackingProvider` 编号 : `useTracking` 从那个模块 整个您的应用程序.

```ts
// src/lib/tracking.ts
import { createTracking } from "@aranova/tracking-react";
import { ARANOVA_TRACKING_CONFIG } from "./aranova-services";

export const { TrackingProvider, useTracking } = createTracking({
  apiKey: import.meta.env.VITE_ARANOVA_TRACKING_API_KEY,
  endpoint: import.meta.env.VITE_ARANOVA_TRACKING_ENDPOINT,
  trackingConfig: ARANOVA_TRACKING_CONFIG,
  triggers: {
    automatic: {
      page_view: {},
      time_on_site: { thresholdSeconds: 60 },
      specific_page_visit: {
        pages: [
          { name: "contact_page", pathPattern: /^\/(contact|book|get-started)/ },
          { name: "google_ads_service_page", pathPattern: /^\/services\/google-ads\/?$/ },
        ],
      },
    },
    manual: {
      form_submit: {},
      phone_click: {},
      cta_click: {},
    },
  },
  debug: import.meta.env.MODE !== "production",
});
```

在您反应树根上挂载提供者 .

```tsx
// src/main.tsx
import { createRoot } from "react-dom/client";
import { App } from "./App";
import { TrackingProvider } from "./lib/tracking";

createRoot(document.getElementById("root")!).render(
  <TrackingProvider>
    <App />
  </TrackingProvider>,
);
```

### 遗留的静态 gtag 标识

`gtagId`, (中文(简体) ), `gtagIds`, (中文(简体) ), `GoogleAdsTracking`,并生成 `ARANOVA_GTAG_IDS` 保留 相容性 APIs. 不要用于新安装: 静态ID不能消耗仪表板 标记更改或墓碑而不进行重新部署。 如果维持一个遗留装置, `gtagIds` 装入每个条目并优先于 `gtagId`。 。 。 .

```tsx
<TrackingProvider gtagIds={{ production: "AW-111111111", test: "AW-222222222" }}>
  <App />
</TrackingProvider>
```

## 手动事件

手动活动必须在 `triggers.manual` 在此之前 `trackEvent()` 接受他们.

```tsx
import { useTracking } from "./lib/tracking";

export function LeadForm() {
  const tracking = useTracking();

  function handleSubmit(event: React.FormEvent<HTMLFormElement>) {
    const form = event.currentTarget;
    const data = new FormData(form);

    tracking.trackEvent("form_submit", {
      form: {
        id: form.id,
        action: form.getAttribute("action"),
        fields: [
          {
            name: "service_interest",
            type: "select",
            label: "Service interest",
            value: String(data.get("service_interest") ?? ""),
          },
          {
            name: "is_existing_patient",
            type: "checkbox",
            label: "Existing patient",
            value: data.get("is_existing_patient") === "on",
          },
        ],
      },
      page: { path: window.location.pathname },
    });
  }

  return (
    <form id="lead-form" action="/api/lead" onSubmit={handleSubmit}>
      {/* fields */}
    </form>
  );
}
```

`fields[].value` 可以是任何 JSON 值:字符串、数字、布尔、无效、数组或对象。 值必须是JSON-可序列化的,因为事件被存储为一党JSONB. 有意提交的牵头字段可能包括生名,电子邮件,电话号码,地址,选取,自由文本消息,以及提交用于第一当事方分析及牵头操作的文件数据. 从提交表单中明确构建数组; SDK 从未刮出任意 DOM 字段 . `File`编号 :`Blob` 对象必须转换为 JSON 表示; 单独上传更大的文件并发送其存储引用。 事件元数据上没有执行字节限制——但是在导航冲出之前,一个提交文件已发射 `keepalive`,它的浏览器在64 KB附近并静静地下降,所以保持内嵌的有效载荷小. 从不发送密码,认证符,付款卡/银行证书,或私人密钥. 适用客户的隐私通知、同意、保留和规范的数据要求。 Google离线匹配使用正常的,服务器侧 SHA-256-hashed标识符——而不是原始的自由文本/文件元数据.

### 电话点击数 (`tel:` • 手动或自动抓取

选择到 **自动抓取** 和每个 `tel:` 链接被跟踪,没有每个链接代码。 添加 `autoCapture` 页:1 `phone_click` 登记 —— 由单一授权的点击听器进行其余:

```tsx
manual: {
  phone_click: { autoCapture: {} }, // default selector: a[href^="tel:"]
  // or narrow it: { autoCapture: { selector: "a.call" } }
},
```

```tsx
<a href="tel:+14165550199" data-aranova-section="header">
  (416) 555-0199
</a>
```

数字是从 `href` (已正式改为E.164); `section` 来源于可选 `data-aranova-section`。 。 。 . **与 `cta_click`页:1 `phone_click` 还炒了Google广告 转换** 联系电话目标(a) `CLICK_TO_CALL` ——自动点火 窃听器被捕获了,所以你从不打电话 `trackConversion` (firring需要销售客户 与电线 相同的配置;见下文).

喜欢用仪器连接自己吗? 从一个点击处理器中发射它 同样的方式:

```tsx
tracking.trackEvent("phone_click", {
  phone_number: "+14165550199",
  page: { path: window.location.pathname },
  section: "header",
});
```

### CTA 点击- 手动或自动抓取

开火 `cta_click` 完全控制这个名字:

```tsx
tracking.trackEvent("cta_click", {
  cta_name: "Book appointment",
  section: "hero",
  destination_url: "/booking",
  page: { path: window.location.pathname },
});
```

或者选择加入 **自动抓取** 并跳过每个按钮代码。 添加 `autoCapture` 页:1 `cta_click` 注册——此选项包含一个获得授权的点击听器:

```tsx
manual: {
  cta_click: { autoCapture: {} }, // default selector: [data-aranova-cta]
  // or target existing classes: { autoCapture: { selector: "a.cta, .btn-primary" } }
},
```

然后标记您的 CTA 在标记中—— 没有进口, 没有处理器 :

```tsx
<a href="/booking" data-aranova-cta="Book now" data-aranova-section="hero">Book now</a>
<button data-aranova-cta="Get a quote">Get a quote</button>
```

`cta_name` 决定: `data-aranova-cta` 值, 否则元素的修剪文本 (封顶120个字符),其他 `tag#id`。 。 。 . `section` 来源于可选 `data-aranova-section`· ; `href`编号 :`destination_url` 和一个短 `element` 描述器是自动捕获的。 点 真实的 CTAs 选择器( 一个明确的属性是安全默认) — 每次匹配点击 计数,包括后面的 `stopPropagation`。 。 。 .

### 自动居中+退出( E)`page_exit`(中文(简体) )

`page_exit` 自动捕获——没有注册。 在 SPA 导航、标签隐藏和 页面卸载它记录 **活动** (可见)花在页面上的时间加上最大卷轴 深度已经达到,通过一个恒定信标交付,所以最后一页仍然算数. 这个权力 每页寄存和寄存在仪表板分析分页中;没有配置.

## 键入的铅表单

生成网站的铅格式合同一次并通过它发送,所以需要放弃 字段失败 `tsc` 而不是丢失线索 :

```bash
npx @aranova/tracking-cli forms gen   # writes src/aranova-lead-forms.ts; `forms check` in CI
```

```tsx
import { createLeadFormSubmit, slotFields } from "@aranova/tracking-react";
import { ARANOVA_LEAD_FORMS } from "@/aranova-lead-forms";

const leadForms = createLeadFormSubmit(useTracking(), ARANOVA_LEAD_FORMS);
leadForms.submit({
  formId: "booking-form",
  kind: "booking",
  fields: { given_name: values.firstName, phone: values.phone, ...slotFields(values.slot) },
});
```

开发记录每项违反合同行为, `debug` 扔出, 生产发送, 无论如何标记 `form.contract_violations`。 手建不整齐 `form_submit` 用于生产 (标记) `invalid_shape`而不是放弃。 全向导 : [文件/跟踪-包装/铅形式](https://npmcn.com/package/docs/tracking-package/lead-forms.md)。 。 。 .

提交后的可选问题(病人类型、时间、他们是如何听到的)附在后面的 领头 握着手柄 `submit()` 返回并传递给 `addDetails()` 从谢幕. 那个屏幕是 `<section>` 有按钮,永远不要 `<form>`: 表格记录它自己的 `form_start` (在漏斗中从未提交表格)并在Enter上提交.

```tsx
const { submission } = leadForms.submit({ formId: "booking-form", kind: "booking", fields });
setSubmission(submission); // then render the post-submit <section>

// "Add to my request" button's onClick: every role is optional here, nothing is owed.
leadForms.addDetails(submission, {
  fields: { patient_type: answers.patientType, note: answers.note, email: answers.email },
  extra: [{ key: "heard_from", label: "How did you hear about us?", value: answers.heardFrom }],
}); // { sent: false, reason: "no_fields" } when every answer is blank
```

## 电话字段

捆绑 `libphonenumber-js`: 剖析/格式 utils + a React 输入. 显示可配置 发送到后端的值是 **总是E.164**配置一次通过 `createTracking({ phone: { defaultCountry: 'CA', display: 'national' } })`。 。 。 .

```tsx
import { usePhoneField, PhoneField, toE164 } from "@aranova/tracking-react";

const phone = usePhoneField(); // phone.value (display), phone.e164 (wire), .isValid, .error
<input {...phone.inputProps} />; // or the batteries-included <PhoneField name="phone" />

toE164("416-555-0199"); // '+14165550199' (null if invalid)
```

纯,同位素的同位素也有 `@aranova/tracking-react/phone` (无回放. 全向导 : [电话:md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/phone.md)。 。 。 .

## 记录销售

记录销售/转换(一等可变资源——不是火灾和遗忘) 活动)。 货币为整数小单位(美分); `currency` 是一个需要的 ISO-4217 enum.

一个异形 `createSalesClient` (在根入)服务双方——什么是 键可能由后端执行,而不是通过隐藏方法。 浏览器写入方式  **公开** 键 :

```tsx
import { createSalesClient, toMinor } from "@aranova/tracking-react";

const sales = createSalesClient({
  apiKey: import.meta.env.VITE_ARANOVA_TRACKING_API_KEY,
  endpoint,
});
await sales.record({ currency: "CAD", amount_total_cents: toMinor(250, "CAD"), service: "tires" });
```

读取/ 完整 CRUD 需要 **隐藏** 键,并且必须运行服务器端——从不运送 浏览器捆绑中的密钥。 在 Vite + Vercel 应用程序中,在无服务器中保存 函数。 从 **`/sales`** 子路径——它是无反应的,所以服务器 捆绑从不拉入提供者/组件 :

```ts
// api/sales.ts  (Vercel serverless function — runs on the server)
import { createSalesClient } from "@aranova/tracking-react/sales";

const sales = createSalesClient({
  apiKey: process.env.ARANOVA_TRACKING_SECRET_KEY!,
  endpoint: process.env.ARANOVA_TRACKING_ENDPOINT!,
});
export default async function handler(_req, res) {
  res.json(await sales.list({ limit: 50 }));
}
```

密钥读取电源仪表板(所有货币组合——从未跨货币总和):

```ts
await sales.summary({ range: "mtd", timezone: "America/Toronto", compare_to: "previous_period" });
await sales.list({ sort: "amount_total_cents", want_total: true }); // → { items, total_count, … }
await sales.customers.list({ segment: "returning", sort: "total_spent" }); // phone-keyed roster
await sales.customers.summary({ range: "mtd" });
const cfg = await sales.business.config(); // tz / currencies / services (pk or sk)
```

`summary()` 记分日历/关税范围, `granularity`,以及期末 `compare_to`; 遗产 `24h/7d/30d` 不变。 A 类 **顾客是他们的电话(E.164)** —— 说 `customers.*` 是一个活人名册,没有单独的表格。 任何读数的公用钥匙客户端都会收到 `403`。 。 。 .

根项`@aranova/tracking-react`仍在再出口 `createSalesClient` 编辑 货币/日期帮助者进行反相匹配,因此现有的进口继续发挥作用——但更愿意 `/sales` 在服务器代码中, 反应表面不会到达您的服务器捆绑 .

生成类型 `AranovaService` 由您与 CLI 的仪表板服务合并 (装作 **依赖性**:

```bash
npm install --save-dev @aranova/tracking-cli
npx @aranova/tracking-cli gen          # reads ARANOVA_TRACKING_SECRET_KEY from .env
```

见完整指南: [销售追踪](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/sales-tracking.md) 和CLI参考文献: [(单位:千美元)](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/cli.md)。 。 。 .

## 订货交割(订货一体化)

当商业书籍通过一个集成(今日AutoLeap), 已出版的跟踪配置 携带 `integrations.autoleap.booking`。在牵头表格成功提交之后(和 `form_submit` 提供可选的“选择时间”步骤:

```tsx
import { BookingHandoffLink } from "@aranova/tracking-react";
import { ARANOVA_TRACKING_CONFIG } from "@/aranova-services";

<BookingHandoffLink
  trackingConfig={ARANOVA_TRACKING_CONFIG}
  fallbackUrl="https://myalp.io/…" // baked last resort when no config has loaded
  prefill={{ firstName, lastName, phone, email }}
>
  Pick your time
</BookingHandoffLink>;
```

-   链接是商店自己的订书页 从现场配置, 否则 `fallbackUrl`; 它会使 没有,除非是 `https://myalp.io/…`电话以数字形式发出.
-   它显示,即使 `enabled` 虚假的:顾客总是有预订的方法.
-   `useBookingIntegration(trackingConfig)` 返回现场提供者(或在配置前无效) ),来自共享配置运行时间(没有额外获取) : `enabled`, (中文(简体) ), `fallbackUrl`, (中文(简体) ), `acceptsBookings`, (中文(简体) ), `timezone`, (中文(简体) ), `configVersion`, (中文(简体) ), `rules` 财务报告和审定财务报表 `options`。 。 。 . `getBookingIntegration(integrations)` 财务报告和审定财务报表 `buildBookingHandoffUrl(url, prefill)` 这是 反应自由等同.
-   报告 `booking_handoff` 能力.

## 网站预订(订书一体化)

何时 `acceptsBookings` 网站可以通过Aranova直接订入店铺系统 API (英语). SDK是无头;在站点自己的设计系统中构建出形式:

```tsx
import { useBookingIntegration, useBookingSlots, useBookingSubmit } from "@aranova/tracking-react";

const booking = useBookingIntegration(ARANOVA_TRACKING_CONFIG);
const days = useBookingSlots(ARANOVA_TRACKING_CONFIG); // [{ date, weekday, morning, afternoon }]
const { status, outcome, submit } = useBookingSubmit(conversions.bookings, {
  formSubmit: {
    tracking,
    formId: "booking-form",
    // Your own questions, for our reporting only; never sent to the shop.
    extraFields: [
      { name: "heardVia", type: "select", label: "How did you hear about us?", value: heardVia },
    ],
  },
});

await submit({
  startDate: "2026-10-06",
  startHour: 9,
  firstName,
  lastName,
  phone,
  email,
  vehicle: { year: 2019, make: "Toyota", model: "RAV4" },
  dropOff: "dropOff", // only when booking.rules.dropOffOptions is non-empty
  services: ["brakes"], // keys from booking.options
  notes,
  marketingSmsConsent, // the customer's own unchecked opt-in; never default it on
});
```

-   `conversions` 是一个网站 `createSalesClient({ apiKey, endpoint, firing: getTrackingConfigRuntime(...) })`· ; `.bookings` 阅读规则 从运行时间.
-   `outcome.status`数字 : `created` (商店的短信和电子邮件给客户本身;不发送 你们自己人, `pending` (同样成功;仍在发送中,如果失败,则提醒所有者; `status` 转弯 `pending` 一旦服务器这么说, 而最后的答案是民意调查, `failed` (成功副本加 `outcome.fallbackUrl`,预填的商店页面, `invalid` (单位:千美元)`outcome.message`没有寄出去, `stale` (时代已变;相貌被回放).
-   `outcome.mode` (和 `booking.mode` 在提交之前: `live` 每个真正的客户; `test` (同意店铺测试铅源)或 `simulated` (从来没有)在测试访问或 非生产 API. 显示一个小的“ 测试预订” 注释, 当它不是 `live`。 。 。 .
-   仅限开发: `useBookingSubmit(bookings, { simulate: "failed" })` 强制模拟 结果`created`, (中文(简体) ), `rejected`, (中文(简体) ), `unknown`, (中文(简体) ), `failed`)来锻炼每个屏幕。 生产 API无视. 本地测试针对本地 API **财务报告和审定财务报表** 本地CDN; SDK 警告在 当终点是本地主机时控制台,但配置来自生产.
-   `booking.options` 按商店服务类别分类: `group` (标题, 或者说 `null`)和可选 `description`。 。 。 . `groupBookingOptions(booking.options)` 返回时 `[{ group, options }]` 因此,将每组一个标题放在它的下面.
-   `useBookingSlots` 编号 : `bookableSlots(rules, { timeZone })` 提供入口的启动时间, 根据店里的日期判断. `useBookingSubmit` 通过双击重用一个尝试键或 重试一次,然后送来 `form_submit` 一次:不要为这个表格寄出自己的表格. 这是一个 类型 `booking` 提交(ADR-0024):每个字段都有合同 `role`, (中文(简体) ), `service` 这是 选项密钥, `preferred_date` 实值 `YYYY-MM-DD`, (中文(简体) ), `preferred_time` 实值 `{ start: "HH:00", end: null }`,以及 `drop_off` 实值 `wait-for-it` 编号 : `drop-off`中添加表单的问题 `formSubmit.extraFields`; 预订已报告的名称( q)`phone`, (中文(简体) ), `email`,.)被丢弃.
-   分别询问姓氏,并使用手机号码(店内确认文字去取).
-   预订后的详情( 当 `booking.rules.vehicleDeferred`,用于额外笔记,或网站 回答: `updateBooking({ vehicle, notes, heardVia })` 从同一个钩子。 它决定 `updated` 编号 : `queued` 编号 : `notified_owner` (全部已保存)或 `invalid`, (中文(简体) ), `mismatch`, (中文(简体) ), `conflict`, (中文(简体) ), `not_found`, (中文(简体) ), `failed` (仅限 `failed` 值得重试。 要活下来的重载, 保存 `booked` (单位:千美元)`{ bookingId, attemptKey }`(中文(简体) ) 内 `sessionStorage` 并传回: `updateBooking(details, saved)`。 。 。 . `heardVia` 只有报告 永远不能到达店铺 它的值和表型相同 `heardVia` `form_submit` 字段, 因此,在成功屏幕上问它 而不是表格报告相同。 每预订一次更新, 所以用延迟的车辆而不是第二次呼叫.
-   报告 `booking_integration` 能力.

## 现场转换射击

运行 `tracking-cli gen` 一次发射 `ARANOVA_TRACKING_CONFIG`,然后使用这个 google追踪系统已初始化。 R2是权威的: SDK确认 发送 Google 标签、页面视图或转换命令之前的当前对象。 盘子 标记更改、目标再映射和废旧状态墓碑 `public, max-age=60, must-revalidate` 没有运行或站点重新部署.

```ts
import {
  createSalesClient,
  createTracking,
  getTrackingConfigRuntime,
  toMinor,
} from "@aranova/tracking-react";
import {
  ARANOVA_TRACKING_CONFIG,
  type AranovaConversion,
  type AranovaService,
} from "./aranova-services";

const googleTracking = getTrackingConfigRuntime(ARANOVA_TRACKING_CONFIG);

export const { TrackingProvider, useTracking } = createTracking({
  apiKey,
  endpoint,
  triggers,
  trackingConfig: ARANOVA_TRACKING_CONFIG,
});

// Bind the generated unions so `service` and `trackConversion` keys are type-checked.
const sales = createSalesClient<AranovaService, AranovaConversion>({
  apiKey,
  endpoint,
  firing: googleTracking,
});

await sales.recordSale({
  currency: "CAD",
  amount_total_cents: toMinor(250, "CAD"),
  service: "tires",
}); // records + fires
```

-   **自动事件目标** 当其注册的探测器越过公布的阈值时起火.
-   **销售+人工目标** 使用上面的共享运行时间。 射击是经过同意的, 交易已编辑,并且只浏览器.

**手动转换(多形式) :** 一次登记触发器,然后呼叫 `trackConversion(key)` 每个表格的提交处理器。 关键出自仪表板目标分页(活动目标有: `form_submit`编号 :`phone_click`编号 :`cta_click` 触发器已映射到WEBPAGE 动作),并作为 `AranovaConversion` 工会 `gen` 因此,他们自动完成并拒绝打字:

```ts
// createTracking({ …, triggers: { manual: { form_submit: {} } } })  // register once

// in the contact form's onSubmit:
sales.trackConversion("contact_form"); // ✅ typed by AranovaConversion
// in the demo form's onSubmit:
sales.trackConversion("demo_request");
sales.trackConversion("typo"); // ❌ compile error — not a known goal key
```

每一次呼叫火灾 **仅限** 用于这一目标的WEBPGE转换(无) `/sales` 写入); SDK 如果球门没有被标定的话,就不要了 重映射已存在的密钥不需要代码 。 A 类 **新手册 目标密钥** 仍然需要 `tracking-cli gen` 要刷新 `AranovaConversion`,加站点处理器 接线. `ARANOVA_CONFIG_URL` 财务报告和审定财务报表 `conversionConfig: { cdnUrl }` 遗留的相容性 API; 不用于新安装 。 见 [转换-配置-schema.md](https://github.com/AranovaIO/aranova_internal/blob/master/docs/tracking-package/conversion-config-schema.md)。 。 。 .

`ARANOVA_TRACKING_CONFIG` 携带商业身份, SDK 构成对象 URL 反对生产CDN—— `endpoint` 选项只移动 **摄入事件**,而不是配置 获取。 要读取来自其它地方的配置( 本地对象商店), 设置 `REACT_APP_ARANOVA_CDN_BASE_URL`;生成的模块已经读取并返回到 因此不需要更改代码。 把它放在生产中.

> **在手动进球之前,** `gen` 发出空 `ARANOVA_CONVERSIONS`这样 `AranovaConversion` 决定: `never` 约束它(`createSalesClient<AranovaService, AranovaConversion>`然后让 **每个** `trackConversion` 调用编译错误。 直到你画出至少一个手动的入球 重新运行 `gen`,仅绑定服务通用(`createSalesClient<AranovaService>(…)`; 转换键默认值返回到 `string`。 。 。 .

## 同意(v2——选择退出模式)

追踪是 **默认**: gtag,"Meta"像素,以及现场转换的射击全部从第一颜料上跑出,除非访客已存储了明确而未到期的下降. 降级是值得的 **90天时间** (然后,来访者转而接受违约赠款);明确的补助金从未到期。) 没有 `pending` 状态和包件船 **未经同意** ——每个网站提供自己的脚步"cookie偏好"控制并披露其隐私政策中的跟踪(该通知是使得选择退出模式可以防守的原因).

### 脚下控制 - `useCookiePreferences()`

```tsx
import { useCookiePreferences } from "@aranova/tracking-react";

function CookiePreferences() {
  const { isDenied, isDefault, optOut, optIn } = useCookiePreferences();

  return isDenied ? (
    <button onClick={optIn}>Enable ad measurement</button>
  ) : (
    <button onClick={optOut}>Opt out of ad measurement</button>
  );
}
```

钩子返回有效 `state` (单位:千美元)`"granted" | "denied"`页:1 `source` (单位:千美元)`"default"` =没有明确的选择, `"explicit"`),布尔助手(`isDefault` 编号 : `isGranted` 编号 : `isDenied`),选择 `updatedAt` 编号 : `expiresAt`,则 `optOut()` 编号 : `optIn()` 编号 : `reset()` 行动。 它与同一标签中的其他组件保持同步(通过 `onConsentChange`)和其他标签(通过 `storage` 活动). `optOut` 通过钩子接受自定义 TTL `{ declineTtlDays }` 选项.

对于非组件背景,则导出相同的原始元素为平面函数: `optOut()`, (中文(简体) ), `optIn()`, (中文(简体) ), `resetConsent()`, (中文(简体) ), `getConsentChoice()`,以及 `onConsentChange()`。 。 。 .

### 已折旧的选入流量

`<ConsentBanner />`, (中文(简体) ), `useConsent()`,以及 `useConsentState()` 为: `@deprecated` 并计划清除。 旗帜是 **永久惯性** 它只是在同意时才作出 `pending`因此,把它挂起来是无害的,但毫无意义. `useConsent()` 仍作him活`isPending` 总是 `false`· ; `accept`编号 :`decline` 地图到 `optIn`编号 :`optOut`) (中文(简体) ).

**从横幅上移去:** 删除 `<ConsentBanner />`,添加一个基于 `useCookiePreferences`,并在隐私政策中提及跟踪+选择退出。 现有参观者储存的赠款准予停留;自升级后的首次参观起,储存量下降被拒绝停留90天.

## 出口

-   `createTracking()`
-   `TrackingProvider` 范围 `useTracking`
-   `AdPlatformTracking` 财务报告和审定财务报表 `getTrackingConfigRuntime`; 遗产 `GoogleAdsTracking`
-   同意(v2): `useCookiePreferences()` + 键 `UseCookiePreferencesResult`; 独立 `optIn()`, (中文(简体) ), `optOut()`, (中文(简体) ), `resetConsent()`, (中文(简体) ), `getConsentChoice()`, (中文(简体) ), `onConsentChange()`, (中文(简体) ), `getConsentState()`, (中文(简体) ), `setConsentState()`
-   无效的同意: `ConsentBanner` + 键 `ConsentBannerProps`, (中文(简体) ), `useConsent()` + 键 `UseConsentResult`, (中文(简体) ), `useConsentState()`
-   归属钩: `useTrackingParams()`, (中文(简体) ), `useGclid()`
-   `createSalesClient()` (异同——公用钥匙写作;密钥读取/CRUD, `summary`, (中文(简体) ), `customers.*`, (中文(简体) ), `business.config`\+ 金钱/约会助手(`toMinor`编号 :`fromMinor`编号 :`formatMoney`编号 :`formatDateInTz`) (中文(简体) ). 也可以在 **`@aranova/tracking-react/sales`** (包含所有销售/客户/配置类型)——推荐的服务器/服务器无服务器代码导入.
-   电话: `parsePhone`编号 :`toE164`编号 :`formatPhone`编号 :`formatPhoneAsTyped`编号 :`phoneField`, (中文(简体) ), `usePhoneField`, (中文(简体) ), `PhoneField` (截至2001年12月31日的 `/phone`(中文(简体) )
-   代码: [`@aranova/tracking-cli`](https://www.npmjs.com/package/@aranova/tracking-cli) —— 说 `gen` 类型服务工会(依赖性)
-   事件元数据/配置类型,例如 `FormSubmitMetadata`, (中文(简体) ), `PhoneClickMetadata`,以及 `JsonValue`

## 常见问题

### @aranova/tracking-react 是什么？

Aranova客户网站的反应跟踪和同意设施

### 如何安装 @aranova/tracking-react？

在项目目录运行 npm install @aranova/tracking-react，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：react（\>=18\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @aranova/tracking-react 支持 TypeScript 吗？

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

### @aranova/tracking-react 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @aranova/tracking-react 可以商用吗？

@aranova/tracking-react 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @aranova/tracking-react 的下载量有多少？

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

### @aranova/tracking-react 还在维护吗？

最新版本 1\.21\.0 发布于 2026/11/07（今天）；至今共发布 84 个版本，其中过去 12 个月发布了 84 个；首次发布于 2026/04/10。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

