归因与广告 SDK 接入实践:OpenInstall + TikTok
Created on
前言
归因与广告 SDK 的接入通常比推送更繁琐:既有深度链接、Universal Links,又有 IDFA 权限与平台差异。把这些配置沉淀为 Config Plugin,是保证工程可维护的关键。
本文以 OpenInstall + TikTok 的组合为例,拆解真实项目的接入路径与工程化策略。
目标拆解
我们需要解决的能力:
- OpenInstall: AppKey、Scheme、Universal Links
- 广告归因: iOS 的 IDFA 权限与 SKAdNetwork
- TikTok 事件追踪: SDK 初始化与事件上报
这些能力都需要同时配置原生层与 JS 层,因此最合适的方式是“插件化 + Hook 封装”。
插件入口:统一解析与配置
插件入口负责解析环境变量与参数,然后分发给 Android/iOS 子插件:
const withOpenInstall = (config, props = {}) => {
const appKey = resolveEnvPlaceholder(
props.appKey || process.env.EXPO_PUBLIC_OPENINSTALL_APPKEY
);
const scheme = resolveEnvPlaceholder(
props.scheme || process.env.EXPO_PUBLIC_OPENINSTALL_SCHEME
);
const domain = resolveEnvPlaceholder(
props.domain || process.env.EXPO_PUBLIC_OPENINSTALL_DOMAIN
);
return withPlugins(config, [
[
withOpenInstallAndroid,
{ appKey, scheme, domain, adEnabled: props.adEnabled },
],
[
withOpenInstallIOS,
{ appKey, scheme, domain, adEnabled: props.adEnabled },
],
]);
};
这一步的关键是“让配置源统一”,避免多处手工配置。
Android: manifestPlaceholders + 深度链接
OpenInstall 在 Android 侧需要写入 manifestPlaceholders,并配置 Scheme 与 App Links:
OPENINSTALL_APPKEY: project.findProperty('OPENINSTALL_APPKEY') ?: ''
mainActivity["intent-filter"].push({
action: [{ $: { "android:name": "android.intent.action.VIEW" } }],
category: [
{ $: { "android:name": "android.intent.category.DEFAULT" } },
{ $: { "android:name": "android.intent.category.BROWSABLE" } },
],
data: [{ $: { "android:scheme": scheme } }],
});
如果启用广告统计,插件还会按需加入 READ_PHONE_STATE 权限以兼容低版本设备。
iOS: Info.plist + Entitlements
iOS 侧关键点包括:
- AppKey 写入 Info.plist
- Scheme 写入 CFBundleURLTypes
- Universal Links 写入 Entitlements
infoPlist["com.openinstall.APP_KEY"] = props.appKey;
entitlements["com.apple.developer.associated-domains"].push(
`applinks:${props.domain}`
);
如果开启广告统计,还需要补齐 IDFA 权限描述:
infoPlist.NSUserTrackingUsageDescription =
props.idfaDescription ||
"为了您可以精准获取到优质推荐内容,需要您允许使用该权限";
TikTok: iOS SKAdNetwork 列表
TikTok 在 iOS 侧需要添加 SKAdNetwork IDs,用于 iOS 14+ 广告归因。插件会批量写入:
config.modResults.SKAdNetworkItems.push({
SKAdNetworkIdentifier: "238da6jt44.skadnetwork",
});
Android 侧目前不需要特殊配置,但保留插件入口,方便后续 SDK 升级。
JS 层封装:初始化与事件追踪
在 JS 层,通常会封装一个统一的事件 Hook,例如:
const { trackStandardEvent, trackCustomEvent, identify } = useTikTokEvents();
await trackStandardEvent("Purchase", { value: 99.9, currency: "THB" });
配合一个单例 Manager 管理 SDK 初始化,避免重复 init 造成异常。
在 app.config 中启用
[
"@repo/attribution/plugin",
{
appKey: process.env.EXPO_PUBLIC_OPENINSTALL_APPKEY,
scheme: process.env.EXPO_PUBLIC_OPENINSTALL_SCHEME,
domain: process.env.EXPO_PUBLIC_OPENINSTALL_DOMAIN,
adEnabled: true,
idfaDescription: "我们需要获取您的设备标识符用于归因分析",
},
];
TikTok 插件可按需启用:
[
"@repo/attribution/plugin/tiktok",
{ appId: process.env.EXPO_PUBLIC_TIKTOK_APP_ID },
];
验证流程
expo prebuild后检查 AndroidManifest 与 Info.plist- 真机验证深度链接与 Universal Links
- 推送或链接打开后校验归因参数
- 事件上报到 TikTok 控制台确认
小结
归因与广告 SDK 的接入核心不是“接上 SDK”,而是把原生配置变成可复用、可验证的工程化能力。通过 Config Plugin + Hook 的方式,可以让接入成本更低、升级更稳,也更适合长期维护。