主题
合规与隐私
文档版本 v1.0.0
本页对应 iOS SDK 1.0.0,与离线包 docs/ 目录里的同一份文档内容一致。其他版本见文档中心。
本文是接入方 App 上架应用商店的必备材料。 各大应用商店与《移动互联网应用程序信息服务管理规定》 均要求在隐私政策中完整披露所嵌入的第三方 SDK。「内嵌第三方 SDK 清单」与「申请的权限及用途」 两节可直接并入 App 隐私政策。
与平台相关的内容按 Android / iOS 分节,标题里带平台名;其余各节两个平台相同。
AdMix SDK 自身
AdMix 是聚合调度层,自身不收集、不存储、不传输任何个人信息。 它的作用是调度下方各广告平台的 SDK 并统一接口。
它有且只有两类网络行为,都只发往 SDK 内置的平台服务 https://api.maemi.cn, 两者都不携带任何用户标识或设备标识:
| 行为 | 内容 | 时机 |
|---|---|---|
| 拉取策略配置 | 下行:广告位、平台广告位 ID、底价、超时等投放策略。上行只有 AppID、签名参数,以及 SDK 版本、已集成的广告平台及其 SDK 版本;iOS 另带跟踪授权状态(授权结果的枚举值,不是 IDFA) | start 之后 |
| 上报广告埋点 | 上行:广告位、广告平台、平台广告位 ID、价格、耗时、错误码等广告维度数据 | start 之后 |
两者都严格晚于 start,也就是用户明确同意隐私政策之后。 在此之前 SDK 不发起任何网络请求、不读写任何持久化数据。这一点可实测验证,方法见本文末节。
内嵌第三方 SDK 清单
须写入隐私政策。接入方若只集成其中一家,隐私政策中只需披露实际集成的那一家。
瀑布流里加别家平台时必须补披露
穿山甲走的是 GroMore 聚合通道,广告可能由 GroMore 瀑布流里的其他平台(快手 / 百度 / Sigmob) 提供。当前瀑布流只配置了穿山甲一家,App 内也只集成了穿山甲 SDK,因此本清单是完整的。
若今后在 GroMore 后台的瀑布流里加入其他平台,App 必须同时集成对应平台的 SDK 与适配器, 并在隐私政策中补充披露那一家的名称、提供方与收集信息 —— 只改后台不改 App 拿不到广告, 而集成了却不披露则构成违规。这一步不能只由运营侧决定。两个平台都一样。
Android 内嵌 SDK
穿山甲(Pangle / GroMore)
| 项目 | 内容 |
|---|---|
| SDK 名称 | 穿山甲广告 SDK(含 GroMore 聚合能力,同一个 aar) |
| 提供方 | 北京巨量引擎网络技术有限公司 |
| 使用目的 | 广告投放、广告归因、反作弊 |
| 收集信息 | 设备标识(OAID、Android ID)、网络状态、设备型号、操作系统版本 |
| 隐私政策 | https://www.csjplatform.com/privacy |
位置信息:穿山甲 aar 不声明定位权限,且 AdMix 已设 isCanUseLocation() = false (见「设备信息采集控制」),因此不列入收集清单。按更保守的口径披露也可以, 但不要写成「已采集」。
优量汇(腾讯广告联盟)
| 项目 | 内容 |
|---|---|
| SDK 名称 | 优量汇广告 SDK |
| 提供方 | 深圳市腾讯计算机系统有限公司 |
| 使用目的 | 广告投放、广告归因、反作弊 |
| 收集信息 | 设备标识(OAID、Android ID)、网络状态、设备型号、操作系统版本、粗略位置信息(aar 声明了 ACCESS_COARSE_LOCATION)、应用安装情况 |
| 隐私政策 | https://e.qq.com/dev/help_detail.html?cid=2005&pid=5983 |
优量汇 SDK 内含腾讯自有的安全 / 反作弊模块(gdt_plugin 中的 yaq / Turing), 该模块在 SDK 初始化后会做设备环境与应用安装情况检测,这部分必须披露, 详见本文「Android 应用列表读取」。
只披露实际集成的那一家为什么是可证的(Android)
这不是口头承诺,是构建产物层面的事实,做隐私自查时可以直接取证:
每家广告平台的适配器是独立的 aar(
com.admix:adapter-csj/adapter-gdt), 各自把自家的广告 SDK 作为运行期依赖带进来。不引那个坐标,那家的 SDK 文件就不在 APK 里聚合核心不在代码里写死「支持哪几家」。每个适配器通过 Java SPI (
META-INF/services/com.admix.adapter.IAdnAdapter)自己声明身份,core启动时扫描一遍 —— 没被引入的那家在包里连一条声明都没有,不存在「代码在包里但没启用」这种灰色状态取证方式(任何能解压 APK 的工具都行):
bashunzip -p your-app.apk META-INF/services/com.admix.adapter.IAdnAdapter # 实际集成了哪几家适配器 # 只引穿山甲时输出只有一行:com.admix.adapter.csj.CsjAdapter再加一步反查:
com.qq.e.(优量汇)/com.bytedance.sdk.openadsdk.(穿山甲)的类在不在 dex 里运行期日志也能对上:启动时每个被发现的适配器打一行
adapter 就绪: csj (ADN SDK 7.7.1.6)
另外,被引入但没用到的广告平台在这台设备上也不会运行 —— 见下文「延迟初始化」: 某家只在首次加载到配置了它的广告位时才初始化。所以隐私政策仍需披露它(代码在包里), 但「从未采集」这一点在日志里可证。
iOS 内嵌 SDK
穿山甲(Pangle / GroMore)
| 项目 | 内容 |
|---|---|
| SDK 名称 | 穿山甲广告 SDK(CocoaPods Ads-CN/BUAdSDK,含 GroMore 聚合能力) |
| 提供方 | 北京巨量引擎网络技术有限公司 |
| 使用目的 | 广告投放、广告归因、反作弊 |
| 隐私政策 | https://www.csjplatform.com/privacy |
位置信息:AdMix 已通过 BUAdSDKPrivacyProvider 设 canUseLocation = NO、canUseWiFiBSSID = NO (WiFi BSSID 在 iOS 上属于位置信息),见「iOS 设备信息采集控制」。
优量汇(腾讯广告联盟)
| 项目 | 内容 |
|---|---|
| SDK 名称 | 优量汇广告 SDK(CocoaPods GDTMobSDK) |
| 提供方 | 深圳市腾讯计算机系统有限公司 |
| 使用目的 | 广告投放、广告归因、反作弊 |
| 隐私政策 | https://e.qq.com/dev/help_detail.html?cid=2005&pid=5983 |
两家 SDK 各自带有 Apple 隐私清单(PrivacyInfo.xcprivacy),其中申报的数据类型与跟踪域名 会进入 Xcode 生成的隐私报告,填写 App Store 隐私问卷时以报告为准,见下文「iOS 隐私清单」。
只披露实际集成的那一家为什么是可证的(iOS)
每家广告平台是独立的 CocoaPods 子模块(
AdMix/CSJ/AdMix/GDT),各自带入自家的广告 SDK。 不引那个子模块,那家的 SDK 就不在 App 里聚合核心按类名前缀
AdMixAdapter查找 App 里实际链接进来的适配器,没被引入的那家不存在取证方式(对 Release 包的可执行文件):
bashxcrun otool -ov YourApp.app/YourApp | grep -E 'name +0x[0-9a-f]+ AdMixAdapter' # 实际集成了哪几家适配器 # 只引穿山甲时只有一行 AdMixAdapterCSJ运行期日志也能对上:启动时打一行
适配器自检: 发现 [csj]
与 Android 相同,被引入但没用到的广告平台在这台设备上也不会运行。
申请的权限及用途
Android 权限
AdMix 自己的三个 aar 一个权限都不声明(清单为空)。下表是同时引入两家适配器后, 合并进宿主清单的全部权限,逐条来自打包产物的清单合并报告(外部最小工程实测,非文档推测)。
| 权限 | 来源 | 用途 | 敏感 |
|---|---|---|---|
INTERNET | 两家 | 请求广告、上报曝光点击 | 否 |
ACCESS_NETWORK_STATE | 两家 | 判断网络类型,决定是否加载视频素材 | 否 |
ACCESS_WIFI_STATE | 两家 | 网络质量判断 | 否 |
CHANGE_NETWORK_STATE | 两家 | 网络切换 | 否 |
CHANGE_WIFI_STATE | 穿山甲 | 网络切换 | 否 |
VIBRATE | 两家 | 互动广告振动反馈 | 否 |
WAKE_LOCK | 穿山甲 | 视频播放期间保持屏幕常亮 | 否 |
READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE | 穿山甲 | 素材缓存(SDK 侧 isCanUseWriteExternal()=false 已关闭写入) | 是 |
REQUEST_INSTALL_PACKAGES | 优量汇 | 下载类广告安装应用 | 是 |
ACCESS_COARSE_LOCATION | 优量汇 | 广告地域定向 | 是 |
REORDER_TASKS | 优量汇 | 广告落地页 / 任务栈调整 | 否 |
com.asus.msa.SupplementaryDID.ACCESS | 穿山甲 | 华硕机型取 OAID(MSA 服务) | 否 |
${applicationId}.openadsdk.permission.TT_PANGOLIN | 穿山甲 | 穿山甲自定义的应用内私有权限 | 否 |
接入方须在自己的清单里移除这两项:
xml
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" tools:node="remove" />
<uses-permission android:name="com.android.permission.GET_INSTALLED_APPS" tools:node="remove" />QUERY_ALL_PACKAGES由优量汇 aar 声明。移除后打包产物中确实不存在它(合并报告可证)GET_INSTALLED_APPS不是任何 SDK 声明的,是华为 ROM 在运行时自己加进 requested permissions 的(系统日志add requested permission),所以tools:node="remove"挡不住华为弹窗。写它只是显式表态
第二行会产生一条构建 Warning,属正常
tagged ... to remove other declarations but no other declaration present —— 它恰好证明没有任何 SDK 声明这一项。
另有一个 <queries> 段也来自两家 SDK(Android 11+ 包可见性声明,合规检测工具会扫): 穿山甲声明了抖音 / 抖音极速版两个包名与一个 https VIEW intent; 优量汇声明了 MAIN + LAUNCHER intent —— 有它在,即使没有 QUERY_ALL_PACKAGES, queryIntentActivities 也能列出全部可启动应用。
iOS 权限与 Info.plist
AdMix 不要求宿主申请定位、相册、相机、麦克风等任何系统权限;真机联调中两家广告 SDK 也没有弹出过系统授权框。 宿主 Info.plist 里与广告相关的配置只有下表几项:
| 配置 | 是否需要 | 说明 |
|---|---|---|
NSUserTrackingUsageDescription | 需要 | 跟踪授权弹窗的文案。弹窗由宿主决定是否、何时弹出,SDK 不弹,见《初始化》「跟踪授权」 |
NSAppTransportSecurity | 需要 | 两家的部分素材走明文 http,见《引入依赖》「网络安全配置」 |
LSApplicationQueriesSchemes | 不需要 | AdMix 不要求声明任何 scheme。声明了哪些,广告 SDK 就能查询哪些,见下文「iOS 应用安装探测」 |
iOS 隐私清单
AdMix 的每个组件(AdMixCore、AdMixAdapterCSJ、AdMixAdapterGDT)都自带 PrivacyInfo.xcprivacy, CocoaPods 集成时随 App 打包,Xcode 生成隐私报告(Archive 后 Organizer 里的 Generate Privacy Report) 时自动汇总,宿主 App 无需代为申报。手工集成时要把它们一并加入 App 包,见《引入依赖》「手工集成」。
AdMix 自身的申报内容:
| 项 | 内容 |
|---|---|
跟踪(NSPrivacyTracking) | 否,不访问 IDFA |
| 采集的数据 | 广告数据(广告请求、填充、曝光、点击、激励事件)、性能数据(加载耗时),均不关联用户身份、不用于跟踪 |
| 需说明理由的 API | 系统启动时间(35F9.1):仅在 App 内计算时间间隔(素材有效期、超时),不上传 |
两个适配器的清单是空声明:适配器只做接口翻译,不采集、不跟踪、不调用需说明理由的 API。
两家广告 SDK 的清单(以平台锁定版本的实际文件为准):
| 穿山甲 | 优量汇 | |
|---|---|---|
| 跟踪 | 未声明 | 声明为跟踪(NSPrivacyTracking = true),并列出跟踪域名 |
| 采集的数据类型 | 为空 | 含设备 ID,用途含跟踪 |
优量汇声明了跟踪域名,用户未授权跟踪时,系统会直接拦截发往这些域名的请求。 这一行为由系统控制,不影响 App 运行,也不影响优量汇出广告。
合规控制能力
延迟初始化
这是最重要的一条。SDK 采用两段式设计,两个平台方法名不同、语义一致:
| 阶段 | Android | iOS | 行为 |
|---|---|---|---|
| 第一段 | AdMix.init() | +[AdMix setupWithAppId:appKey:] | 仅读取本地配置,不联网、不采集任何设备信息,可在 App 启动时调用 |
| 第二段 | AdMix.start() | +[AdMix startWithCompletion:] | 才真正初始化各广告 SDK,必须在用户明确同意隐私政策之后调用 |
Android:
java
// 第一步:Application.onCreate —— 只读本地配置,不联网、不采集、不碰任何广告 SDK
AdMix.init(this, appId, appKey);
// 第二步:首次启动弹隐私政策弹窗;用户点「同意」之后才:
AdMix.start(listener);iOS:
objc
// 第一步:application:didFinishLaunchingWithOptions: —— 只读本地配置,不联网、不采集、不碰任何广告 SDK
[AdMix setupWithAppId:appId appKey:appKey];
// 第二步:首次启动弹隐私政策弹窗;用户点「同意」之后才:
[AdMix startWithCompletion:completion];uni-app 版对应 initAdMix 与 startAdMix,两段式语义相同,写法见 uni-app 版。
接入方务必遵守此顺序。用户未同意前调用 start 即构成违规采集。
三条容易被驳回的细节:
- 同意结果必须持久化(Android 用 SharedPreferences、iOS 用 NSUserDefaults 即可),否则每次启动都弹, 用户会当成弹窗广告
- 不同意不能不让用:只是没有广告,App 其余功能照常。做法是禁掉广告入口、 留一个「重新查看隐私政策」按钮
- 弹窗文案要能对应到实际集成的 SDK:把「内嵌第三方 SDK 清单」(名称、提供方、 收集信息、隐私政策地址)写进隐私政策全文,弹窗里给出入口
用户点「不同意」时一次 start 都不要调。此时 SDK 的状态是可实测的: 一家广告平台都没初始化、零网络请求、私有目录零文件,验证方法见本文末节。
还有一道兜底红线:任何广告加载请求在用户未同意时都会直接失败(错误码 -1006), 不管从哪个入口进来都不会碰到任何广告 SDK。
个性化广告开关
java
AdMix.init(context, "AppID", "App密钥", new AdMixConfig.Builder()
.limitPersonalAds(true) // true = 用户已关闭个性化推荐
.build());objc
AdMixConfig *options = [AdMixConfig new];
options.limitPersonalAds = YES; // YES = 用户已关闭个性化推荐
[AdMix setupWithAppId:@"AppID" appKey:@"App密钥" options:options];该设置会透传至各广告平台,须在首次加载广告之前确定:
| 广告平台 | Android | iOS |
|---|---|---|
| 穿山甲 | MediationPrivacyConfig.isLimitPersonalAds() | BUAdSDKConfiguration.mediation.limitPersonalAds |
| 优量汇 | GlobalSetting.setPersonalizedState(1) | [GDTSDKConfig setPersonalizedState:1] |
穿山甲侧的配置由 GroMore 继续下发给瀑布流里的每一家平台,不需要为新增平台再写一遍。
uni-app 版在 initAdMix 的可选项里传 limitPersonalAds。
流量分组标识
java
AdMix.init(context, "AppID", "App密钥", new AdMixConfig.Builder()
.channel("渠道").subChannel("子渠道") // 可选,不填不影响出广告
.build());objc
AdMixConfig *options = [AdMixConfig new];
options.channel = @"渠道"; // 可选,不填不影响出广告
options.subChannel = @"子渠道";
[AdMix setupWithAppId:@"AppID" appKey:@"App密钥" options:options];用于把广告收入拆分到不同接入方 / 产品线,会随广告请求上传给穿山甲(GroMore)。
uni-app 版在 initAdMix 的可选项里传 channel / subChannel / userValueGroup / segmentCustomInfo。
流量分组字段不得包含任何个人信息
这些字段以及自定义分组标签(Android segmentCustomInfo(key, value)、iOS segmentCustomInfos)上传的内容里,手机号、身份证号、精确位置、 可关联到自然人的账号 ID 一律不得出现。它们的定位是渠道标签, 放入个人信息即构成未告知的个人信息出境 / 共享,属违规。
Android 设备信息采集控制
AdMix 在适配器层已按最小必要原则默认收紧,接入方无需额外配置。
穿山甲 TTCustomController:
| 项目 | 默认 | 说明 |
|---|---|---|
| 位置信息 | 关闭 | isCanUseLocation() = false |
| 手机状态 / IMEI | 关闭 | isCanUsePhoneState() = false,getDevImei() 返回空 |
| MAC 地址 | 关闭 | getMacAddress() 返回空 |
| 外部存储读写 | 关闭 | isCanUseWriteExternal() = false |
| 录音权限 | 关闭 | isCanUsePermissionRecordAudio() = false |
| 短信 | 关闭 | isCanUseMessage() = false |
| 已安装应用列表 | 关闭 | alist() = false |
| Android ID | 开启 | 广告归因必需 |
| OAID | 开启 | 广告归因必需(未覆写 getDevOaid(),按 SDK 默认取值) |
| WiFi 状态 | 开启 | 网络质量判断 |
优量汇 GlobalSetting(全部在 SDK 初始化之前完成,顺序不可颠倒):
| 调用 | 值 | 作用 |
|---|---|---|
setAgreePrivacyStrategy | true | 已由聚合层保证用户已同意隐私政策 |
setAgreeReadAndroidId | true | 广告归因必需 |
setAgreeReadDeviceId | false | 不读设备号 |
setEnableCollectAppInstallStatus | false | 关闭后台收集已安装应用列表,见下节 |
setPersonalizedState | 按 limitPersonalAds | 个性化推荐开关 |
iOS 设备信息采集控制
iOS 系统本身不向 App 提供 IMEI、MAC、已安装应用列表等标识,Android 上那十几个设备标识开关在 iOS 上没有对应项。 AdMix 在适配器层把剩下的开关显式收紧,接入方无需额外配置。
穿山甲 BUAdSDKPrivacyProvider:
| 项目 | 默认 | 说明 |
|---|---|---|
| 位置信息 | 关闭 | canUseLocation = NO,经纬度返回 0 |
| WiFi BSSID | 关闭 | canUseWiFiBSSID = NO(iOS 上 BSSID 属于位置信息) |
| 传感器数据 | 关闭 | privacyConfig 里 motion_info = 0,开屏「摇一摇 / 扭一扭」依赖它 |
优量汇 GDTSDKConfig(在 SDK 初始化之前完成):
| 调用 | 值 | 作用 |
|---|---|---|
setPersonalizedState: | 按 limitPersonalAds | 个性化推荐开关 |
优量汇 iOS SDK 没有 Android 那个「应用安装情况采集」开关(平台锁定版本的头文件中不存在), iOS 也没有枚举已安装应用的系统接口,见下文「iOS 应用安装探测」。
IDFA 只在用户授予跟踪授权后才可能被读取,授权弹窗由宿主控制,见《初始化》「跟踪授权」。
已知问题
Android 应用列表读取
读取应用列表的是优量汇,不是穿山甲。 华为弹窗已修复并两轮真机验证通过; 遗留的是一项不弹窗但仍属采集的行为。
已修复:枚举应用列表 + 华为系统弹窗
优量汇初始化约 60 秒后,其内置的腾讯安全模块(gdt_plugin 中的 yaq / Turing, 调用链 com.qq.e.comm.plugin.u3$c.run → yaq.pro.* native)在定时任务里调 getInstalledPackages + queryIntentActivities(MAIN + LAUNCHER) 把应用全部枚举一遍, 华为 ROM 随即弹出「是否允许读取已安装应用列表」。
弹窗与展示哪家广告无关,只与「优量汇初始化后约 60 秒」这个定时有关 —— 它常常刚好出现在穿山甲广告展示期间,因此容易被误判成穿山甲。
修法:GdtAdapter 在优量汇 init 之前调 GlobalSetting.setEnableCollectAppInstallStatus(false)(优量汇客服已确认该开关即为 「关闭后台收集已安装包名列表」)。Debug 两轮 + Release 一轮真机验证:零枚举调用、 无权限申请、无弹窗,三种广告位广告正常。
清单这一侧的事实也需明确:QUERY_ALL_PACKAGES 是优量汇 aar 声明的(不是穿山甲); GET_INSTALLED_APPS 不是任何 SDK 声明的,是华为在运行时枚举发生后自己加进 requested permissions 的,所以宿主清单里的 tools:node="remove" 挡不住弹窗 —— 真正的开关是上面那一行。
仍然存在:按名单逐个探测约 276 个包名
开关关掉之后,同一个安全模块(yaq.pro.getJresult ← com.qq.e.comm.plugin.u3$d, 线程 GDT_NET_THREAD)改为逐个调用 getPackageInfo 探测约 276 个指定包名 (美团外卖、陌陌、B 站、饿了么、携程,以及一批 com.yw.cps.new.tencent.*), 约 0.2 秒查完,同样在优量汇初始化后约 60 秒。
华为不为此弹窗,但它本质上仍在探测应用是否安装。名单是写死还是服务端下发未确认 (方法体加壳,静态读不到),用什么开关能关未确认 —— 已向优量汇提交工单。
接入方应对建议:
- 隐私政策里把「应用安装情况」写进优量汇的收集信息。优量汇客服答复的要点是: 第三方 SDK 在静默或后台运行时收集个人信息的,需在隐私政策中明示收集频率并经用户同意 (频率可写「SDK 初始化后约 1 分钟,每进程一次」)
- 金融、政务等强监管行业 App:该项属工信部通报高发项,建议纳入上架前合规检查项
- 风险不能接受时只引
adapter-csj,优量汇 SDK 与这段行为就都不在包里,可按上文方法取证 - 穿山甲侧对照结论(供备查):逐类扫过 9444 个类并真机观察两轮约 25 分钟, 没有任何枚举类调用、没有触发弹窗;
queryIntentActivities只用于判断单个 Intent 能否打开
iOS 应用安装探测
iOS 没有枚举已安装应用的系统接口,App 只能用 canOpenURL: 逐个查询、且只能查询 Info.plist LSApplicationQueriesSchemes 里声明过的 scheme。所以广告 SDK 能探测到什么,取决于宿主声明了什么。
真机实测:穿山甲 SDK 初始化后会探测一次 weixin://。宿主未声明该 scheme 时探测拿不到结果; 宿主因接入微信 SDK 而声明了 weixin 时,穿山甲即可获知用户是否安装微信。 该行为的用途待向穿山甲确认。优量汇在广告展示与点击阶段的探测行为未覆盖。
不要照抄广告平台 Demo 的白名单
穿山甲官方 Demo 的 Info.plist 声明了 34 条 scheme,其中大部分是 Demo 自身的分享与登录功能所需。 照抄会让广告 SDK 多出一批可查询的应用,宿主 App 的隐私问卷里也要逐条解释。
广告交互样式
开屏广告的「摇一摇」「扭一扭」「上滑」等交互样式由广告平台后台配置, 热区设置过大即构成诱导点击,是监管通报的高发情形。
AdMix 在开屏请求时已显式关闭聚合侧的摇一摇:Android 关闭聚合侧的摇一摇按钮 (MediationAdSlot.setSplashShakeButton(false)),iOS 关闭穿山甲的传感器数据(motion_info = 0)。 但平台后台配置的交互样式优先级更高,仍须在各广告平台后台逐项确认。
广告埋点上报
本节描述 AdMix SDK 自己采集并上报的数据,与第三方 SDK 无关。 接入方需要在隐私政策中披露的是上文两节;本节说明的是「AdMix 到底往自己的服务端传了什么」, 供接入方做 SDK 自查和上架材料备查。事件类型与接入方可用的事件回调见《数据与事件》。
采集目的
出广告投放报表:填充率、曝光率、点击率、平均填充耗时、eCPM 估算。 数据用于投放策略优化、异常流量识别与对账核查, 不用于用户画像、不用于个性化推荐、不参与广告定向。
采集的字段
完整清单,一条不多:
| 字段 | 含义 | 举例 |
|---|---|---|
event_type | 事件类型 | ad_request / fill / impression / click / close / reward 等 10 种 |
unit_id | 广告位标识(平台定义) | reward_main |
ad_type | 广告形态 | splash / reward / banner |
adn | 广告平台标识 | csj / gdt |
slot_id | 平台广告位 ID | 形如 9890xxxxx |
bidding | 该广告源是竞价位还是瀑布层 | true / false |
ecpm | 广告价格,单位分 | 1500 |
cost_ms | 该阶段耗时 | 820 |
err_code / err_msg | 广告平台返回的错误码与错误信息,原样透传 | 5004 / 无匹配广告 |
sdk_version | AdMix SDK 版本 | 1.2.0 |
request_id | 一轮广告调度的随机标识 | 随机串,每轮不同 |
session_id | 单次启动的随机标识 | 随机串 |
event_time | 事件发生时刻 | 毫秒时间戳 |
ext.adn_source | 聚合通道下真正出广告的平台名 | pangle / ks |
app_id | 接入方在配置服务中的应用标识 | 平台后台创建应用时生成 |
全部是广告维度的数据。清单之外的任何字段都不会被上报。
明确不采集的内容
| 类别 | 例子 | 是否采集 |
|---|---|---|
| 设备标识 | IMEI、OAID、Android ID、MAC、序列号、IDFA、IDFV | 否 |
| 网络标识 | IP 地址、基站信息、WiFi 名称 | 否(服务端也不把 IP 记进埋点表) |
| 个人信息 | 手机号、身份证、用户 ID、昵称、位置 | 否 |
| 设备画像 | 机型、系统版本、分辨率、运营商、应用列表 | 否 |
| 可拼接标识 | 任何能跨 App 启动、跨设备关联到同一个人的稳定串 | 否 |
关于 session_id:它是每次进程启动随机生成的串,不落盘、不跨启动复用。 App 杀掉重启就是另一个值,无法用于跨启动或跨设备识别同一台设备或同一个人。 它唯一的用途是把一次启动内的事件串成漏斗。
关于 request_id:每轮广告调度随机生成,作用域只在这一轮之内,同样不具备任何标识能力。
接入方通过流量分组(channel / subChannel / userValueGroup / 自定义分组标签) 传入的内容一律不进埋点上报。 这是刻意的:这些字段的内容完全由接入方填写, SDK 无从保证其中不含个人信息,把它们接进埋点等于开了一条不受控的管道。 报表侧的归属拆分由服务端用 app_id 反查开发者完成,不需要客户端上报。
上报时机与前提
- 前提:用户明确同意隐私政策、宿主调用
start之后。 在此之前 SDK 不采集任何事件、不写任何文件、不发任何请求 - 频率:攒够 50 条或间隔 30 秒发一批,不是一条一发
- 传输:HTTPS POST 至 SDK 内置地址
https://api.maemi.cn/v1/events, 带 AppID 与签名参数(签名用的 App 密钥不随请求发送) - 本地缓存:待上报事件暂存于 App 私有目录(Android
files/admix_events.log、 iOSLibrary/Application Support/AdMix/events.log),其他应用无法读取;上报成功即删除。 队列上限 1000 条,超出丢弃最早的
为什么不提供关闭开关
上报内容全部是广告维度的数据,不含个人信息和设备标识,关闭它不会减少任何个人信息处理; 而这些数据是平台做流量质量风控、与广告平台结算数据交叉校验的依据, 因此 SDK 不提供关闭上报的配置项。
接入方能控制的是上报何时开始 —— 在用户同意隐私政策、调用 start 之前, SDK 不采集也不上报任何事件。
事件回调(Android AdMix.setEventListener()、iOS +[AdMix setEventHandler:])是另一条路径, 只在 App 进程内传递,不出设备。
数据保留
埋点明细在服务端保留 90 天,之后只保留不可还原到单次事件的聚合统计数据。
自行验证「同意之前不联网」
上架自查时可按以下步骤实测。两个平台的判据相同:同意之前没有任何 /v1/config 与 /v1/events 请求、 没有埋点队列文件、没有任何广告平台初始化记录。
Android
bash
adb shell pm clear <包名> # 清空应用数据
adb shell am start -n <包名>/<启动 Activity> # 启动,停在隐私弹窗,不要点同意
adb shell run-as <包名> ls files/ # 应为空:没有任何埋点队列文件同时在服务端访问日志(或抓包)中确认此阶段没有任何 /v1/config 与 /v1/events 请求, 且 logcat 里没有任何广告平台初始化记录。点击「同意」之后才会出现这两个请求。 本 SDK 已按此方法实测通过。
iOS
- 删除 App 后重新安装(清空沙盒),启动后停在隐私弹窗,不要点同意
- 用抓包代理(或服务端访问日志)确认此阶段没有发往
api.maemi.cn的请求 - 控制台搜索
subsystem:com.admix.sdk:只有AdMix setup 完成 … (尚未初始化 ADN,等待隐私授权)一行, 没有拉取远端配置与任何适配器就绪 - Xcode「Devices and Simulators」里下载该 App 的容器,
Library/Application Support/下没有AdMix目录
点击「同意」之后才会出现配置请求与埋点队列文件。
参考依据
- GB/T 43435-2023《信息安全技术 移动互联网应用程序(App)软件开发工具包(SDK)安全要求》
- GB/T 41391-2022《信息安全技术 移动互联网应用程序(App)收集个人信息基本要求》
- 《App 违法违规收集使用个人信息行为认定方法》
- 《移动互联网应用程序信息服务管理规定》