使用__tcfapi事件监听器:面向同意感知脚本的开发者教程

为什么脚本应当监听而非轮询

任何依赖同意的脚本——广告标签、分析加载器、header bidding包装器——都需要知道两件事:CMP是否已有决定,以及该决定是什么。一个常见错误是在页面加载时读取cookie,或用定时器轮询CMP直到出现结果。这两种做法都会以可预见的方式失效:cookie格式是CMP的内部实现,可能会改变;而轮询要么触发得太早,要么白白浪费等待时间。

IAB TCF为这项工作定义了标准的JavaScript接口:__tcfapi函数。本教程将介绍你真正需要的命令、会收到的事件,以及生产环境中最常出现的错误。

存根与队列

TCF CMP应在完整的CMP脚本加载之前,尽早在页面上放置一个小型存根(stub)。存根定义window.__tcfapi,并将CMP就绪前发出的任何调用放入队列。CMP加载完成后,会处理该队列并回应每个调用。

这使得其他脚本可以安全地立即调用__tcfapi:只要存根位于它们之前,调用就不会丢失。如果某个脚本因__tcfapi未定义而抛出错误,说明存根缺失或加载得太晚——应修复加载顺序,而不是添加重试。

关键命令

ping

__tcfapi('ping', 2, callback)无需等待用户决定即可返回基本状态。响应包含cmpLoaded、cmpStatus(取值为stub、loading、loaded或error之一),以及displayStatus(取值为visible、hidden或disabled之一)。一旦确定,它还会报告gdprApplies。可用它做诊断,并判断TCF是否与该访客有关。

addEventListener

__tcfapi('addEventListener', 2, callback)是大多数集成应使用的命令。回调会收到一个tcData对象和一个成功标志,且每当同意状态变化时都会再次被调用。自TCF v2.2起,这是获取同意数据的推荐方式;较早的getTCData命令已被弃用。

removeEventListener

每个tcData对象都带有一个listenerId。当你的脚本不再需要更新时——例如一个已经做出决定的一次性加载器——将它传给__tcfapi('removeEventListener', 2, callback, listenerId)。

解读eventStatus

tcData中的关键字段是eventStatus,有三个取值:

典型的加载器会等待tcloaded或useractioncomplete之一,然后检查它所需的项目和供应商。它会忽略cmpuishown,至多用来记录横幅已出现。

检查项目与供应商

在tcData内部,同意和合法利益以按ID为键的对象形式提供:

项目和供应商都要检查。对大多数供应商来说,只有项目同意而没有供应商同意,或者反过来,都不足以处理数据。

iframe与跨框架调用

广告和小部件通常运行在iframe中,无法看到父页面的__tcfapi。TCF用postMessage协议解决了这个问题:CMP会在顶层页面添加一个名为__tcfapiLocator的框架,iframe内的代码可以找到它,发送__tcfapiCall消息并接收__tcfapiReturn响应。大多数广告SDK已经这样做了。如果你自己编写iframe代码,请实现同样的模式,而不要跨框架读取cookie。

常见错误及识别方法

  1. 对cmpuishown采取行动。只要任何回调触发就加载的脚本,会在用户做出决定之前运行。请按eventStatus过滤。
  2. 过早移除监听器。如果在第一次回调后就移除,你会错过之后的useractioncomplete,脚本永远不会加载。
  3. 忽略撤回。持续运行的脚本应保持监听,并在同意被撤回时停止或重新配置自己。
  4. 忽略gdprApplies。在TCF适用地区之外,项目对象可能为空;将其视为“无同意”可能会关闭你本可合法获得的收入。
  5. 不检查成功标志。当success为false时,请记录日志;这通常意味着CMP设置有问题。

测试你的集成

在浏览器控制台中,调用__tcfapi('ping', 2, console.log)确认CMP存在,然后以console.log为回调注册一个监听器,并点击操作横幅。首次访问时你应当看到cmpuishown之后是useractioncomplete,刷新后则是tcloaded。分别用全部接受、全部拒绝和自定义选择重复测试,并确认脚本在每种情况下行为正确。

核心要点

← 博客 阅读全部 →