WWDC Quick Look 💓 By SwiftGGTeam
What's new with SKAdNetwork

What's new with SKAdNetwork

观看原视频

Highlight

SKAdNetwork 4.0 将 Campaign ID 扩展为层级 Source Identifier,引入粗细两级转化值、三轮 postback、Web 广告归因和 StoreKitTest 测试能力,让广告主在 crowd anonymity 约束下获得更多安装归因信号。


核心内容

做广告归因有一个长期矛盾:广告主需要知道广告是否带来安装和后续行为,用户不希望自己的行为被跨 App 或跨网站追踪。SKAdNetwork 的位置就在这里。它让广告网络、publisher app 和 advertiser app 通过签名 impression、首次启动信号、conversion value 更新和 postback 完成安装归因,同时把用户隐私保护放在协议里(00:36)。

SKAdNetwork 4.0 的核心变化,是在不突破隐私边界的前提下给广告主更多信号。Apple 用 crowd anonymity 描述这个边界:安装量低时,postback 返回更少字段;安装量升高后,用户混入更大的群体,系统才返回更多细节(03:38)。

这套规则影响每一个新字段。Source Identifier 的位数、conversion value 的粒度、postback 的次数,都会受 crowd anonymity 约束。开发者要做的事情也变了:字段不能随便编码,服务器不能只解析旧格式,测试不能等线上广告跑起来才发现签名或 postback 有问题。

从单一 Campaign ID 到层级 Source Identifier

旧版 SKAdNetwork 的 campaign identifier 是 2 位字段。SKAdNetwork 4.0 把它扩展到 4 位,并改名为 Source Identifier。Apple 建议把它当成 2 位、3 位、4 位三层结构,而不是一个普通整数(04:41)。

这个设计适合归因钻取。前 2 位可以代表广告活动,第 3 位可以代表分桶后的用户位置,第 4 位可以代表屏幕上的广告位置。也可以把它设计成 treatment、时间段、广告尺寸。关键点是:低匿名等级可能只返回 2 位,高匿名等级才返回完整 4 位。

从一次 postback 到三次 postback

旧模型只有一个 postback。Food Truck 示例里,用户启动 App、拿起第一批甜甜圈后,postback 时间到了;用户后来完成配送,这个后续行为就无法再归因(10:18)。

SKAdNetwork 4.0 改成三个固定时间窗口,对应三个 postback。第一轮仍然能携带 fine conversion value;后两轮可以携带 coarse conversion value。这样,开发者能把安装后的短期行为和更晚发生的 re-engagement 分开记录(11:21)。

Web 广告也进入 SKAdNetwork 流程

过去的典型流程发生在 publisher app:广告点击打开 App Store 产品页,安装后由 SKAdNetwork 发 postback。SKAdNetwork 4.0 把同样的隐私保护归因扩展到网页广告。用户在 Safari 点广告链接后,App Store 会从广告网络服务器获取签名 impression,再走后续安装归因流程(12:53)。

Web 链接里有两个关键字段:attributionDestination 告诉 Apple 去哪里获取签名 impression,attributionSourceNonce 帮助广告网络定位要返回的那一份签名 impression(13:47)。


详细内容

1. Source Identifier 要按匿名等级设计

04:41)SKAdNetwork 4.0 把 2 位 campaign identifier 扩展为 4 位 Source Identifier。返回结果随 crowd anonymity 变化:低等级返回 2 位,中等级返回 3 位,高等级返回完整 4 位(07:04)。

可以把 Source Identifier 当成嵌套信息来设计。以 transcript 中的 5739 为例,返回粒度随 crowd anonymity 提升而增加:

Crowd anonymitypostback 中可能返回的内容设计含义
Low2-digit component最少细节,只放最关键、最低风险的业务分类
Medium3-digit component在 2 位基础上增加一层分桶信息
Highfull 4-digit source identifier返回完整 4 位,可包含最细的实验、位置或广告展示信息

