---
code: javascript_sdk_advanced
name: "进阶指南"
wikiToken: XB4ywbB3LiMvFWkDUVDcRY0pnlm
parentWikiToken: Ian8wU157i7or8kW1ORccuT8nWe
updateTime: 1763108517000
sourceUrl: https://docs-v2.thinkingdata.cn/?version=v5.0&lan=zh-CN&code=javascript_sdk_advanced
---
# 进阶指南

### 一、设置用户 ID

SDK 实例默认会使用随机数作为每个用户的默认访客 ID，该 ID 将会作为用户在未登录状态下身份识别 ID。需要注意的是，访客 ID 在用户清理缓存以及更换设备时将会变更。

#### 1.1 设置访客 ID

::: tip 提示

 一般情况下，您不需要自定义访客 ID. 请确保已经理解用户识别规则，再进行访客 ID 的设置。

 :::

```
ta.setDistinctId("Thinker");
```

如果需要获得访客 ID，可以调用 `getDistinctId` 获取：

```
//返回访客ID
var distinctId = ta.getDistinctId();
```

#### 1.2 设置账号 ID

在用户进行登录时，可调用 `login` 来设置用户的账号 ID， AE 平台将会以账号 ID 作为身份识别 ID，并且设置的账号 ID 将会在调用 `logout` 之前一直保留。多次调用 `login` 将覆盖先前的账号 ID 。

```
// 用户的登录唯一标识，此数据对应上报数据里的#account_id，此时#account_id的值为TA
ta.login("TA");
```

<!-- unsupported block: 34 -->

**该方法不会上传登录事件**

#### 1.3 清除账号 ID

在用户产生登出行为之后，可调用 `logout` 来清除账号 ID，在下次调用 `login` 之前，将会以访客 ID 作为身份识别 ID。

```
ta.logout();
```

我们推荐您在登出操作时调用 `logout`，比如用户产生了注销账号这一行为时才调用，而不需要在关闭应用时调用。

<!-- unsupported block: 34 -->

**该方法不会上传登出事件**

### 二、发送事件

在 SDK 初始化完成之后，您就可以进行数据埋点，收集用户的的行为信息。一般情况下普通事件即可满足业务场景需求，您也可以根据自己的实际业务场景使用首次、可更新等事件。

#### 2.1 普通事件

您可以调用 `track` 来上传事件，建议您根据先前梳理的文档来设置事件的属性以及发送事件的条件，此处以用户购买某商品作为范例：

```
ta.track(
  "product_buy", //事件名称
  { product_name: "商品"} //事件属性
);
```

#### 2.2 首次事件

首次事件是指针对某个设备或者其他维度的 ID，只会记录一次的事件。例如在一些场景下，您可能希望记录在某个设备上的激活事件，则可以用首次事件来上报数据

```
ta.trackFirst({
  eventName: "device_activation",
  properties: { key:"value" }
});
```

如果您希望以设备以外的其他维度来判断是否首次，则可以为首次事件自定义first_check_id:

```
// 将用户 ID 设置为首次事件的 FIRST_CHECK_ID，实现用户首次激活事件的采集
ta.trackFirst({
  eventName: "account_activation",
  firstCheckId: "TA",
  properties: { key: "value"}
});
```

<!-- unsupported block: 34 -->

注意：由于在服务端完成对是否首次的校验，首次事件默认会延时 1 小时入库。

#### 2.3 可更新事件

您可以通过可更新事件实现特定场景下需要修改事件数据的需求。可更新事件需要指定标识该事件的 ID，并在创建可更新事件对象时传入。AE 后台将根据事件名和事件 ID 来确定需要更新的数据。

```
// 示例： 上报可被更新的事件，假设事件名为 UPDATABLE_EVENT
// 上报后事件属性 status 为 3, price 为 100
ta.trackUpdate({
  eventName: "UPDATABLE_EVENT",
  properties: { status: 3, price: 100 },
  eventId: "test_event_id"
});

// 上报后事件属性 status 被更新为 5, price 不变
ta.trackUpdate({
  eventName: "UPDATABLE_EVENT",
  properties: { status: 5 },
  eventId: "test_event_id"
});
```

#### 2.4 可重写事件

