更新记录

1.2.0(2026-09-10) 下载此版本

新增 $Exception 采集

Changelog

Sensors Wave UniApp X 数据采集 SDK 的所有显著变更均记录于此文件。 格式参考 Keep a Changelog, 版本号遵循 Semantic Versioning

[1.2.0] - 2026-09-10

新增

  • 新增 $Exception 采集

[1.1.0] - 2026-08-14

新增

  • 新增安全合规,支持禁用数据采集,用户允许之后才采集。
  • $AppInstall 新增 $install_time,记录 App 安装时间。

[1.0.0] - 2026-07-27

新增

  • Sensors Wave 数据采集 SDK 正式发布

1.1.0(2026-08-14) 下载此版本

  • 新增安全合规,支持禁用数据采集,用户允许之后才采集。
  • $AppInstall 新增 $install_time,记录 App 安装时间。

1.0.0(2026-07-27) 下载此版本

Sensors Wave 数据采集 SDK 正式发布

Changelog

Sensors Wave UniApp X 数据采集 SDK 的所有显著变更均记录于此文件。 格式参考 Keep a Changelog, 版本号遵循 Semantic Versioning

[1.0.0] - 2026-07-27

新增

  • Sensors Wave 数据采集 SDK 正式发布
查看更多

平台兼容性

uni-app x(4.0)

Chrome Safari Android iOS 鸿蒙 微信小程序

其他

多语言 暗黑模式 宽屏模式

Sensorswave UniApp X 数据采集 SDK

Sensors Wave UniApp X 数据采集 SDK 是一个跨平台的数据埋点采集库,一套代码即可在多个平台自动采集用户行为数据。 以 uni-app-x 的 uni_modules 插件形态发布,业务工程通过 app.use(Sensorswave.plugin, config) 一行接入,应用级预置事件自动采集。 如果你是第一次接触 Sensors Wave,欢迎访问 sensorswave.com 了解产品并创建账号。

源码位于 uni_modules/sensorswave-uniappx/

特性

  • 🌐 跨平台支持:微信 / 支付宝 / 抖音 / 百度小程序、App(iOS / Android / 鸿蒙)、H5
  • 🔎 平台运行时探测:通过 uni.getSystemInfoSync() 自动识别宿主平台,无需手填 platformType / platformName
  • 🚀 应用级预置事件自动采集app.use() 后无需在 App.uvue 手动调用应用级生命周期方法
  • 📄 页面级预置事件:由 install() 注入的全局 mixin 统一驱动(H5 配合 vue-router.afterEach),业务页面零侵入
  • 👤 用户体系:匿名 / 登录用户标识、用户属性(profile)增删改、公共属性注册
  • 🧪 A/B 测试:功能开关(Feature Gate)、远程配置(Feature Config)、实验分组(Experiment)
  • 📡 UTM 追踪:自动解析启动参数中的 UTM 渠道参数并写入首值归因
  • 🔒 敏感字段脱敏:自定义事件属性中的敏感信息(token / password / cookie …)自动掩码
  • 💾 离线持久化:事件队列持久化存储、批量上报、失败重试,保障数据不丢
  • ♻️ 挂起离开恢复:进程被杀后下次启动自动补发未结束会话的离开事件
  • 💥 异常采集($Exception):error 级自动捕获(小程序 / H5 / 鸿蒙)+ fatal 级崩溃采集(App 端原生钩子,崩溃前落盘、下次启动补发),支持 trackException 手动上报

平台支持

平台 自动采集事件
微信小程序 $MPLaunch $MPShow $MPHide $MPPageView $MPPageLeave $MPShare
支付宝小程序 同微信小程序
抖音小程序 同微信小程序
百度小程序 同微信小程序
App iOS / Android / 鸿蒙 $AppStart $AppEnd $AppPageView $AppPageLeave $AppInstall
H5 $PageView $PageLeave $PageLoad $WebClick
  • 平台在运行时通过 uni.getSystemInfoSync() 自动识别,无需手动指定。
  • 所有平台上报事件的 $lib 预置属性统一为 uniappx,用于在数据端标识本采集 SDK。
  • $WebClick 需开启 enableClickTrack: true$MPShare 需开启 enableShareTrack(默认开启)。

