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

如何運用 Long Animation Frames API (LoAF) 和採用智慧收益策略,讓 Taboola 在不損及廣告成效的情況下,改善發布商網站的回應速度。

David Belford
David Belford

「與下一個顯示的內容互動 (INP)」指標可評估網站在使用者輸入內容的回應速度。INP 會評估使用者開始互動 (例如點選、輕觸或輸入) 後,產生視覺回饋的時間。INP 即將在 2024 年 3 月取代 First Input Delay (FID) 做為 Core Web Vitals

Taboola 是全球首屈一指的內容探索平台,在開放網路中每秒提供 500,000 個推薦項目。這些最佳化建議可協助 Taboola 的 9,000 家專屬發布商合作夥伴,吸引目標對象並從中營利。發布者會使用 JavaScript 在網頁上顯示推薦內容。

由於第三方 JavaScript 可能會影響網頁對使用者輸入內容的回應速度,因此 Taboola 已投入大量資源,減少 JavaScript 檔案大小和執行時間。Taboola 一直在重新設計整個轉譯引擎,並直接使用瀏覽器 API 而非抽象化,以盡量減少對 INP 的影響。

本個案研究將說明 Taboola 如何透過使用全新的 Long Animation Frames (LoAF) API,評估該 API 對網頁回應速度的影響,並在後續的努力中應用特定最佳化方式,改善使用者體驗。

以 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 毫秒。

使用 TBT 做為 INP 的代理指標,Tabloa 開始監控及最佳化 JavaScript 執行時間,以限制 JavaScript 對 Core Web Vitals 的潛在影響。他們一開始是採取下列做法:

不過,Taboa 發現使用這些工具分析 TBT 時,有以下限制:

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

為解決這些問題,Tablooa 加入了Long Animation Frames (LoAF) API 原始試用計畫,以便進一步瞭解這項技術對使用者輸入回應的實際影響。來源試用可讓開發人員測試新功能或實驗功能,讓使用者在限時內試用。

請務必強調,這項挑戰最困難的部分,就是如何成功改善 INP,同時不影響任何廣告 KPI(主要成效指標),或造成發布商資源延遲。

使用 LoAF 評估 INP 的影響

如果算繪更新延遲超過 50 毫秒,就會出現長動畫影格。Taboola 找出使用者介面更新速度緩慢的原因 (而非單純的長時間工作),進而分析這項問題對實地網頁回應速度的影響。觀察 LoAF 後,Taboa 可以:

  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 });
  • 使用 loafEntryAnalysis 函式後,Taboa 就能找出自己是主要貢獻者的項目。
  • 如果腳本總時間的一半以上是由 Taboola 造成,或是 Taboola 腳本執行時間超過 50 毫秒,就會視為 Taboola 是主要影響因素。
  • 如果使用者互動因長動畫影格而延遲,系統就會產生 firstUIEventTimeStamp。系統會將最長封鎖時間長度視為整體 INP 分數,我們也可以判斷 Taboola 何時觸發 firstUIEventTimeStamp,以便計算 Taboola INP 分數。

透過 LoAF 收集的資料有助於 Taboola 建立下列歸因表,以便找出可運用產生商機的區域。

指令碼 時間長度 (毫秒)
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 進一步瞭解指令碼最佳化機會,Tabloa 也重新設計整個轉譯引擎,大幅縮短 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。

業務指標

多虧 LoAF,Taboola 才能更深入瞭解 LoAF 對 INP 的影響。這項工具也會標示出可用於新 TRECS 引擎的腳本最佳化機會。

為了評估 TRECS 和成效淡出功能的影響,Taboa 在出版商合作夥伴的面板上,針對 INP 與現有引擎 (不含無效指令碼) 進行 A/B 測試。

下表顯示 Taboola 網路中四個匿名發布商的 INP 結果,以毫秒為單位,並以第 75 百分位數為準。

發布端 INP 搭配 TRECS + 效能淡出效果 使用現有引擎的 INP INP 減少百分比
發布商 A 48 75 36%
發布商 B 153 163 6%
發布商 C 92 135 33%
發布商 D 37 52 29%

所幸,在測試面板中啟用 TRECS 和成效淡出功能後,廣告點閱率和每千次曝光收益 (RPM) 等業務指標並未受到負面影響。在 INP 方面取得正面進展後,廣告 KPI 沒有任何負面影響,Tabloa 將逐步改善發布商對產品的看法。

另一個針對先前所提客戶執行的 Lighthouse 顯示,在使用新引擎時,Tabloa 的主執行緒封鎖時間大幅改善。

在套用新的 TRECS 和 Performance Fader 引擎後,Lighthouse 稽核檢查畫面截圖,顯示封鎖主執行緒的時間。審查時間縮短至僅 206 毫秒,而最佳化前為 712 毫秒。
Taboola 的新引擎可協助 RELEASE.js 等指令碼將 TBT 縮短 485 毫秒 (-70%)

這項研究顯示,使用 LoAF 找出 INP 的原因,並透過成效淡出器部署後續的收益技術,可讓 Taboola 合作夥伴在廣告和網頁成效方面獲得最佳成效。

結論

改善 INP 是一項複雜的程序,尤其是在合作夥伴網站上使用第三方指令碼時。在開始進行最佳化前,將 INP 歸因於特定指令碼,可避免您對其他網站效能指標的猜測,並避免造成潛在的損害。LoAF API 已證實是用來找出及解決 INP 問題的實用工具,特別是針對嵌入的第三方,因為這可讓他們找出特定 SDK 改善機會,同時消除網頁上其他技術的干擾。

搭配使用 LoAF 和良好的產生策略 (例如使用 scheduler.postTask()),就能觀察並瞭解網頁回應速度不佳的原因,進而提供改善網站 INP 所需的資訊。

特別感謝 Google 的 Gilberto Cocchi、Noam Rosenthal 和 Rick Viscomi,以及 Taboola 工程和產品團隊的 Dedi Hakak、Anat Dagan 和 Omri Ariav,感謝他們對這項工作的貢獻。