可重写事件与可更新事件类似，区别在于可重写事件会用最新的数据完全覆盖历史数据，从效果上看相当于删除前一条数据，并入库最新的数据。AE 后台将根据事件名和事件 ID 来确定需要更新的数据。

```
// 示例： 上报可被重写的事件，假设事件名为 OVERWRITE_EVENT
// 上报后事件属性 status 为 3, price 为 100
ta.trackOverwrite({
  eventName: "OVERWRITE_EVENT",
  properties: { status: 3, price: 100 },
  eventId: "test_event_id"
});

// 上报后事件属性 status 被更新为 5, price 属性被删除
ta.trackOverwrite({
  eventName: "OVERWRITE_EVENT",
  properties: { status: 5 },
  eventId: "test_event_id"
});
```

#### 2.5 设置公共事件属性

 在采集数据的过程中，有一些字段会被多个事件所共用，比如发生在同一页面上的所有事件，都应该带有这个页面的页面属性，用户的账号信息应该在所有数据中都带有。那么在调用 `track` 上报事件时，这些属性每次都需要设置一遍，针对这样的属性，可以使用公共属性设置接口来统一设置。

 在介绍如何设置公共属性之前，您需要先了解三种类型的公共属性的特性，根据实际需求，选用适合的类型：

- 静态公共属性: 对所有页面生效. 优先级最低，开启缓存的情况下，会缓存在 localStorage 或 cookie 中。只能设置定值。
- 页面公共属性: 针对当前页面生效，优先级最高。如果重新初始化 SDK，页面公共属性会被清空。只能设置定值。
- 动态公共属性: 优先级次于页面公共属性，重新初始化 SDK 后，需要再次设置动态公共属性，可以设置动态变量。
##### 2.5.1 设置静态公共属性

 对于一些重要的属性，譬如用户的渠道、昵称、ID 等，这些属性需要设置在每个事件中，您可以调用`setSuperProperties` 来设置静态公共事件属性，静态公共事件属性会对全局生效。当开启缓存时（默认打开），静态公共属性会缓存在 `localStorage` 或 `cookie` 中。

 静态公共属性的参数是一个 JSON 对象，其格式要求与事件属性保持一致。

```
// 设置公共事件属性，所有数据事件中都会带有这些属性
ta.setSuperProperties({ channel: "渠道名", user_name: "用户名" });
```

 除了属性设置，我们也提供其他API来操作静态公共事件属性，满足日常的业务需求。

```
// 获取静态公共事件属性
var superProperties = ta.getSuperProperties();
// 清除一条静态公共事件属性，比如将之前设置 'channel' 属性清除，之后的数据将不会该属性
ta.unsetSuperProperty("channel");
// 清除所有静态公共事件属性
ta.clearSuperProperties();
```

##### 2.5.2 设置页面公共属性

 对于一些页面中的静态属性，比如一个页面的名称或者地址，您可能希望在这个页面中触发的所有事件上都加入这个属性。类似这样的、需要适用于页面中所有事件的静态属性，您可以使用 `setPageProperty` 进行设置，请注意，使用 `setPageProperty` 设置的公共属性只对当前页面有效

```
// 将页面 ID 设置为页面公共属性，该页面中触发的所有事件，都会带有以下属性
ta.setPageProperty({ page_id: "page10001" });
```

如果您希望获取当前页面的页面公共属性，可以调用`getPageProperty`来获取

```
// 获取当前页面的页面公共属性
var pageProperty = ta.getPageProperty();
```

##### 2.5.3 设置页面动态公共属性

通过 `setDynamicSuperProperties` 设置动态公共属性的回调函数，SDK 将会在事件上报时触发回调函数，并把返回 JSON 对象加入到事件属性中。`setDynamicSuperProperties` 的参数是一个函数，函数需要返回一个 JSON 对象。

```
// 设置动态公共属性，在事件上报时触发回调函数，并把返回的JSON对象加入到事件属性中
ta.setDynamicSuperProperties(function() {
  var d = new Date();
  d.setHours(10);
  return { date: d };
});
```

#### 2.6 记录事件时长

 如果您需要记录某个事件的持续时长，可以调用 `timeEvent` 来开始计时。配置您想要计时的事件名称，当您上传该事件时，将会自动在您的事件属性中加入 `#duration` 这一属性来表示记录的时长，单位为秒。需要注意的是，同一个事件名只能有一个在计时的任务。