安装

SDK 已发布到 DCloud 插件市场,推荐通过 HBuilderX 一键导入:

  1. 打开插件市场页面:Sensors Wave uni-app x 数据采集 SDK
  2. 点击页面上的 使用 HBuilderX 导入插件 按钮
  3. 在 HBuilderX 弹窗中选择目标 UniApp X 工程,确认导入
  4. 等待下载完成,插件会自动安装到工程的 uni_modules/ 目录下

导入完成后,工程结构如下:

your-app/
└── uni_modules/
    ├── sensorswave-uniappx/                       ← 由插件市场自动导入
    │   ├── package.json
    │   └── utssdk/
    └── sw-ios-crash-trigger      ← 依赖插件,自动跟随导入
        ├── package.json
        └── utssdk/app-ios/

第二个插件 sw-ios-crash-trigger 是本 SDK 在 App-iOS 端 fatal 崩溃采集的 原生面(iOS 崩溃捕获必须在原生层进行,而编译器规则决定它只能以独立插件形态进基座),已在本 插件 package.jsonuni_modules.dependencies 中声明——HBuilderX 导入主插件时会提示 "安装插件三方依赖",确认后自动带入,业务代码无需也无法直接调用它

私有 zip 分发时请确保两个插件目录同时解压到工程的 uni_modules/ 下。

无需 npm 安装;uni-app-x 会自动识别 uni_modules 插件。后续插件更新也可在 HBuilderX 中通过插件市场一键升级。

如果你需要本地调试或二次开发,也可以将本仓库的 uni_modules/sensorswave-uniappx/uni_modules/sw-ios-crash-trigger/ 两个目录拷贝(或软链)到工程的 uni_modules/ 下,效果一致。

快速开始

推荐通过 Vue 插件 接入,插件会在 app.use() 时自动完成初始化,并注入页面生命周期 mixin,实现无侵入的页面浏览 / 离开采集。

1. 在 main.uts 安装插件

import App from './App.uvue'
import { createSSRApp } from 'vue'
import Sensorswave from '@/uni_modules/sensorswave-uniappx/utssdk/index'

export function createApp() {
  const app = createSSRApp(App)
  app.use(Sensorswave.plugin, {
    sourceToken: 'your_source_token', // 必填:数据源 Token
    apiHost: 'https://example.com',   // 必填:数据上报地址
    autoCapture: true,                // 自动采集生命周期(默认 true)
    enableClickTrack: true,           // 自动采集点击(默认 false)
    enableAB: true,                   // 启用 A/B 测试(默认 false)
    debug: false,                      // 调试日志(默认 false)
  })
  return { app }
}

2. App.uvue 无需手动调用应用级预置事件

应用级事件(启动 / 前后台切换 / 小程序分享)由 SDK 在 install() 内自动监听与触发, App.uvue 只需放置与业务身份相关的逻辑:

<script setup lang="uts">
import Sensorswave from '@/uni_modules/sensorswave-uniappx/utssdk/index'

onLaunch((options : any) => {
  // 仅在已登录场景下设置 loginId(可选)
  Sensorswave.setLoginId('user_123')
})
</script>

不需要调用 Sensorswave.onAppLaunch / onAppShow / onAppHide / onShare —— 它们会被自动触发。 页面级生命周期方法(onPageShow / onPageHide / onPageUnload)也不再对外暴露。

3. 页面级事件接入

通过 Vue 插件接入(推荐)后,页面级事件($PageView / $*PageLeave / $PageLoad)由 install() 注入的全局 mixin 统一驱动,业务页面零侵入

  • H5:全局 mixin + vue-router.afterEach 共同生效
  • 小程序 / App:全局 mixin 合并到 App 根组件、页面及所有自定义组件,SDK 内部通过 $scope.route / $page.route / $options.mpType === 'page' 过滤出真正的页面实例,避免 App 根组件 / 子组件的 onShow 误触发 $MPPageView / $AppPageView

