更新记录

1.0.0(2026-11-04)

首次发布:接入巨量引擎 Android转化(AppConvert 2.0.6)和iOS 转化 SDK(BDASignalSDK 2.0.0),上报启动事件、提取深链 clickid、AndroidId


平台兼容性

uni-app(5.34)

Vue2 Vue2插件版本 Vue3 Vue3插件版本 Chrome Safari app-vue app-vue插件版本 app-nvue app-nvue插件版本 Android Android插件版本 iOS iOS插件版本 鸿蒙
√ 1.0.0 √ 1.0.0 - - √ 1.0.0 √ 1.0.0 5.0 1.0.0 15 1.0.0 -
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(5.34)

Chrome Safari Android Android插件版本 iOS iOS插件版本 鸿蒙 微信小程序
- - 5.0 1.0.0 15 1.0.0 - -

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
√ √ √ ×

dh-oceanengine 巨量引擎转化 SDK(融合归因)

巨量引擎(抖音、头条等字节系广告平台)转化 SDK 的 UTS 封装,用于接入巨量「融合归因」方案。

App 启动时由 SDK 把启动事件和设备特征直接上报给巨量,巨量据此完成广告归因;服务端再用 IDFV(iOS)/ android_id(Android)向巨量查询归因结果,并回传激活、注册、付费等转化。用户未授权 IDFA、拿不到 OAID 时也能归因,可明显提升 iOS 的归因率。

平台 原生 SDK 最低系统 引入方式
iOS BDASignalSDK 2.0.0 iOS 15 CocoaPods(插件已配置)
Android com.bytedance.ads:AppConvert 2.0.6 Android 5.0(API 21) maven(插件已配置)
其他平台 - - 调用返回 unsupported

需使用自定义调试基座或云打包,标准基座不包含原生 SDK。


API

import { initOceanSignal, handleOceanOpenURL, getOceanClickId, getAndroidId } from '@/uni_modules/dh-oceanengine';
方法 iOS Android 说明
initOceanSignal(options) ✓ ✓ 初始化 SDK 并上报启动事件
handleOceanOpenURL(url) ✓ 无操作 App 运行中被深链唤起时提取 clickid
getOceanClickId() ✓ 返回 '' 获取深链注入的 clickid
getAndroidId() 返回 '' ✓ 获取 android_id,供上报服务端

initOceanSignal(options)

初始化 SDK 并上报启动事件 launch_app。每次冷启动调用一次,同一进程内重复调用会被忽略并返回 inited。

必须在用户同意隐私政策之后调用,SDK 初始化即开始采集设备信息。

参数 options

字段 类型 必填 默认值 平台 说明
mainlandOnly boolean 否 false iOS / Android 仅当系统设置中的地区为中国大陆时初始化。巨量转化 SDK 面向中国境内用户,海外用户不需要归因时设为 true
openUrl string 否 '' iOS 冷启动时唤起 App 的链接,用于提取 clickid,一般传 plus.runtime.arguments
enableIdfa boolean 否 true iOS 是否允许 SDK 采集 IDFA。即使为 true,也只有用户在 ATT 弹窗中允许跟踪后才能取到
enableLog boolean 否 false Android 是否开启 SDK 自身的调试日志

返回值 OceanSignalStatus

值 说明
'inited' 已初始化(或之前已初始化过)
'skipped' 开启了 mainlandOnly,且系统地区不是中国大陆,未初始化
'unsupported' 非 App 平台
const status = initOceanSignal({
  mainlandOnly: true,
  openUrl: plus.runtime.arguments || '',
});
console.log(status); // 'inited'

handleOceanOpenURL(url)

iOS:App 已在运行,又被 URL Scheme 唤起(热启动)时调用,把链接里的 clickid 交给 SDK。冷启动的链接请通过 initOceanSignal 的 openUrl 传入。

  • 未初始化(包括被 mainlandOnly 跳过)时忽略
  • 链接里不含 clickid 时忽略

Android:无操作,深链 clickid 由 SDK 自行处理。

// App.vue
onShow() {
  handleOceanOpenURL(plus.runtime.arguments || '');
}

getOceanClickId()

iOS:返回 SDK 当前记录的 clickid,没有或未初始化时返回 ''。SDK 会把 clickid 缓存在本地,下次启动仍可取到。一般只用于调试。

