使用 AdAttributionKit 在保护用户隐私的前提下测量广告效果。适用于注册广告曝光(impression)、处理归因回传(postback)、更新转化值(conversion value)、实现二次互动(re-engagement)归因、配置媒体端(publisher)或广告主端(advertiser)应用,以及使用 AdAttributionKit 替代 SKAdNetwork 进行广告测量。
AdAttributionKit
面向 iOS 17.4+ 的隐私保护型广告归因框架。AdAttributionKit 允许广告网络在不暴露用户级数据的前提下测量转化(安装与二次互动)。它同时支持 App Store 和第三方应用市场(alternative marketplaces),并能与 SKAdNetwork 保持互操作。
归因流程中存在三种角色:广告网络(Ad network,负责签署曝光、接收回传)、媒体端应用(Publisher app,负责展示广告)和广告主端应用(Advertised app,被推广的目标应用)。
目录
概览与隐私模型
AdAttributionKit 通过以下机制保护用户隐私:
- 人群匿名分级(Crowd anonymity tiers) —— 设备根据与广告相关联的人群规模来限制回传数据的粒度,分为 Tier 0(极简数据)到 Tier 3(最丰富数据,包含媒体端 ID 和国家/地区代码)。
- 延时归因回传(Time-delayed postbacks) —— 回传会在转化窗口关闭后的 24–48 小时发送(第一个窗口),或 24–144 小时发送(第二/三个窗口)。
- 无用户级标识符 —— 回传仅包含聚合后的来源标识符(source identifiers)和转化值,不包含任何设备 ID 或用户 ID。
- 层级化来源标识符 —— 2 位、3 位或 4 位的来源 ID,具体返回几位取决于当前的人群匿名分级。
在迁移和互操作性评估中,需明确说明:系统会将 AdAttributionKit 和 SKAdNetwork 的曝光放在一起综合评估,每次转化仅有一个曝光胜出;点击归因(click-through)优先于展示归因(view-through);在点击归因同分时,更近发生的点击胜出,最后才会倒退回选最近一次展示归因。
媒体端应用配置
媒体端应用用于展示已注册广告网络的广告。需将各个广告网络的 ID 添加到应用的 Info.plist 中,以便其曝光具备安装验证资格。
添加广告网络标识符
<key>AdNetworkIdentifiers</key>
<array>
<string>example123.adattributionkit</string>
<string>another456.adattributionkit</string>
</array>
广告网络 ID 必须全部小写。系统同样支持 SKAdNetwork ID(以 .skadnetwork 结尾)——两个框架共享这些 ID。
展示 UIEventAttributionView
对于自定义渲染的点击类广告,需要在每个可点击的广告/控件上方覆盖一个 UIEventAttributionView。它必须完整覆盖点击区域,并保持在可能拦截触摸事件的其他视图之上,以确保 handleTap() 能够成功调用。
import UIKit
let attributionView = UIEventAttributionView()
attributionView.frame = adContentView.bounds
attributionView.isUserInteractionEnabled = true
adContentView.addSubview(attributionView)
广告主端应用配置
广告主端应用是指用户在看到广告后安装或重新打开的应用。它必须至少调用一次转化值更新,以开启回传转化窗口。
开启接收胜出回传副本
在顶级 AdAttributionKit Info.plist 字典下添加 AttributionCopyEndpoint,以便设备将胜出回传的副本发送到你的服务器:
<key>AdAttributionKit</key>
<dict>
<key>AttributionCopyEndpoint</key>
<string>https://example.com</string>
</dict>
系统会从 URL 中的可注册域名衍生出标准端点路径(忽略子域名):
https://example.com/.well-known/appattribution/report-attribution/
请配置服务器在该路径下接收 HTTPS POST 请求。域名必须配备有效的 SSL 证书。
开启接收二次互动回传副本
在同一个 AdAttributionKit 字典中添加第二个键,以同时接收胜出二次互动回传的副本:
<key>AdAttributionKit</key>
<dict>
<key>AttributionCopyEndpoint</key>
<string>https://example.com</string>
<key>OptInForReengagementPostbackCopies</key>
<true/>
</dict>
首次启动时更新转化值
应用首次启动后,尽早调用转化值更新以开启转化窗口:
import AdAttributionKit
func applicationDidFinishLaunching() async {
do {
try await Postback.updateConversionValue(0, lockPostback: false)
} catch {
print("Failed to set initial conversion value: \(error)")
}
}
广告曝光
广告网络使用 JWS(JSON Web Signature)生成已签名的曝光数据。媒体端应用使用 AppImpression 来注册和处理这些曝光。
根据 JWS 创建曝光
import AdAttributionKit
let impression = try await AppImpression(compactJWS: signedJWSString)
JWS 包含广告网络 ID、被推广项目 ID、媒体端项目 ID、来源标识符、时间戳以及可选的二次互动资格标志。详见 references/adattributionkit-patterns.md 了解 JWS 生成细节。
检查设备支持情况
guard AppImpression.isSupported else {
// 降级使用其他广告展示方式
return
}
展示归因曝光
当广告内容展示完毕并被关闭时,记录一次展示曝光:
func handleAdViewed(impression: AppImpression) async {
do {
try await impression.handleView()
} catch {
print("Failed to record view-through impression: \(error)")
}
}
对于长时间展示的广告,使用 beginView() 和 endView() 来追踪展示时长:
try await impression.beginView()
// ... 广告保持可见 ...
try await impression.endView()
点击归因曝光
用户点击广告后,需在创建 AppImpression 的 15 分钟内调用 handleTap();否则需要请求新的曝光对象。若未安装广告主端应用,系统会打开其 App Store 或应用市场页面;若已安装,系统会直接拉起应用。
func handleAdTapped(impression: AppImpression) async {
do {
try await impression.handleTap()
} catch {
print("Failed to record click-through impression: \(error)")
}
}
广告上方必须覆盖 UIEventAttributionView,handleTap() 才能成功执行。
StoreKit 渲染的广告
将曝光对象传递给 StoreKit overlay 或商品页控制器 API。StoreKit 会在广告展示 2 秒后自动记录展示归因曝光,并在点击时自动记录点击归因曝光。
import StoreKit
let config = SKOverlay.AppConfiguration(appIdentifier: "1234567890",
position: .bottom)
config.appImpression = impression
归因回传
归因回传是指在发生转化事件后,由设备发送给广告网络(以及可选的广告主应用开发者)的归因报告。
转化窗口
胜出的归因可能会跨越多个转化窗口生成多条回传;较低的数据分级和未胜出的归因披露的数据较少。有关最新的窗口与延迟矩阵,请参阅 references/adattributionkit-patterns.md。
事件时间窗口
归因资格窗口与转化/回传窗口是不同的概念。请结合当前官方文档与参考资料配置并校验展示归因、点击归因、安装更新及二次互动的限制;切勿混淆这两个概念。
提前锁定转化值
在窗口结束前锁定回传以固定转化值,可以更早接收到回传:
try await Postback.updateConversionValue(
42,
coarseConversionValue: .high,
lockPostback: true
)
锁定之后,系统将忽略该转化窗口内的后续更新。
各分级对应的回传数据
数据披露粒度随系统分配的数据分级提升而增加。代码和数据分析逻辑必须能够容忍缺失的来源位数、精细/粗粒度转化值、媒体端项目 ID 以及国家/地区代码。详细的分级矩阵见参考文档。
转化值
精细转化值
精细值为 0...63(6 位)的整数。它仅在第一个回传且处于 Tier 2 或更高分级时可用:
try await Postback.updateConversionValue(
35,
coarseConversionValue: .medium,
lockPostback: false
)
粗粒度转化值
针对较低分级以及第二/第三个回传,分为三个等级:
// CoarseConversionValue 可选值:.low, .medium, .high
try await Postback.updateConversionValue(
10,
coarseConversionValue: .high,
lockPostback: false
)
按转化类型更新(iOS 18+)
可以分别更新安装(install)与二次互动(re-engagement)回传的转化值。在服务端 JSON 中,使用带连字符的 "conversion-type": "re-engagement";而在 Swift API 中,使用不带连字符的 .reengagement。
let installUpdate = PostbackUpdate(
fineConversionValue: 20,
lockPostback: false,
conversionTypes: [.install]
)
try await Postback.updateConversionValue(installUpdate)
let reengagementUpdate = PostbackUpdate(
fineConversionValue: 12,
lockPostback: false,
conversionTypes: [.reengagement]
)
try await Postback.updateConversionValue(reengagementUpdate)
转化标签(iOS 18.4+)
当存在重叠的转化窗口时,使用转化标签有选择地更新特定回传:
let update = PostbackUpdate(
fineConversionValue: 15,
lockPostback: false,
conversionTag: savedConversionTag,
conversionTypes: [.reengagement]
)
try await Postback.updateConversionValue(update)
系统会通过二次互动 URL 的 AdAttributionKitReengagementOpen 查询参数传递转化标签。
二次互动
二次互动用于追踪已安装广告主端应用的用户,通过点击广告重新返回应用的行为。
将曝光标记为具备二次互动资格
生成曝光数据时,将 JWS Payload 中的 eligible-for-re-engagement 设置为 true。
使用 URL 处理二次互动点击
传递一个由系统在广告主端应用中打开的通用链接(Universal Link):
let reengagementURL = URL(string: "https://example.com/promo/summer")!
try await impression.handleTap(reengagementURL: reengagementURL)
系统会自动追加 AdAttributionKitReengagementOpen 作为查询参数。广告主端应用可通过检查此参数来识别由 AdAttributionKit 触发的打开行为:
func handleUniversalLink(_ url: URL) {
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
let isReengagement = components?.queryItems?.contains(where: {
$0.name == Postback.reengagementOpenURLParameter
}) ?? false
if isReengagement {
// 本次打开是由 AdAttributionKit 二次互动广告触发的
}
}
二次互动限制
- 仅点击互动(Click-through)会生成二次互动回传,展示互动(View-through)不会。
- 设备会对每个应用设置每月上限,对每台设备设置每年上限。
- 无论系统最终是否生成回传,URL 上始终会附带
AdAttributionKitReengagementOpen参数。
常见错误
| 常见错误 | 修复方案 |
|---|---|
| 首次启动时从未更新转化值 | 在预期的窗口超时前,调用标准的首次启动更新。 |
| 广告网络 ID 包含大写字符 | 严格使用小写的网络标识符。 |
handleTap() 使用了过期的曝光对象,或未在当前归因视图的点击中触发 |
用 UIEventAttributionView 覆盖广告区域,保持曝光对象最新,并在验证过的点击流程中进行调用。 |
| 点击错误... |
<!-- 因翻译批次截断;正文后半部分见源文件 -->