备选方案:如果你直接调用 Sensorswave.init(sourceToken, config)(不走 app.use()),没有 app 实例注册全局 mixin,需要在每个页面手动集成:

<script setup>(推荐)

<script setup lang="uts">
import { useSensorswavePageLifecycle } from '@/uni_modules/sensorswave-uniappx/utssdk/index'

useSensorswavePageLifecycle()
</script>

Options API

import { SensorswavePageMixin } from '@/uni_modules/sensorswave-uniappx'
export default {
  mixins: [SensorswavePageMixin],
}

4. 在组件中调用

插件安装后,SDK 实例会挂载到 Vue 全局属性 $sensorswave

  • Options API:可通过 this.$sensorswave 访问。
  • <script setup>:没有 this,直接 import Sensorswave 调用单例即可(推荐)。

无论哪种写法,拿到的是同一个 SDK 单例,调用方式完全一致。

import Sensorswave from '@/uni_modules/sensorswave-uniappx/utssdk/index'

// 自定义事件(推荐:使用 trackEvent)
Sensorswave.trackEvent('button_click', { button_name: 'submit', amount: 99 })

⚠️ 导入方式约定:统一使用深路径导入 import Sensorswave from '@/uni_modules/sensorswave-uniappx/utssdk/index',且同一应用内所有文件保持一致(混用不同导入路径会产生两份 SDK 单例,事件分裂)。

⚠️ sourceTokenapiHost 为必填项,缺失会导致数据无法上报(SDK 会在控制台输出告警)。

配置项

配置 类型 默认值 说明
sourceToken string '' 必填。数据上报凭证,由服务端分配
apiHost string '' 必填。数据上报 API 地址
debug boolean false 是否开启调试模式,输出详细日志
autoCapture boolean true 是否自动采集生命周期事件(启动、前后台、页面浏览等)
batchSend boolean false 是否启用批量发送(关闭则即时发送)
maxBatchSize number 10 批量发送时每批最大事件数
flushInterval number 5000 批量发送轮询间隔(毫秒)
enableClickTrack boolean false 是否自动采集元素点击($WebClick),仅 H5 支持
enableShareTrack boolean true 是否自动采集小程序分享(仅 MP)
enableAB boolean false 是否启用 A/B 测试功能
enableErrorTrack boolean false 是否自动采集 error 级异常($Exception$exception_level = error)。平台捕获面见异常采集
enableCrashTrack boolean false 是否采集 fatal 级崩溃($Exception$exception_level = fatal,仅 App)。iOS 端需自定义基座,见自定义基座与真机调试说明
abRefreshInterval number 600000 A/B 测试缓存刷新间隔(毫秒,默认 10 分钟,最小 30 秒)
optOutCapturing boolean false 合规:初始化即禁用采集(不发、不读、不写任何埋点数据),满足 GDPR / 隐私法规的「默认不采集」诉求
persistOptOut boolean false 合规:是否将 opt-out 状态持久化到本地存储,使其跨会话保留(进程重启 / destroy 后重新初始化仍恢复用户的授权决策)

💡 optOutCapturing / persistOptOut 的运行时行为见 合规(禁用采集) 小节。

API 方法

事件追踪

trackEvent(eventName, properties?)

手动上报一个自定义事件。时间戳默认取当前时刻。

  • eventName(string,必填):事件名称
  • properties(object,可选):事件属性
Sensorswave.trackEvent('OrderSubmit', {
  order_id: 'ORDER_001',
  amount: 99.9,
  currency: 'CNY',
})

track - 高级事件追踪

发送完整的事件对象,支持更精细的控制。此方法允许您手动指定所有事件字段。