Android:返回 ''。

getAndroidId()

Android:返回设备的 android_id,取不到时返回 ''。SDK 内部使用的是同一个值,保证和你上报给服务端的一致。

服务端查询巨量实时归因、回传转化时都要用到 android_id,请随激活请求一起上报(例如放在请求头里)。

iOS:返回 ''。iOS 的查询 key 是 IDFV,可通过 UIDevice.current.identifierForVendor 获取(需自行实现或使用其他插件)。


场景流程

以「用户在抖音刷到广告 → 下载 App → 注册付费」为例:

 用户                 App(本插件)               你的服务端                巨量引擎
  │                       │                          │                        │
  │ ① 点击抖音广告 ─────────────────────────────────────────────────────────▶ │ 记录点击
  │                       │                          │ ◀── 点击监测(可选)──── │
  │ ② 下载并打开 App ────▶ │                          │                        │
  │                       │ ③ 用户同意隐私政策         │                        │
  │                       │   iOS:请求 ATT 授权       │                        │
  │                       │                          │                        │
  │                       │ ④ initOceanSignal()      │                        │
  │                       │ ── SDK 上报 launch_app + 设备特征 ──────────────▶ │ 匹配点击,完成归因
  │                       │                          │                        │
  │                       │ ⑤ 上报激活               │                        │
  │                       │ ── idfv / android_id ──▶ │                        │
  │                       │                          │ ⑥ 查询实时归因 ───────▶ │
  │                       │                          │ ◀── callback 等结果 ─── │
  │                       │                          │                        │
  │                       │                          │ ⑦ 回传激活 ───────────▶ │
  │ ⑧ 注册、付费 ────────▶ │ ───────────────────────▶ │ ⑨ 回传注册、付费 ─────▶ │
步骤 谁来做 说明
① 巨量 用户点击广告,巨量记录点击。若配置了监测链接,会同时把点击推给你的服务端
② ③ App 用户同意隐私政策;iOS 需要 IDFA 时先请求 ATT 授权,有结果后再进行下一步
④ 本插件 initOceanSignal() 初始化 SDK,SDK 直接把启动事件和设备特征上报给巨量。这一步只用于巨量匹配,不等于激活回传
⑤ App 调用你自己的激活接口,带上 IDFV(iOS)或 getAndroidId()(Android)。无论是否拿到 IDFA / OAID 都要上报
⑥ 服务端 用 idfv / android_id + 包名请求巨量实时归因接口,拿到 callback_param、last_touch_time 等
⑦ 服务端 用 callback 回传激活,并带上 idfv / android_id
⑧ ⑨ 服务端 注册、付费等后续转化,同样由服务端用同一个 callback 回传,并带上 idfv / android_id

深链(clickid):用户在抖音点击广告直接拉起已安装的 App 时,链接形如 com.example.app://oceanengine/ads?clickid=xxx。冷启动通过 initOceanSignal({ openUrl })、热启动通过 handleOceanOpenURL(url) 交给 SDK,归因可直接命中。


完整示例

App.vue:

// #ifdef APP-PLUS
import { initOceanSignal, handleOceanOpenURL, getAndroidId } from '@/uni_modules/dh-oceanengine';
// #endif

export default {
  data() {
    return { oceanInited: false };
  },
  onLaunch() {
    // #ifdef APP-PLUS
    if (plus.os.name === 'Android') {
      this.initOcean();
    } else {
      // iOS:先请求 ATT 授权(需自行实现),有结果后再初始化,启动事件才能带上 IDFA
      requestATT().then(() => this.initOcean());
    }
    // #endif
  },
  onShow() {
    // #ifdef APP-PLUS
    if (this.oceanInited) {
      handleOceanOpenURL(plus.runtime.arguments || '');
    }
    // #endif
  },
  methods: {
    initOcean() {
      const status = initOceanSignal({
        mainlandOnly: true,
        openUrl: plus.runtime.arguments || '',
      });
      this.oceanInited = status === 'inited';

      // 上报激活给你的服务端,服务端据此查询巨量实时归因
      reportActivate({
        androidId: plus.os.name === 'Android' ? getAndroidId() : '',
        // idfv: iOS 自行获取
      });
    },
  },
};

