內容推薦供應商 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 透過全新長動畫影格 (LoAF) API,評估其對實際網頁回應度的影響,藉此改善 INP 的改善歷程,以及後續調整具體做法以改善使用者體驗。

TBT 做為 INP 的 Proxy

總封鎖時間 (TBT) 是一項研究室指標,可找出主執行緒在哪個位置遭到封鎖,進而影響網頁回應速度。測量回應速度 (例如 INP) 的實際指標可能會受到高 TB 影響。Annie Sullivan行動裝置的 TBT 與 INP 之間關聯性的調查結果顯示,在盡量減少主執行緒封鎖時間的情況下,網站更有可能達成良好的 INP 分數。

這樣的關聯,同時也與 Taboola 發布者Toola 是非常關注高未定案的疑慮,因此 Taboola 著重於將對這項指標的貢獻降到最低。

Lighthouse 稽核主執行緒時間遭封鎖的螢幕截圖。主要執行緒總共遭到多個指令碼封鎖 2,630 毫秒,而第三方 JavaScript 在這 712 毫秒的時間內就造成了 712 毫秒。Taboola 的 RELEASE.js 指令碼主要負責處理第三方封鎖作業的時間為 691 毫秒。
使用 Taboola 的舊引擎,RELEASE.js 等指令碼會封鎖主執行緒 691 毫秒。

Taboola 採用 TBT 做為 INP 的 Proxy 指標,開始監控及最佳化 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 來源試用,試圖進一步瞭解對使用者輸入回應回應的實際影響。來源試用提供全新或實驗功能的存取權,可讓開發人員測試新興功能,而且可讓使用者限時試用。

這裡一定要強調的是,最困難的部分是,在不犧牲任何廣告 KPI(主要成效指標) 或造成發布商資源延遲的情況下,成功改善 INP。

使用 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 });
  • 使用 loafEntryAnalysis 函式,可讓 Taboola 找出主要貢獻者的項目。
  • 如果 Taboola 最長的指令碼時間長度超過半數是 Taboola,或者 Taboola 指令碼執行時間超過 50 毫秒,系統就會視為主要貢獻者。
  • 如果使用者互動因長動畫影格而延遲,就會產生 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 深入瞭解指令碼的最佳化做法,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 結果。

發布端 採用 TRECS 和效能 Fader 的 INP 使用現有的引擎進行 INP 測試 INP 減少 (%)
發布商 A 48 75 36%
發布商 B 153 163 6%
發布商 C 92 135 33%
發布商 D 37 52 29%

幸好,在測試面板啟用 TRECS 和 Performance Fader 的情況下,廣告點閱率和每 1,000 次曝光 (千次曝光收益) 等業務指標不受影響。隨著 INP 的正向改善,但 Google Ads 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 的一項重要工具,可找出並解決內嵌第三方的特定 INP 問題,同時免除網頁上其他技術的干擾。

搭配良好的收益策略 (例如使用 scheduler.postTask()) 使用時,LoAF 可協助您觀察並瞭解網頁回應速度不佳的原因,進而取得改善網站 INP 所需的資訊。

在此特別感謝 Google 的 Gilberto Cocchi、Noam Rosenthal 和 Rick Viscomi 和 Taboola 工程與產品團隊的 Dedi Hakak、Anat Dagan 和 Omri Ariav 對此專案的貢獻。