关键点:

  • Source Identifier 是 SKAdNetwork 4.0 新的 4 位字段,替代过去的 2 位 campaign identifier。
  • 5739 应该被理解为嵌套业务维度的编码结果,不要把完整 4 位误标成单个“广告位”或“位置”字段。
  • transcript 说明 SKAdImpression 有新的 sourceIdentifier 属性;如果使用 dictionary 配置 impression,也要填写 Source Identifier 字段,具体 key 以 Apple 文档和当前 SDK 为准。
  • 服务端和客户端必须共享同一套编码表,否则 postback 里的数字无法还原业务含义。
  • 编码表要覆盖 2 位、3 位、4 位三种返回情况;不要把最重要的信息只放在第 4 位,因为低匿名等级下它不会返回。

2. Conversion value 分成 fine 和 coarse

06:08)旧版 conversion value 是 6 bit。SKAdNetwork 4.0 引入两种值:fine-grained conversion value 仍然是原来的细粒度值;coarse-grained conversion value 只有 low、medium、high 三档。

Apple 给出的例子是 high 42high 是 coarse value,42 是 fine value。coarse value 需要的安装量更低,因此 App 能更早拿到粗粒度结果;同一次 postback 只会返回其中一种 conversion value(06:34)。

// 概念示例:用 fine + coarse 两层值描述一次用户行为
let fineValue = 42
let coarseValue = "high"

SKAdNetwork.updatePostbackConversionValue(
    fineValue,
    coarseValue: coarseValue
) { error in
    // transcript 建议在 completion handler 中执行后续任务
}

关键点:

  • updatePostbackConversionValue 是 transcript 中提到的新方法名。
  • fineValue 对应旧版 6 bit conversion value。
  • coarseValue 对应 low、medium、high 三档值。
  • completion handler 应用于更新完成后的后续任务,这是 session 中明确给出的建议(08:33)。
  • 真实项目应使用当前 SDK 的正式类型和签名,不能直接把这个概念片段复制进生产代码。

设计 coarse value 时,不要把它当成 fine value 的简单截断。三档值只有很少信息量,适合表达“还没激活 / 已完成核心动作 / 高价值用户”这类粗分类。

3. 三轮 postback 要服务不同时间窗口

09:57)单一 postback 只能覆盖一个时间窗口。SKAdNetwork 4.0 的三个 postback 让开发者能记录安装后的不同阶段:启动、首次核心行为、后续 re-engagement。

// 概念示例:把不同阶段映射到不同 postback 窗口
func userDidLaunchApp() {
    updateConversion(window: 1, coarse: "low", fine: 5)
}

func userDidCompleteFirstDelivery() {
    updateConversion(window: 2, coarse: "medium", fine: nil)
}

func userDidCreateNewRecipe() {
    updateConversion(window: 3, coarse: "high", fine: nil)
}

关键点:

  • window: 1 对应第一轮 postback,它可以获得 fine conversion value。
  • window: 2window: 3 对应额外 postback,session 说明它们可以携带 coarse conversion value。
  • fine: nil 表示后两轮不依赖细粒度值。
  • 这个片段表达业务映射方式,updateConversion 不是 Apple API。

服务器也要按三轮 postback 存储数据。不要只保留“最后一次归因结果”。第一轮适合衡量安装后的早期质量,第二轮和第三轮适合衡量更晚发生的价值行为。

4. Web 广告归因需要能返回签名 impression

13:47)Web 广告链接的 href 指向 App Store 产品页。attributionDestination 告诉 Apple 到哪个域名取签名 impression。attributionSourceNonce 帮助广告网络找到对应的 impression。

<!-- 概念示例:Web 广告链接包含 App Store 目标和归因字段 -->
<a
  href="https://apps.apple.com/app/id123456789"
  attributionDestination="https://ad-network.example"
  attributionSourceNonce="nonce-from-ad-network">
  Download the app
</a>

关键点:

  • href 是被广告推广的 App Store 链接。
  • attributionDestination 是 Apple 获取签名 impression 的位置。
  • attributionSourceNonce 用来让广告网络定位原始广告 impression。
  • session 说明这类链接可用于 first-party site,也可用于 embedded cross-site iframe(14:11)。

Apple 会从 attributionDestination 提取 eTLD+1,再加上 fixed protocol、well-known qualifier 和固定 path components,构造 HTTP POST URL。POST body 是 JSON,并包含原始链接里的 source_nonce14:22)。

{
  "source_nonce": "nonce-from-ad-network"
}

