WebView中的同意:保持原生与网页同意同步

双重横幅问题

许多应用一部分是原生的,一部分是网页的。游戏在WebView中显示其商店、新闻或帮助页面;工具类应用渲染来自其网站的文章;混合应用则把大部分界面包裹在网页内容中。双方各有自己的同意机制:原生应用使用应用内CMP或SDK,网页则加载网页CMP。除非二者相互连接,否则用户会被询问两次,在一处做出的选择在另一处被忽略,而来自WebView内部的广告请求则带着错误的信号发出。

本指南介绍如何让原生与网页的同意保持一致,使用户只需回答一次,每个广告请求都携带相同的决定。

双方分别在哪里存储同意

原生

IAB TCF规定了应用内CMP如何存储同意:在iOS上存于NSUserDefaults,在Android上存于SharedPreferences,使用IABTCF_TCString、IABTCF_gdprApplies和IABTCF_PurposeConsents等标准键。广告SDK直接读取这些键。IAB GPP定义了带有IABGPP_前缀的类似键,例如IABGPP_HDR_GppString。

网页

网页CMP通常把决定存储在网站域名下的第一方cookie或本地存储中,并通过__tcfapi和__gpp这两个JavaScript函数对外提供。页面中的广告标签调用的是这些函数,而不是原生存储。

差距

WebView拥有自己的cookie和存储空间,与设备浏览器分开,也与应用的原生偏好设置分开。在iOS上,使用非持久数据存储的WKWebView在关闭时会忘记一切。除非你自己搭建,否则双方之间不会有任何数据流动。

选定唯一可信来源

首先要决定由哪一方拥有同意。对大多数应用而言,答案是原生CMP,因为:

对于整个界面都是网页内容的混合应用,网页优先可能说得通,但那样你必须把决定写回原生存储,供原生SDK使用。

将原生同意传入WebView

以原生为可信来源时,WebView需要看到相同的决定。常见的做法有:

  1. 注入一个__tcfapi实现。在页面脚本运行之前,注入一小段脚本,定义__tcfapi(如有需要还有__gpp),并用从原生存储读取的TC string和各项值回应调用。这样页面中的广告标签就能通过标准API获取原生决定。
  2. 抑制网页横幅。配置网页CMP,使其在页面于你的应用内加载时保持隐藏,例如基于查询参数,或你自己控制的自定义用户代理标记。否则用户会看到第二个横幅。
  3. 在加载时传递字符串。一些网页CMP可以在初始化时接收现有的同意字符串并采用它。请查阅你的网页CMP文档,了解支持的方法。

无论采用哪种做法,都要确保当用户在原生设置界面中更改选择时,注入的值也随之更新,而不只是在下次启动应用时更新。

将网页同意传回原生

如果用户可以在WebView内更改同意,例如通过隐私设置页面,应用就必须得知此事。使用JavaScript桥:iOS上是消息处理器,Android上是JavaScript接口。网页端通过__tcfapi('addEventListener', ...)监听,并把新字符串发送给原生代码,由原生代码写入标准键。写入前要验证来自WebView的输入;只接受来自你自己内容的消息。

WebView内的广告

在WebView中渲染的广告属于网页广告。它们从页面而不是原生存储读取同意,除非广告SDK提供了关联二者的方法。例如,Google的Mobile Ads SDK提供了一个API,用于注册WebView,使其中的广告能够使用来自应用的信号;请查阅你所用SDK的最新文档。无论如何,都要通过测试确认来自WebView的广告请求携带的TC或GPP字符串与原生广告请求相同。

测试清单

核心要点

← 博客 阅读全部 →