```
//以下示例，完成用户在某个商品页面停留时长的统计
ta.timeEvent("stay_shop");
/**do someting
    .......
**/
//用户离开商品页面，计时结束，"stay_shop" 这一事件中将会带有表示事件时长的属性#duration
ta.track("stay_shop",{product_name:"商品名"});
```

#### 2.7 批量发送

SDK 版本需 1.6.1 及以上支持数据批量发送

```
var config = {
    appId: '2f2d8810817c4cbfb7c38aeb8466615a',
    serverUrl: 'https://receiver-ta-preview.thinkingdata.cn',
    send_method: 'ajax',
    //开启批量发送，默认为false
    batch:true
     //或者
    batch: {
        size: 6,//达到size条数据自动触发上报 默认为6
        interval: 6000,//间隔多少毫秒，立即发送，默认6S
        maxLimit:500//本地最多缓存的数据条数，默认为500条
    },
};
```

- batch：是否开启数据批量发送，非必填默认值为false
- size：达到size条数据自动触发上报，默认为6，最小值为1，最大值30
- interval：发送时间间隔，默认为6000
- maxLimit: 本地最多缓存的数据条数，默认为500条
注意：

1. 批量发送功能和回调函数功能不可同时使用，比如 track 加了 callback ，使用批量发送后 callback 不会执行。
1. 批量发送默认使用 ajax 的方式发送数据。
1. 如果 localStorage 里已经存了超过 200 条数据，会导致批量发送功能失效，localStorage 中只保存这 200 条数据，新产生的数据使用配置方式发送数据20localStorage中存储的数据条数超过最大值时，按照先进先出的策略，每次移除20条数据，同时对这20条数据进行一次数据发送。
1. app_js_bridge 和 batch_send 只能选择一个，开启了打通就不能再用批量发送。
1. 使用localstorage存储。
1. debug或者debugOnly会直接发送数据，不会缓存到本地然后批量上报。
1. 开启之后，需满足指定的条数或者指定的时间间隔才会上报数据，对于一些频繁跳转的页面，可能来不及上报，页面就关闭了，导致部分数据丢失的情况，需谨慎开启。
### 三、用户属性

 AE 平台支持的用户属性设置API有: `userSet`、`userSetOnce`、`userAdd`、`userUnset`、`userDelete`、`userAppend`、`userUniqAppend`。

#### 3.1 userSet

 对于一般的用户属性，您可以调用 `userSet` 来进行设置。使用该接口上传的属性将会覆盖原有的属性值，如果之前不存在该用户属性，则会新建该用户属性，类型与传入属性的类型一致，此处以设置用户名为例：

```
// username为TA
ta.userSet({ username: "TA" });
//username为TE
ta.userSet({ username: "TE" });
```

#### 3.2 userSetOnce

 如果您要上传的用户属性只要设置一次，则可以调用 `userSetOnce` 来进行设置，当该属性之前已经有值的时候，将会忽略这条信息，以设置首次付费时间来为例：

```
//first_payment_time为2018-01-01 01:23:45.678
ta.userSetOnce({first_payment_time: "2018-01-01 01:23:45.678" });
//first_payment_time仍然为2018-01-01 01:23:45.678
ta.userSetOnce({first_payment_time: "2018-12-31 01:23:45.678" });
```

#### 3.3 userAdd

 当您要上传数值型的属性时，您可以调用 `userAdd` 来对该属性进行累加操作，如果该属性还未被设置，则会赋值 0 后再进行计算。如果传入负值，等同于减法操作。

```
//此时total_revenue为30
ta.userAdd({ total_revenue: 30 });
//此时total_revenue为678
ta.userAdd({ total_revenue: 648 });
```

#### 3.4 userUnset

当您要清空用户的用户属性值时，您可以调用 `userUnset` 来对指定属性进行清空操作，如果该属性还未在集群中被创建，则 `userUnset` **不会**创建该属性

```
// 清空该用户属性名为 userPropertykey 的用户属性值，即设置成 NULL
ta.userUnset("userPropertykey");
```

#### 3.5 userDelete