参数

  • event (必填):完整事件对象,包含以下字段:
    • event (string,必填):事件名称
    • properties (Record<string, any>,可选):事件属性
    • time (number,可选):时间戳(毫秒),缺省时 SDK 取当前时刻
    • anon_id (string,可选):匿名用户 ID,缺省时从 store 读取
    • login_id (string,可选):登录用户 ID。login_idanon_id 至少传一个;都传时优先 login_id;都缺省时从 store 兜底
    • trace_id (string,可选):请求追踪 ID,缺省时 SDK 自动生成 UUID
    • user_properties (Record<string, any>,可选):用户属性,透传

示例

Sensorswave.track({
  event: 'purchaseCompleted',
  properties: {
    product_id: '12345',
    amount: 99.99,
    currency: 'USD'
  },
  time: Date.now(),
  trace_id: 'unique-trace-id-12345',
  anon_id: 'anonymous-user-id',
  login_id: 'user_12345',
  user_properties: {
    // $set: 代表插入或者更新一条用户属性信息
    $set: {
      plan: 'premium',
      signup_date: '2024-01-01'
    }
  }
});

// 也可只传 event 名称,其余字段由 SDK 兜底
Sensorswave.track({ event: 'OrderPaid' });

💡 普通业务事件请优先使用 trackEvent,仅在需要精确控制 time / trace_id / user_properties 等字段时使用 track

用户标识

identify(loginId)

设置登录 ID,并发送 $Identify 事件,将匿名行为与登录用户关联。

Sensorswave.identify('user_12345')

setLoginId(loginId)

设置登录 ID,发送 $Identify 事件。仅需要标识用户、不需要追踪关联事件时使用。

Sensorswave.setLoginId('user_12345')

getLoginId()

获取当前登录用户 ID,未登录或未初始化时返回空字符串。返回 string

const loginId = Sensorswave.getLoginId()

getAnonId()

获取当前匿名用户 ID,该 ID 在设备首次使用时自动生成并持久化。返回 string

const anonId = Sensorswave.getAnonId()

reset(resetAnonId?)

用户登出时调用,解除登录 ID 与设备的绑定。默认保留匿名 ID,登出后事件改以原匿名 ID 继续标识。 同时会失效 A/B 测试身份缓存,后续实验按新身份重新分组。不发送任何服务端事件。

  • resetAnonId(boolean,可选):是否同时重置匿名 ID,默认 false
// 用户登出时
Sensorswave.reset()  // 默认保留匿名 ID

// 如果需要同时重置匿名 ID(如公共设备场景)
Sensorswave.reset(true)

用户属性(Profile)

profileSet(properties)

设置用户属性,已存在的属性会被覆盖。

Sensorswave.profileSet({
  name: 'alice',
  age: 30,
  plan: 'premium',
})

profileSetOnce(properties)

首次设置用户属性,已存在的属性不会被覆盖。常用于记录首次注册时间、首次来源等。

Sensorswave.profileSetOnce({
  signup_date: '2026-01-15',
  initial_referrer: 'google',
})

profileIncrement(properties)

对数值型用户属性进行递增操作,仅支持数值类型,支持正数和负数。

// 递增单个属性
Sensorswave.profileIncrement({ login_count: 1 })

// 递增多个属性
Sensorswave.profileIncrement({
  login_count: 1,
  points_earned: 100,
})

profileAppend(properties)

向数组类型的用户属性追加元素,不去重

Sensorswave.profileAppend({
  categories_viewed: ['electronics', 'mobile_phones'],
})

profileUnion(properties)

向数组类型的用户属性追加元素,自动去重

Sensorswave.profileUnion({
  interests: ['technology', 'gaming'],
})

profileUnset(keys)

删除指定的用户属性。

  • keys(string[],必填):要删除的属性名数组
// 删除单个属性
Sensorswave.profileUnset(['temporary_campaign'])

// 删除多个属性
Sensorswave.profileUnset(['old_plan', 'expired_flag'])

profileDelete()