关键点:

  • source_nonce 与广告链接中的 nonce 对应。
  • 广告网络用它查找并返回签名 impression。
  • 返回的 signed impression 会包含 source domain,它是 Web 归因流程里对应 source app ID 的字段。
  • postback server 要能解析新的可选 source domain 字段(15:43)。

5. StoreKitTest 可以验证 impression 和 postback

16:28)Apple 在 Xcode 13.3 中提供 SKAdNetwork testability changes,放在 StoreKitTest 的 unit testing framework 里。它解决两个常见摩擦点:impression 的签名和配置,以及 postback 的接收和验证。

验证 impression 的流程是:创建并配置 SKAdImpression,提供生成签名所用私钥对应的 public key,然后调用 SKAdTestSessionvalidate 方法。配置错误或签名无效都会抛错(17:19)。

// 概念示例:验证 SKAdImpression 的配置和签名
let impression = SKAdImpression()
let publicKey = loadPublicKeyForTesting()

try skAdTestSession.validate(impression, publicKey: publicKey)

关键点:

  • SKAdImpression 是被测试的广告 impression。
  • publicKey 对应签名私钥,session 明确要求提供它。
  • validate 来自 SKAdTestSession
  • 这个测试能在签名或 impression 配置错误时提前失败。

测试 postback 分两步。先创建 SKAdTestPostback,配置要发送的值和 postback URL,再通过 setPostbacks 加到 SKAdTestSession。随后调用 flushPostbacks,测试 postback 会被发送到指定的本地或远程服务器(17:49)。

// 概念示例:把测试 postback 送到指定服务器
let postback = SKAdTestPostback()
postback.url = URL(string: "https://example.test/skadnetwork/postback")!

skAdTestSession.setPostbacks([postback])
skAdTestSession.flushPostbacks()

关键点:

  • SKAdTestPostback 表示要模拟发送的 postback。
  • postback.url 是接收服务器地址,可以是远程服务器,也可以是本地服务器。
  • setPostbacks 把测试 postback 加入 session。
  • flushPostbacks 触发发送,session 说明它会经由网络发到指定服务器。

核心启发

1. 做一个 Source Identifier 编码表检查器

  • 做什么:把 4 位 Source Identifier 拆成 2 位、3 位、4 位三层含义,检查低匿名等级下是否仍能返回关键业务信息。
  • 为什么值得做:SKAdNetwork 4.0 会按 crowd anonymity 返回不同位数;错误编码会让低量级广告完全失去可分析信号。
  • 怎么开始:从 campaign、位置分桶、广告位三个维度建表,再为每个维度写反解逻辑。

2. 做一套 coarse conversion value 映射后台

  • 做什么:为 low、medium、high 三档定义独立含义,并把它们映射到安装后的关键行为阶段。
  • 为什么值得做:coarse value 比 fine value 更早返回,适合新广告活动或安装量较低的场景。
  • 怎么开始:把事件分成“启动”、“完成核心动作”、“高价值行为”三类,再将它们写入 conversion 更新策略。

3. 做三轮 postback 的归因看板

  • 做什么:按第一轮、第二轮、第三轮分别展示安装质量、后续行为和 re-engagement。
  • 为什么值得做:SKAdNetwork 4.0 不再只给一次 postback,后两轮能补上旧模型丢失的长期行为。
  • 怎么开始:服务器表结构增加 postback sequence 或窗口字段,查询层按窗口聚合转化事件。

4. 做 Web 广告签名 impression 服务

  • 做什么:根据 source_nonce 返回对应的 signed impression,并记录 source domain。
  • 为什么值得做:Web 广告进入 SKAdNetwork 后,广告网络需要能在 Apple 构造的 URL 上响应 HTTP POST。
  • 怎么开始:先实现 nonce 到 impression 的查找接口,再让 postback 解析逻辑兼容可选 source domain。

5. 做本地 postback 验证环境

  • 做什么:用 SKAdTestSessionSKAdTestPostback 把测试 postback 发到本地服务器,验证接收、解析和落库。
  • 为什么值得做:签名配置和 postback 接收是 session 中明确提到的摩擦点,单元测试能把问题提前暴露。
  • 怎么开始:在测试里配置 postback URL 指向本地服务,调用 setPostbacksflushPostbacks,断言服务器收到预期字段。

关联 Session

评论

GitHub Issues · utterances