如果您要删除某个用户，可以调用 `userDelete` 将这名用户删除，您将无法再查询该名用户的用户属性，但该用户产生的事件仍然可以被查询到。

```
ta.userDelete();
```

#### 3.6 userAppend

您可以调用 `userAppend` 对数组类型的用户数据追加元素。

```
ta.userAppend({ user_list: ["apple", "ball"] });
```

#### 3.7 userUniqAppend

自 v1.6.0 开始，您可以调用 `userUniqAppend` 对 Array (List) 类型的用户数据追加唯一元素。调用 `userUniqAppend` 接口会对追加的用户属性进行去重， `userAppend` 接口不做去重，用户属性可存在重复。

```
//此时user_list的属性值为["apple"，"ball"]
ta.userAppend({ user_list: ["apple", "ball"] });
//此时user_list的属性值为["apple","apple","ball","cube"]
ta.userAppend({ user_list: ["apple", "cube"] });
//此时user_list的属性值为["apple"，"ball","cube"]
ta.userUniqAppend({ user_list: ["apple", "cube"] });
```

### 四、支持数据传输加密

从v1.6.0开始，数据上报方式为ajax的支持数据传输加密。可以在SDK初始化config中配置加密相关信息。

```
var config = {
    appId: "xxx",
    serverUrl: "xxx",
     secretKey: {
       //加密公钥 可以在TE管理后台获取
       publicKey: '公钥',
       //公钥版本号
       version: 1
     },
};
```

<!-- unsupported block: 34 -->

支持数据加密，需要额外引入crypto-js和jsencrypt

```
<script src="https://cdn.bootcdn.net/ajax/libs/crypto-js/4.1.1/crypto-js.js"></script>
<script src="https://cdn.bootcss.com/jsencrypt/3.2.1/jsencrypt.js"></script>
```

### 五、多域名打通

SDK 版本需 1.6.1 及以上支持多域名打通，可以将两个不同域名的网站上的用户行为统一，它可以让您更有效地观察相关网站用户的转化历程。

```
ta.quick('siteLinker', {
    linker: [
        { part_url: 'thinkingdata.cn', after_hash: true }，
        { part_url: 'example.com', after_hash: true }
    ]
})
```

part_url :配置的 part_url 字符串必须为打通网址的 URL 的子字符串。

希望打通的网域

配置

a 标签 href 地址

a 标签打通结果

thinkingdata.cn

{ part_url: 'thinkingdata.cn', after_hash: false }

https://thinkingdata.cn/

https://thinkingdata.cn/?_tasdk='d'+distinctID

after_hash: 必填属性，且属性值必须为布尔类型，即 true 或 false,配置 _tasdk 参数在 URL 的 hash 部分（即 # 后部分）还是在 URL 的 search 部分（即 # 前的 ？部分）

url

after_hash

结果

https://thinkingdata.cn

false

https://thinkingdata.cn?_tasdk=distinctID

true

https://thinkingdata.cn#?_tasdk=distinctID

https://thinkingdata.cn#index

false

https://thinkingdata.cn?_tasdk=distinctID#index

true

https://thinkingdata.cn#index?_tasdk=distinctID

https://thinkingdata.cn?a=1#index

false

https://thinkingdata.cn?a=1&_tasdk=distinctID#index

true

https://thinkingdata.cn?a=1#index?_tasdk=distinctID

https://thinkingdata.cn?a=1#index?b=2

false

https://thinkingdata.cn?a=1&_tasdk=distinctID#index?b=2

true

https://thinkingdata.cn?a=1#index?b=2&_tasdk=distinctID

### 六、其他功能

#### 6.1 获取设备 ID

您可以通过调用 `getDeviceId` 来获取设备 ID：

```
var deviceId = ta.getDeviceId();
```

#### 6.2 设置默认时区

默认情况下,SDK 默认会使用接口调用时的本机时间作为事件发生时间上报。您也可以通过初始化时设置默认时区，这样所有的事件都将按照您设置的时区来对齐事件时间：

```
var config = {
    appId: "xxx",
    serverUrl: "xxx",
    zoneOffset:8
};
```

<!-- unsupported block: 34 -->

注意：用指定时区对齐事件时间，会丢掉设备本机时区信息。如果需要保留设备本机时区信息，目前需要您自己为事件添加相关属性。