删除当前用户的全部用户属性数据,操作不可恢复。仅对已登录用户有效。

Sensorswave.profileDelete()

公共属性

公共属性会自动附加到后续上报的所有事件上,适合注入全局上下文(如应用版本、环境等)。 值支持静态值(字符串 / 数值 / 布尔等),也支持动态函数——函数会在每次事件构建时调用取最新值, 例如 now: () => Date.now()$screen: () => getCurrentPage().route 等场景都能正确取到当前时刻 / 当前页。

registerCommonProperties(properties)

注册公共属性,已存在的同名属性会被覆盖。

// 静态公共属性
Sensorswave.registerCommonProperties({
  app_version: '1.0.0',
  environment: 'production',
  app_channel: 'wechat',
})

// 动态公共属性:每次事件上报时实时求值
Sensorswave.registerCommonProperties({
  $current_time: () => Date.now(),
  $active_page: () => getCurrentPages().pop()?.route ?? '',
})

clearCommonProperties(keys?)

清除已注册的公共属性。不传 keys 时清除全部。

// 清除指定公共属性
Sensorswave.clearCommonProperties(['app_version', 'app_channel'])

// 清除全部公共属性
Sensorswave.clearCommonProperties()

A/B 测试

需在初始化时设置 enableAB: true,否则以下方法将直接返回默认值。

checkFeatureGate(key)

检查功能开关(Feature Gate)是否对当前用户开启。返回 Promise<boolean>

const enabled = await Sensorswave.checkFeatureGate('new_checkout_flow')
if (enabled) {
  showNewCheckout()
}

getFeatureConfig(key)

获取远程配置(Feature Config)。服务端返回的 JSON 字符串会被自动解析。返回 Promise<Record<string, any>>,未启用 A/B 测试时返回空对象 {}

const config = await Sensorswave.getFeatureConfig('app_settings')
const { theme, layout } = config

getExperiment(key)

获取实验分组(Experiment)。返回 Promise<Record<string, any>>,未命中实验或未启用 A/B 测试时返回空对象。

const exp = await Sensorswave.getExperiment('homepage_layout')
const { layout_type } = exp

异常采集($Exception)

需在初始化时设置 enableErrorTrack: true(error 级)和 / 或 enableCrashTrack: true(fatal 级),两者均默认关闭、互不依赖。

error 级自动捕获(enableErrorTrack)

自动采集未捕获的 JS 异常与 Promise 拒绝,上报为 $Exception$exception_level = error)。各平台捕获面:

平台 捕获机制
小程序 uni.onError + uni.onUnhandledRejection(个别平台缺失时静默降级,如支付宝无 onError
H5 uni.onError(Vue 捕获面)+ window.error / unhandledrejection(逃逸 Vue 的异步错误)
App 鸿蒙 应用级 onError 钩子(鸿蒙运行时恒装 Vue errorHandler,组件回调内的同步 throw 进程不崩溃)
App Android / iOS 无 JS 级错误钩子(uni-app x 运行时会 catch 住组件回调里的异常仅打日志)——未捕获异常即进程崩溃,走下方 fatal 通道;已捕获的异常(业务 try-catch 拿到的)用 trackException 手动上报

fatal 级崩溃采集(enableCrashTrack,仅 App)

通过各平台原生机制捕获「未捕获异常导致进程终止」级崩溃:崩溃瞬间把最小 payload(类型 / message / 堆栈 / 结构化帧)同步落盘,进程死亡;下次启动 SDK 自动补发$Exception$exception_level = fatal,事件时间为崩溃时刻而非补发时刻)。