requestATT、reportActivate 为示意,请替换为项目里的实现。


配置说明

iOS

  1. URL Scheme:manifest.json → app-plus → distribute → ios → urltypes 中加入以应用包名为值的 scheme,多个用英文逗号分隔:

    "urltypes": "myapp,com.example.app"

    巨量深链格式为 包名://oceanengine/ads?clickid=__CLICKID__。配置后可在备忘录里输入该链接、点击验证能否拉起 App。

  2. IDFA(enableIdfa 为 true 时):manifest.json → app-plus → distribute → ios:

    "privacyDescription": {
     "NSUserTrackingUsageDescription": "用于统计应用的安装来源"
    },
    "idfa": true

    并在调用 initOceanSignal 之前自行请求 ATT 授权。

  3. 最低系统版本:SDK 要求 iOS 15,使用本插件后 App 最低支持版本会提高到 iOS 15。

Android

  1. 依赖和 maven 仓库已在插件的 utssdk/app-android/config.json 中配置,无需额外操作。
  2. 若使用 uni-app 原生隐私弹窗(androidPrivacy.json),请在用户同意后再调用 initOceanSignal,可用 plus.runtime.isAgreePrivacy() 判断。
  3. 巨量要求安卓包先在后台「应用管理 → SDK 检测」中通过数据检测,才能进行联调和投放。

服务端对接

项目 iOS Android
实时归因接口 POST https://analytics.oceanengine.com/sdk/app/attribution 同左
请求参数 platform: "ios"、idfv、package_name platform: "android"、android_id、package_name
转化回传必带 idfv android_id

要点:

  • 每一次激活(新增和回流用户)都要查询实时归因,不能只在自己的归因失败时兜底
  • 返回 202(归因中)、204(未找到 SDK 启动事件)时需要重试,建议 3 次、间隔 300ms
  • 接口返回的 last_touch_time 要和监测链接匹配到的点击时间放在同一优先级比较,转化归给时间更晚的一方

完整字段和错误码以巨量营销后台提供的《巨量营销融合归因优化方案接入手册》为准。


合规

  • 必须在用户同意隐私政策之后调用 initOceanSignal
  • 隐私政策需披露巨量引擎转化 SDK,披露内容以接入手册中「巨量引擎转化 SDK 隐私政策」的最新版本为准
  • SDK 采集的数据:IDFA(需用户授权,可通过 enableIdfa 关闭)、IDFV、OAID、android_id、设备特征、公网 IP、UA、运营商信息
  • iOS 上架时需在 App Store Connect「App 隐私」中声明收集「设备 ID」,用途为第三方广告 / 跟踪
  • 巨量转化 SDK 面向中国境内用户,同一安装包在海外上架时建议开启 mainlandOnly

本插件只做调用封装,不收集、不上传任何数据。


常见问题

initOceanSignal 返回 skipped

开启了 mainlandOnly,且设备「设置 → 通用 → 语言与地区」中的地区不是中国大陆。

服务端查询实时归因一直返回 204

巨量没有收到该设备的 SDK 启动事件。检查:是否调用了 initOceanSignal 且返回 inited;Android 控制台是否有 [dh-oceanengine] event send success launch_app;该设备是否被 mainlandOnly 跳过。

Android 初始化失败

控制台会打印 [dh-oceanengine] init failure <reason>,reason 含义:

reason 说明
-1 未知错误,看后面的异常信息
1 重复初始化
4 构造参数错误
5 网络请求错误
6 获取 android_id 出错

iOS 云打包报 Undefined symbols ... BDASignalSwiftRequestManager

pod 自带的静态库 BDASignalRequestLib.xcframework 不会被 UTS 工程自动链接,插件已从 官方仓库 tag 2.0.0 拷贝一份到 utssdk/app-ios/Frameworks/。如果自行升级 pod 版本,请同步替换这个 xcframework。

测试深链时,取到的 clickid 是上一次的值

iOS SDK 会把 clickid 缓存在本地。测试时每次换一个不同的 clickid,便于区分。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

由巨量引擎转化 SDK 采集 IDFA(需用户授权,可关闭)、IDFV、OAID、android_id、设备特征、公网 IP、UA、运营商信息并上报巨量引擎,用于广告归因;可配置仅中国大陆用户采集。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无