内容推荐服务提供商 Taboola 如何利用 LoAF 将其发布商合作伙伴网站的 INP 提升高达 36%。

Taboola 如何利用 Long Animation Frames API (LoAF) 并采用智能收益策略,在不影响广告效果的情况下提高发布商的网站响应速度。

David Belford
David Belford
Thierno Thiam
Thierno Thiam

Interaction to Next Paint (INP) 是一个指标,用于评估网站对用户输入的响应能力。INP 衡量的是从用户开始互动(例如点击、点按或输入)到产生的视觉反馈所用的时间。INP 将于 2024 年 3 月取代 First Input Delay (FID) 作为 Core Web Vitals 指标

Taboola 是全球领先的内容发现平台,每秒在开放网络上为 50 万次推荐提供支持。借助这些建议,Taboola 的 9,000 家独家发布商合作伙伴能够从受众群体中获利并吸引受众群体。发布商使用 JavaScript 在其网页上呈现推荐内容。

由于第三方 JavaScript 会影响网页快速响应用户输入的能力,因此,Taboola 投入了大量资源来缩减其 JavaScript 文件大小并缩短执行时间。Taboola 一直在重��设计整个渲染引擎,并直接使用未进行抽象化处理的浏览器 API,以尽量减少其对 INP 的影响。

本案例研究介绍了 Taboola 如何使用新的 Long Animation Frames (LoAF) API 来衡量其对实际页面响应速度的影响,从而改进 INP 的历程,以及后续如何应用特定优化措施来提升用户体验。

TBT 作为 INP 的替代指标

总阻塞时间 (TBT) 是一项基于实验室的指标,用于标识主线程在什么位置被阻塞的时间足够长,可能会影响网页响应速度。衡量响应能力的实测指标(如 INP)可能会受到 TBT 高的影响。Annie Sullivan移动设备上的 TBT 与 INP 之间的关联进行的研究表明,尽可能缩短主线程阻塞时间后,网站更有可能获得良好的 INP 得分。

这种相关性,再加上 Taboola 发布商对 TBT 高的担忧,使得 Taboola 将注意力集中在尽可能减少对该指标的贡献上。

Lighthouse 针对阻塞主线程时间的审核的屏幕截图。主线程被多个脚本总共阻塞了 2,630 毫秒,而第三方 JavaScript 则贡献了 712 毫秒。Taboola 的 RELEASE.js 脚本负责大部分第三方阻塞时间,即 691 毫秒。
在 Taboola 的旧引擎中,RELEASE.js 等脚本会将主线程阻塞 691 毫秒。

Taboola 使用 TBT 作为 INP 的代理指标,开始监控和优化 JavaScript 执行时间,以限制其对核心网页指标的潜在影响。他们首先采取了以下措施:

不过,Taboola 注意到,使用这些工具分析 TBT 存在一些局限性:

  • Long Tasks API 无法将任务归因于源网域或特定脚本,因此更难识别长任务的来源。
  • Long Tasks API 只能识别长时间运行的任务,而非可能导致渲染延迟的任务和布局更改的组合。

为了克服这些挑战,Taboola 加入了 Long Animation Frames (LoAF) API 源试用,以便更好地了解它对用户输入响应能力的真实影响。源试用是指用户能够使用新功能或实验性功能,让开发者能够测试新功能,并允许用户限时试用这些新功能。

请务必强调,此次挑战中最困难的方面是如何成功改进 INP,而不影响任何广告 KPI(关键绩效指标)或导致发布商资源延迟。

使用 LoAF 评估 INP 的影响

如果渲染更新延迟超过 50 毫秒,就会出现较长的动画帧。通过找出导致界面更新缓慢的原因(而不仅仅是冗长任务),Taboola 能够分析其对实际应用页面响应速度的影响。观察 LoAF 让 Taboola 可以:

  1. 将条目归因于特定的 Taboola 任务。
  2. 在将特定功能部署到生产环境之前,观察特定功能存在的性能问题。
  3. 收集汇总数据以比较 A/B 测试中的不同代码版本,并报告关键成效指标。