平台 崩溃捕获机制 覆盖范围
Android Thread.setDefaultUncaughtExceptionHandler JVM 任意线程未捕获异常
iOS NSSetUncaughtExceptionHandler(经配套原生插件,见自定义基座与真机调试说明 NSException 级未捕获异常;SIGSEGV 等信号级崩溃不覆盖
鸿蒙 双通道:errorManager(未捕获 JS 异常,进程不退出)+ hiAppEvent watcher(系统 faultlog,下次启动回放 C++ crash / 卡死等真崩溃) 两通道以 ±5s 崩溃时刻窗口判重,防同一崩溃双计

约束:待补发记录上限 10 条(超出淘汰最旧)、有效期 7 天;落盘前检查持久化 opt-out 标志(见合规)。

trackException(throwable, properties?)

手动上报一条 $Exception$exception_level = error),不受任何开关限制。适合业务 try-catch 拿到异常后主动上报——也是 Android / iOS 端 error 级采集的唯一通道。

try {
  riskyBusiness()
} catch (e) {
  Sensorswave.trackException(e, { source: 'manual_catch', page: 'OrderPage' })
}

$Exception 事件属性

属性 说明
$exception_level error(自动捕获 / 手动上报)或 fatal(崩溃补发)
$exception_type 异常类型名(如 TypeError / NSInvalidArgumentException / JVM 全类名)
$exception_message 异常 message
$exception_frames 结构化堆栈帧(平台家族路由符号化;仅解析出帧时上报,无空数组占位)

💡 iOS 崩溃的结构化帧在崩溃时刻预解析落盘(image_addr 依赖崩溃现场 ASLR 布局,不可事后重算),补发时直通使用。

合规(禁用采集)

为满足 GDPR 等隐私法规要求,SDK 提供 opt-out(禁用采集)能力。禁用期间,SDK 不发、不读、不写 任何埋点数据——所有事件上报、用户标识读写、公共属性写入、A/B 查询等对外 API 均为 no-op 且不抛错;唯一例外是 UTM 启动参数仍会静默捕获到内存,以便用户重新授权后补发首触归因。

以下三个方法均可在 init() / app.use() 之前调用(init 时会按优先级合并):

optOutCapturing()

立即禁用所有采集与上报:置内存标记并暂停发送器;若开启 persistOptOut: true,状态会同步写入本地存储(跨会话保留)。可在 init 前调用。

// 例:用户在隐私弹窗中拒绝授权
Sensorswave.optOutCapturing()

optInCapturing()

解除禁用状态,恢复正常的采集与上报流程。若禁用期间首触归因事件($UserSet)从未发送过,则使用禁用期间静默捕获的 UTM 的原始时间补发一次;禁用期间发生的其他事件一律不补发。可在 init 前调用。

// 例:用户在隐私弹窗中同意授权
Sensorswave.optInCapturing()

hasOptedOutCapturing()

查询当前是否处于禁用采集状态。返回 booleantrue = 已禁用,不发不读不写)。

if (Sensorswave.hasOptedOutCapturing()) {
  // 当前已禁用采集
}

初始化时的状态合并优先级

init() 阶段会按以下优先级确定最终的 opt-out 状态(高优先级覆盖低优先级):

  1. init 前 API 已 opt-out(调用过 optOutCapturing())→ 保留禁用状态
  2. config 显式 optOutCapturing: true → 强制禁用
  3. persistOptOut: true 且本地有持久化值(如 destroy 后重新初始化)→ 从本地存储恢复用户的授权决策
// 典型用法:默认禁用采集,由用户授权后再开启,且授权决策跨会话保留
app.use(Sensorswave.plugin, {
  sourceToken: 'your_source_token',
  apiHost: 'https://example.com',
  optOutCapturing: true, // 默认禁用,等用户授权
  persistOptOut: true,   // 授权决策持久化,重启后仍生效
})

// 用户同意授权后开启
Sensorswave.optInCapturing()

⚠️ 授权决策属于合规语义,destroy() 不会 清除本地持久化的 opt-out 状态;重新初始化时若 persistOptOut: true,仍会恢复用户上一次的授权选择。

其他

isInitialized()

查询 SDK 是否已完成初始化。返回 boolean。与只读属性 isInited 等价。

if (Sensorswave.isInitialized()) {
  Sensorswave.trackEvent('Ready')
}

isInited

