內容推薦供應商 Taboola 如何使用 LoAF,為發布商合作夥伴網站改善高達 36% 的 INP。

瞭解 Taboola 如何運用 Long Animation Frames API (LoAF),並採用智慧型讓步策略,在不影響廣告成效的情況下,提升發布商網站的回應速度。

David Belford
David Belford

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) 是以實驗室為基礎的指標,可找出主執行緒遭封鎖的時間長度,可能影響網頁回應速度。如果 TBT 偏高,可能會影響用來評估回應性的現場指標,例如 INP。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 執行時間,以限制其對 Core Web Vitals 的潛在影響。他們首先採取了下列行動:

  • 使用 Long Tasks API 找出並最佳化實際環境中造成問題的指令碼。
  • 每天使用 PageSpeed Insights API 評估 10,000 到 15,000 個網址,預估 TBT 貢獻度。

不過,Taboola 發現使用這些工具分析 TBT 有一些限制:

  • Long Tasks API 無法將工作歸因於來源網域或特定指令碼,因此更難找出長時間工作的原因。
  • Long Tasks API 只會找出長時間執行的工作,不會找出可能導致延遲算繪的工作和版面配置變更組合。

為解決這些挑戰,Taboola 參與了 Long Animation Frames (LoAF) API 原始碼試用活動,進一步瞭解這項 API 對使用者輸入回應速度的實際影響。來源試用可讓開發人員使用新功能或實驗功能,測試新興功能,使用者則可在一段時間內試用這些功能。

請務必注意,這項挑戰最困難的部分,在於如何成功改善 INP,同時不影響任何 Google Ads 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 分數。

Taboola 運用 LoAF 收集的資料建立下列歸因表格,找出可套用收益機會的領域。

指令碼 時間長度 (毫秒)
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 引擎:全新的收益策略

除了使用 LoAF 更瞭解指令碼最佳化機會,Taboola 也重新設計了整個轉譯引擎,大幅縮短 JavaScript 執行和封鎖時間。

TRECS (Taboola Recommendations Extensible Client Service) 可維護用戶端算繪和發布商目前的 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。

業務指標

Taboola 運用 LoAF 更深入瞭解自身對 INP 的影響,這項工具也列出可做為新 TRECS 引擎一部分的指令碼最佳化商機。

為判斷 TRECS 和 Performance Fader 的影響,Taboola 對一組發布商合作夥伴進行 A/B 測試,並根據現有引擎 (面板上沒有產生指令碼) 評估 INP。

下表顯示 Taboola 聯播網中四位匿名發布商的第 75 百分位數 INP 結果 (以毫秒為單位)。

發布端 搭配 TRECS 和 Performance Fader 使用 INP 使用現有引擎的 INP INP 降幅 (%)
發布商 A 48 75 36%
發布商 B 153 163 6%
發布商 C 92 135 33%
發布者 D 37 52 29%

所幸,在測試面板上啟用 TRECS 和成效衰減功能後,廣告點閱率和每千次曝光收益 (RPM) 等業務指標並未受到負面影響。INP 沒有任何負面結果,且廣告 KPI 表現良好,因此 Taboola 將逐步改善發布商對產品的觀感。

稍早對同一位客戶執行的另一次 Lighthouse 測試顯示,使用新引擎後,Taboola 的主執行緒封鎖時間大幅縮短。

螢幕截圖:套用新的 TRECS 和 Performance Fader 引擎後,Lighthouse 稽核結果顯示主要執行緒遭到封鎖的時間縮短。最佳化調整後,稽核時間縮短至 206 毫秒,相較於先前的 712 毫秒,縮短了 70% 以上。
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,他們對這項工作貢獻良多。