以下 JavaScript 是在生产环境中使用的简化版本,用于收集 LoAF,以分离 Taboola 的影响。

function loafEntryAnalysis (entry) {
  if (entry.blockingDuration === 0) {
    return;
  }

  let taboolaIsMajor = false;
  const hasInteraction = entry.firstUIEventTimestamp > 0;
  let taboolaDuration = 0;
  const nonTaboolaLoafReport = {};
  const taboolaLoafReport = {};

  entry.scripts.forEach((script) => {
    const taboolaScriptBlockingDuration = handleLongAnimationFrameScript(script, taboolaLoafReport, nonTaboolaLoafReport);
    taboolaDuration += taboolaScriptBlockingDuration;

    if (taboolaScriptBlockingDuration > 0 || taboolaDuration > entry.duration / 2) {
      taboolaIsMajor = true;
    }
  });

  generateToboolaLoafReport(taboolaLoafReport, nonTaboolaLoafReport, hasInteraction, taboolaIsMajor);

  if (hasInteraction) {
    const global = _longAnimationFramesReport.global;
    global.inpBlockingDuration = Math.max(global.inpBlockingDuration, entry.blockingDuration);

    if (taboolaIsMajor) {
      global.taboolaInpBlockingDuration = Math.max(global.taboolaInpBlockingDuration, entry.blockingDuration);
    }
  }
}

const observer = new PerformanceObserver(list => {
  for (const entry of list.getEntries()) {
    loafEntryAnalysis(entry);
  }
});

observer.observe({ type: 'long-animation-frame', buffered: true });
  • Taboola 使用 loafEntryAnalysis 函数可以识别出它在哪个条目中起到主要作用。
  • 如果来自 Taboola 的脚本总时长超过一半或是由 Taboola 脚本的运行时间超过 50 毫秒,则系统认为 Taboola 是主要影响因素。
  • 如果用户互动因长动画帧而延迟,系统会生成 firstUIEventTimeStamp。最长的阻塞持续时间会被视为总体 INP 得分。我们还可以确定 Taboola 何时触发了 firstUIEventTimeStamp 来计算 Taboola INP 得分。

通过 LoAF 收集的数据帮助 Taboola 创建了以下归因表,确定它可以在哪些方面应用创收机会。

Script 持续时间(毫秒)
vpaid/units/33_6_8/infra/cmTagINLINE_INSTREAM.js:106517 997
vpaid/units/33_6_8/infra/cmTagFEED_MANAGER.js:496662 561
vpaid/vPlayer/player/v15.8.6/OvaMediaPlayer.js:44631 336
libtrc/impl.20231212-23-RELEASE.js:821090 857
publisher_name/pmk-20220605.5.js:7728 336
libtrc/card-interference-detector.20231219-7-RELEASE.es6.js:183 239
Taboola RUM 捕获的 LoAF 脚本条目

TRECS Engine:新的收益策略

除了使用 LoAF 来更好地了解脚本优化机会之外,Taboola 还一直在重新设计整个渲染引擎,以大幅缩短 JavaScript 的执行和阻塞时间。

TRECS (Taboola Recommendations 可扩展客户端服务) 可维护客户端渲染和发布商当前的 JS 代码,同时减少加载 Taboola 的建议所需的必需文件的数量和大小。

在使用 LoAF 识别出渲染阻塞任务后,“Performance Fader”可以先将这些任务分解,然后再使用 scheduler.postTask() 让出主线程。这种设计可确保,无论任何现有任务可能占用主线程,都能尽快执行面向用户的关键工作(例如渲染更新)。

以下是“Performance Fader”任务运行程序的 JS 代码段:

/**
* Send a task to run using the Fader. The task will run using the browser Scheduler, by the configuration settings, or immediately.
* @param task
* @param isBlocker
*/
function sendTaskToFader (task, isBlocker = true) {
  const publisherFaderChoice = fillOptimizationGlobals(); // Loading publisher choice
  const applyYielding = publisherFaderChoice === OptimizationFaderType.Responsiveness;

  if (applyYielding) {
    return runAsPostTask(task, isBlocker);
  }

  return runImmediately(task);
}

/**
* Yielding method using scheduler.postTask and falling back to setTimeout when it's not availabe based on the publisher choice
*/
function runAsPostTask (task, isBlocker = true) {
  if ('scheduler' in window && 'postTask' in scheduler) {
    const priority = isBlocker ? 'user-blocking': 'background';

    return window?.scheduler?.postTask(task, { priority });
  }

  const publisherChoiceEnableFallback = fillPublisherChoices();

  if (publisherChoiceEnableFallback) {
    return new Promise(resolve => {
      window.setTimeout(() => {
        resolve(task());
      }, 0);
    });
  }

  return runImmediately(task);
}

sendTaskToFader 函数

  • 使用 runAsPostTask,后者会在后台使用 scheduler.postTask()(如果 API 可用),或回退到 setTimeout
  • 此函数会将函数调用封装在导致长动画帧和 INP 的代码部分中。它会将这些代码部分拆分为较短的任务,从而减少 INP。

业务指标

得益于 LoAF,Taboola 能够更好地了解其对 INP 的影响。该工具还突出显示了可用作新 TRECS 引擎一部分的脚本优化机会。

为了确定 TRECS 和 Performance Fader 的影响,Taboola 对一组发行商合作伙伴进行了一项 A/B 测试,以对照现有引擎来衡量 INP,而无需生成任何脚本。

下表显示了 Taboola 网络中四个匿名发布商的第 75 个百分位的 INP 结果(以毫秒为单位)。

Publisher INP 与 TRECS + Performance Fader 使用现有引擎生成 INP INP 下降幅度 (%)
发布商 A 48 75 36%
发布商 B 153 163 6%
发布商 C 92 135 33%
发布商 D 37 52 页 29%

幸运的是,在测试面板启用 TRECS 和 Performance Fader 后,广告点击率和每千次展示收入 (RPM) 等业务指标并未受到负面影响。随着对 INP 的积极改进,广告 KPI 没有达到预期的效果,Taboola 将会逐步提升发布商对其产品的看法。

之前针对同一客户运行的另一个 Lighthouse 显示,使用新引擎时,Taboola 显著缩短了主线程阻塞时间。

屏幕截图:采用新的 TRECS 和 Performance Fader 引擎以缩短主线程阻塞时间后,对主线程阻塞时间进行的 Lighthouse 审核。审计时间缩短至仅 206 毫秒,与优化前的 712 毫秒相比。
Taboola 的新引擎帮助 RELEASE.js 等脚本将 TBT 缩短了 485 毫秒 (-70%)

这表明,使用 LoAF 找出 INP 的原因,并通过 Performance Fader 部署后续产出技术,可让 Taboola 的合作伙伴在广告和页面性能方面取得最大成功。

总结

优化 INP 是一个复杂的过程,尤其是在合作伙伴网站上使用第三方脚本的情况下。在开始优化之前,将 INP 归因于特定脚本可以消除任何猜测,并消除对其他网站性能指标的潜在损害。事实证明,LoAF API 是一款非常有价值的工具,可用于识别和解决 INP 问题(尤其是对于嵌入的第三方)。通过它,他们可以精确找出具体的 SDK 改进机会,同时消除对网页上其他技术的干扰。

结合有效的收益策略(例如使用 scheduler.postTask())时,LoAF 可帮助您观察和了解网页响应速度不佳的原因,进而为您提供改进网站 INP 所需的信息。

特别感谢 Google 的 Gilberto Cocchi、Noam Rosenthal 和 Rick Viscomi,以及 Taboola 工程和产品团队的 Dedi Hakak、Anat Dagan 和 Omri Ariav,对这项工作做出的贡献。