只读属性,判断 SDK 是否已完成初始化。未初始化时为 false

if (Sensorswave.isInited) {
  Sensorswave.trackEvent('Ready')
}

init(sourceToken, config?)

手动初始化 SDK(不使用 Vue 插件)。sourceToken 作为独立参数传入。

⚠️ 直接调用 init() 不会注入页面生命周期 mixin,因此页面浏览 / 离开的自动采集将失效。 仅在你不需要自动页面采集、或希望完全控制初始化时机时使用。

Sensorswave.init('your_source_token', {
  apiHost: 'https://example.com',
  autoCapture: true,
})

destroy()

销毁 SDK 实例:停止批量发送器、销毁所有插件、移除全部事件监听器并重置为未初始化状态。销毁后可重新 init() 或再次 app.use() 安装。

Sensorswave.destroy()

自动采集事件

开启 autoCapture(默认开启)后,SDK 会根据运行平台自动注册对应采集器:

  • 小程序:启动、显示 / 隐藏、页面浏览 / 离开(由全局 mixin 驱动)、(默认)分享
  • App:启动 / 退出(后台满 30s 才触发 $AppEnd,30s 内回前台视为同会话)、首次安装、UTM 首值归因($UserSet)、页面浏览 / 离开(由全局 mixin 驱动)
  • H5:页面浏览、页面加载性能、页面离开、(可选)点击

页面浏览 / 离开采集通过 install() 注入的全局 mixin 统一驱动(onLoad / onShow / onHide / onUnload),业务页面零侵入——这是 Vue 插件的标准用法。直接调 init()(不走插件)时无 app 实例,需要改用手动集成,见上方「页面级事件接入」小节。

预置事件一览

