---
code: h5_app_integrate
name: "H5 与 APP SDK 打通"
wikiToken: AQADwTQ9jisoGSkiyZycSLAInlt
parentWikiToken: FTcTwinIOi3OiRkK4MPc2Ex7neg
updateTime: 1745309847000
sourceUrl: https://docs-v2.thinkingdata.cn/?version=v5.0&lan=zh-CN&code=h5_app_integrate
---
# H5 与 APP SDK 打通

### 一、方案介绍

在 APP 当中，可能会有一些页面是由 H5 页面所构成的，此时 APP SDK 无法对 H5 页面进行数据采集，需要搭配使用 JavaScript SDK 对用户在 H5 页面的行为进行采集，为了保证 JavaScript SDK 与 APP SDK 的数据保持一致，在新版本 SDK 中加入了数据打通功能：

H5 页面使用 JavaScript SDK 进行数据采集，采集到数据后不直接发送，而是通过 APP SDK（即 Android SDK 、 iOS SDK、 Flutter SDK、 ReactNative SDK）发送到服务器。APP SDK 会对 JavaScript SDK 采集的数据进行调整，规则如下：

1. 保留 JavaScript SDK 传入的 `#time`，即事件的时间以触发埋点的时间为准
1. 使用 APP SDK 的`#account_id` 与 `#distinct_id`，以 APP SDK 维护的用户为准
1. 加入 APP SDK 的预置属性，如果与 JavaScript 的预置属性冲突，则 APP SDK 的预置属性将覆盖冲突值，比如`#lib`字段，APP SDK 的值会覆盖 JavaScript SDK 的值
1. APP SDK 的公共属性：如果与 JavaScript 传入的属性冲突，则丢弃原生公共属性值；如果 JavaScript SDK 没有该属性，则加入到上报数据中
1. APP SDK 中的`timeEvent` 接口可以对 JavaScript SDK 采集的事件生效
1. JavaScript SDK 中的 login、logout、identify 接口无法修改 APP SDK 中的用户 ID，在 H5 与 APP SDK 打通的情况下，在 JavaScript SDK 中通过上述接口无法对数据的用户 ID 进行修改
1. 当开启 H5 与 APP SDK 打通的开关后，如果运行环境中并不存在 APP SDK，则 JavaScript SDK 将会直接上报数据，等同于未开启打通的状态。
### 二、使用方法

如需开启 H5 与 APP SDK 打通功能，需要在 JavaScript SDK 与 APP SDK 进行如下配置，**请注意 SDK 的适用版本**，请使用历史版本的用户升级至最新版本。

#### 2.1 Android SDK 使用方法

**Android SDK 需要使用 1.2.0 及之后的版本**

在初始化 `WebView` 时调用`setJsBridge`：

```
TDAnalytics.setJsBridge(WebView webView);
```

如果需要支持腾讯的`X5Webview`，需要 Android SDK 需要使用 2.0.1 及之后的版本，调用`setJsBridgeForX5WebView`：

```
TDAnalytics.setJsBridgeForX5WebView(webView);
```

#### 2.2 iOS SDK 使用方法

**iOS SDK 需要使用 1.1.1 及之后的版本**

##### WKWebView

在 iOS 17 之后的系统，废弃了使用 NSUserDefaults 设置全局 UserAgent 的方式。需要你手动给 WKWebView 对象添加上数数 SDK 特有的 UserAgent。否则不能实现 H5 与原生应用的打通。

添加方式如下

```
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.applicationNameForUserAgent = [NSString stringWithFormat:@"%@ %@", config.applicationNameForUserAgent ?: @"", @"/td-sdk-ios"]; 
WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
```

在 WKWebView 的代理方法： decidePolicyForNavigationAction 中添加下列代码

```
- (**void**)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(**void** (^)(WKNavigationActionPolicy))decisionHandler {
    **if** ([TDAnalytics showUpWebView:webView withRequest:navigationAction.request]) {
        decisionHandler(WKNavigationActionPolicyCancel);
        **return**;
    }
    
    decisionHandler(WKNavigationActionPolicyAllow);
}
```

##### UIWebView

1.在初始化完 SDK 之后，调用`addWebViewUserAgent`：

```
[TDAnalytics addWebViewUserAgent];
```

2.在初始化 `WebView` 时，根据`WebView`的类型做如下调用：

```
- (**BOOL**)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    **if** ([TDAnalytics showUpWebView:webView withRequest:request]) {
        **return** **NO**;
    }
    /*
        other code
    */
    **return** **YES**;
}
```

#### 2.3 Flutter SDK 使用方法

**Flutter SDK 需要使用 3.1.0-beta.1 及之后的版本**

在初始化 `WebView` 时调用`addJavaScriptChannel`，在`onMessageReceived`方法会调用中调用`TDAnalytics.h5ClickHandler();`

```
controller = WebViewController();
controller.addJavaScriptChannel("ThinkingData_APP_Flutter_Bridge", onMessageReceived: (JavaScriptMessage message){
    TDAnalytics.h5ClickHandler(message.message);
});
```

#### 2.4 ReactNative SDK 使用方法

**ReactNative SDK 需要使用 3.1.0-beta.1 及之后的版本**

在初始化 `WebView` 时调用`injectedJavaScript`方法注入js，在`onMessage`方法会调用中调用`TDAnalytics.h5ClickHandler();`

```
<WebView
  ref={webViewRef}
  source={localHtmlFile}
  onMessage={ event => {
    console.log(event.nativeEvent.data);
    TDAnalytics.h5ClickHandler(event.nativeEvent.data);
  }}
  javaScriptEnabled={true}
  injectedJavaScript='window.ThinkingData_APP_ReactNative_Bridge = function(data) { window.ReactNativeWebView.postMessage(data); };'
/>
```

#### 2.5 JavaScript SDK 使用方法

**JavaScript SDK 需要使用 ****2****.0.****4**** 及之后的版本**

- 在初始化参数配置中加入 `useAppTrack: true`，示例如下：
```
(function(param) {
  var p = param.sdkUrl,
    n = param.name,
    w = window,
    d = document,
    s = "script",
    x = null,
    y = null;
  w["ThinkingDataAnalyticalTool"] = n;
  w[n] =
    w[n] ||
    function(a) {
      return function() {
        (w[n]._q = w[n]._q || []).push([a, arguments]);
      };
    };
  var methods = [
    "track",
    "quick",
    "login",
    "logout",
    "trackLink",
    "userSet",
    "userSetOnce",
    "userAdd",
    "userDel",
    "setPageProperty"
  ];
  for (var i = 0; i < methods.length; i++) {
    w[n][methods[i]] = w[n].call(null, methods[i]);
  }
  if (!w[n]._t) {
    (x = d.createElement(s)), (y = d.getElementsByTagName(s)[0]);
    x.async = 1;
    x.src = p;
    y.parentNode.insertBefore(x, y);
    w[n].param = param;
  }
})({
  appId: "APP_ID", //系统分配的APPID
  name: "ta", //全局的调用变量名，可以任意设置，后续的调用使用该名称即可
  sdkUrl: "http://www.a.com/thinkingdata.js", //统计脚本URL
  serverUrl: "https://global-receiver-ta.thinkingdata.cn:9080", //数据上传的URL
  send_method: "image", //数据上传方式
  useAppTrack: true // 打通 APP 与 H5
});
```
