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

瞭解 Taboola 運用 Long Animation Frames API (LoAF) 並採用智慧收益策略,能在不影響廣告成效的情況下,改善發布商的網站回應速度。

大衛貝爾福德
David Belford

與下一個顯示的內容互動 (INP) 指標可評估網站對使用者輸入內容的回應速度。INP 會測量從使用者開始互動 (例如點擊、輕觸或輸入) 到產生視覺回饋的時間。INP 起因於 2024 年 3 月將首次輸入延遲時間 (FID) 取代為 Core Web Vitals

Taboola 是全球首屈一指的內容探索平台,每秒提供 50 萬個開放式網路推薦機制。這些建議幫助 Taboola 的 9,000 個專屬發布商合作夥伴透過目標對象營利,並與他們互動。發布商使用 JavaScript 在他們的網頁上顯示建議。

第三方 JavaScript 可能會影響網頁是否能快速回應使用者輸入的內容,因此 Taboola 投注了大量心力來縮減 JavaScript 檔案大小與執行時間。Taboola 重新設計了整個轉譯引擎,以及在沒有抽象的情況下直接使用瀏覽器 API,以便將對 INP 的影響降至最低。

本個案研究涵蓋 Taboola 運用全新 Long Animation Frames (LoAF) API 評估 INP 在領域中對網頁回應速度的影響,然後再說明後續的最佳化措施,以改善使用者體驗。

待定做為 INP 的替代依據

總封鎖時間 (TBT) 是一項研究室式指標,會指出主要執行緒遭到封鎖時間過長,進而影響網頁回應速度。評估回應速度的欄位指標 (例如 INP) 可能會受到高 TBT 的影響。Annie Sullivan 進行了一項調查,其中指出行動裝置的 TBT 與 INP 之間的關聯性,顯示在主執行緒封鎖時間降到最低時,網站更有機會獲得良好的 INP 分數。

運用這項關聯,再加上 Taboola 發布者對高 TBT 的疑慮,Taboola 得以將注意力放在盡量降低對這項指標的貢獻。

Lighthouse 稽核 (主執行緒遭封鎖的時間) 螢幕截圖。多個指令碼總共遭到多個指令碼封鎖 2,630 毫秒,同時第三方 JavaScript 因此在這 712 毫秒內增加了 712 毫秒。Taboola 的 RELEASE.js 指令碼在 691 毫秒裡處理大部分的第三方封鎖時間。
使用 Taboola 的舊引擎,RELEASE.js 等指令碼會將主執行緒封鎖 691 毫秒。

Taboola 使用 TBT 做為 INP 的替代指標,開始監控並最佳化 JavaScript 執行時間,限制 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 指令碼的執行時間超過 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 的方式進一步瞭解指令碼最佳化機會,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 和成效 Fader 的影響,Taboola 針對現有引擎進行 INP 測試,以評估 INP 和發布商合作夥伴的小組不產生任何指令碼。

下表列出 Taboola 聯播網四個匿名發布商的第 75 個百分位數,以毫秒為單位計算 INP 結果。

發布者 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 等業務指標時,廣告點閱率和每 1,000 次曝光 (RPM) 等業務指標並未受到負面影響。隨著 INP 的正面改善成果未如預期出現任何負面結果,Taboola 將可逐漸改善發布商對自家產品的觀感。

另一位 Lighthouse 於同一客戶稍早執行,代表 Taboola 在使用新引擎時,主要執行緒會阻斷時間。

在套用新的 TRECS 和 Performance Fader 引擎後,針對主要執行緒封鎖時間的 Lighthouse 稽核螢幕截圖,以改善主執行緒的封鎖時間。相較於最佳化前的 712 毫秒,稽核結果降低至 206 毫秒。
Taboola 的新引擎協助 RELEASE.js 等指令碼減少 485 毫秒 (-70%) 的 TBT。

這證明瞭,Taboola 的合作夥伴能運用 LoAF 找出 INP 的原因,然後透過 Performance Fader 部署後續收益技術,大幅提升廣告和網頁成效。

結語

INP 最佳化作業相當複雜,尤其是在合作夥伴網站上使用第三方指令碼時。開始進行最佳化作業前,將 INP 歸咎於特定指令碼即可消除任何猜測,且可能破壞其他網站成效指標。事實證明,LoAF API 是找出及解決第三方內嵌 INP 問題的重要工具,尤其可找出特定 SDK 改善機會,同時消除網頁上其他技術的干擾。

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

特別感謝 Google 的 Gilberto Cocchi、Noam Rosenthal 和 Rick Viscomi,以及 Taboola 工程與產品團隊的 Dedi Hakak、Anat Dagan 和 Omri Ariav。