事件 平台 触发时机
$MPLaunch 小程序 启动(自动)
$AppStart App 启动 / 从后台回前台(自动;30s 内回前台不发)
$AppInstall App 首次启动(自动)
$MPShow 小程序 进入前台(自动)
$MPHide 小程序 进入后台(自动,即时上报)
$AppEnd App 进入后台满 30s(自动)
$MPPageView 小程序 页面显示(全局 mixin 自动)
$AppPageView App 页面显示(全局 mixin 自动)
$PageView H5 页面显示(全局 mixin + vue-router 自动)
$MPPageLeave 小程序 页面离开 / 卸载(全局 mixin 自动,含 $event_duration
$AppPageLeave App 页面离开 / 卸载(全局 mixin 自动,含 $event_duration
$PageLeave H5 页面离开 / 卸载(自动,含 $event_duration
$PageLoad H5 页面加载性能(自动)
$WebClick H5 元素点击(需 enableClickTrack: true
$MPShare 小程序 用户分享(自动包裹 onShareAppMessage
$Identify 全部 identify()
$UserSet 全部 UTM 首值归因(每次启动 + 首次拿到非空 UTM 时自动发,含 5 个 UTM 键)
$FeatureImpress / $ExpImpress 全部 A/B 曝光(自动,含 user_properties: $feature_/ $exp_ 命中赋值或未命中清空)

预置属性

SDK 会自动采集一系列以 $ 开头的预置属性并附加到每个事件,包括:

  • 设备 / 系统$lib(固定 uniappx)、$lib_version$model$os$os_version$screen_width$screen_height$timezone_offset$language
  • 小程序特有$brand$manufacturer$network_type$scene
  • App 特有$brand$manufacturer$device_id$wifi$app_version$app_id$app_name$region$network_type
  • H5 特有$browser$browser_version$viewport_width$viewport_height
  • 页面信息$url$url_path$url_query$title$referrer(H5 另有 $host$pathname$referrer_host$search_engine
  • UTM 渠道utm_sourceutm_mediumutm_campaignutm_contentutm_term

⚠️ $ 前缀为系统保留,自定义事件属性请勿使用 $ 前缀,以免与预置属性冲突。

数据安全

  • 自定义事件属性脱敏tokenpasswordsecretcookiesession_idapi_key 等 17 类敏感关键词命中的字段,其值在发送前自动掩码为 ***(保留键名,仅丢弃值)。
  • URL 查询参数脱敏$url_query 中的敏感参数会被整体剔除。

鸿蒙适配

App 鸿蒙端需要声明网络与网络信息相关权限,否则事件数据无法上报、$network_type 等属性无法正常采集:

// entry/src/main/module.json5
{
  "module": {
    "requestPermissions": [
      { "name": "ohos.permission.INTERNET" },
      { "name": "ohos.permission.GET_NETWORK_INFO" }
    ]
  }
}

⚠️ 关键说明:必须配置 ohos.permission.GET_NETWORK_INFO 权限才能正确获取网络信息

鸿蒙平台上,SDK 通过 uni.getNetworkType() 获取当前网络类型以采集 $network_type 预置属性。若未声明 ohos.permission.GET_NETWORK_INFO 权限,uni.getNetworkType() 将调用失败,导致 $network_type 始终为空。这是鸿蒙端正确获取网络信息的前提,请务必在 module.json5 中声明该权限。

各权限作用:

  • ohos.permission.INTERNET:保证事件数据能正常上报
  • ohos.permission.GET_NETWORK_INFO:保证 $network_type 能正确获取

自定义基座与真机调试说明

uni-app x 的 iOS 端业务层(uvue / uts)始终运行在 JS 引擎上,uts 插件的原生实现只有打进自定义基座(或正式包)才会被编译生效。这决定了各功能在不同运行环境下的可用性:

功能 iOS 标准基座(开发运行) iOS 自定义基座·模拟器 iOS 自定义基座·真机 / 正式包 Android / 鸿蒙(任意运行)
基础埋点(预置事件 / trackEvent / 用户体系 / A/B / UTM / 公共属性)
trackException 手动上报
error 级异常自动采集 ❌(iOS 无 JS 级捕获面) ✅(仅鸿蒙有捕获面)
fatal 级崩溃采集(iOS) ❌ 静默降级 ⚠️ 仅「模拟派发」链路 ✅ 完整链路 ——
fatal 级崩溃采集(Android / 鸿蒙) —— —— —— ✅ 开发运行即可用

结论:只有 iOS 的 fatal 崩溃采集链路依赖自定义基座;其中「真实 NSException 派发」的验证还必须真机(模拟器可用模拟派发验证全链,见下)。 Android(Thread.setDefaultUncaughtExceptionHandler)与鸿蒙(errorManager + hiAppEvent)的崩溃采集走 JS 侧可直接编译的通道,开发运行即可验证;鸿蒙的 error 级 / fatal 级双通道同理。

iOS fatal 崩溃采集的接入步骤

iOS 端崩溃捕获需要原生钩子(NSSetUncaughtExceptionHandler),而主插件必须保留 JS 实现(标准基座可用性前提),其原生实现无法进基座——因此 iOS 崩溃捕获链承载在配套原生插件 sw-ios-crash-trigger 中(app-ios-only,无 JS 实现),由它负责崩溃钩子安装、崩溃线程落盘与记录读取;主 SDK 启动时经原生代理拉取记录并补发,业务侧零额外代码。

  1. 将配套插件 sw-ios-crash-trigger 导入工程 uni_modules/(与主 SDK 一同分发)
  2. 初始化时开启 enableCrashTrack: true
  3. 打自定义基座(会自动包含该插件的原生实现)
  4. 真机验证:触发崩溃 → 进程终止 → 重新打开应用 → 启动时补发 $Exception$exception_level = fatal

⚠️ 未集成配套插件(或标准基座运行)时,iOS fatal 链路静默降级:SDK 其余功能完全不受影响,仅崩溃不落盘、无补发。

许可

Apache-2.0

隐私、权限声明

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

android.permission.INTERNET

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

本插件会采集终端用户行为数据并上报至开发者配置的服务端

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

许可协议

MIT协议