如何運用 Long Animation Frames API (LoAF) 和採用智慧收益策略,讓 Taboola 在不損及廣告成效的情況下,改善發布商網站的回應速度。
「與下一個顯示的內容互動 (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 將重心放在盡量減少對這項指標的貢獻。
使用 TBT 做為 INP 的代理指標,Tabloa 開始監控及最佳化 JavaScript 執行時間,以限制 JavaScript 對 Core Web Vitals 的潛在影響。他們一開始是採取下列做法:
- 使用 Long Tasks API,找出並改善欄位中的有問題指令碼。
- 使用 PageSpeed Insights API 評估每天 10,000 到 15,000 個網址,估算 TBT 貢獻。
不過,Taboa 發現使用這些工具分析 TBT 時,有以下限制:
- Long Tasks API 無法將任務歸因於來源網域或特定指令碼,因此更難找出長時間執行的任務來源。
- Long Tasks API 只能找出長時間的工作,不會找出可能造成轉譯延遲的工作和版面配置變更組合。
為解決這些問題,Tablooa 加入了Long Animation Frames (LoAF) API 原始試用計畫,以便進一步瞭解這項技術對使用者輸入回應的實際影響。來源試用可讓開發人員測試新功能或實驗功能,讓使用者在限時內試用。
請務必強調,這項挑戰最困難的部分,就是如何成功改善 INP,同時不影響任何廣告 KPI(主要成效指標),或造成發布商資源延遲。
使用 LoAF 評估 INP 的影響
如果算繪更新延遲超過 50 毫秒,就會出現長動畫影格。Taboola 找出使用者介面更新速度緩慢的原因 (而非單純的長時間工作),進而分析這項問題對實地網頁回應速度的影響。觀察 LoAF 後,Taboa 可以:
- 將項目歸因於特定 Taboola 工作。
- 在特定功能部署至實際工作環境前,先觀察其效能問題。
- 收集匯總資料,比較 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 建立下列歸因表,以便找出可運用產生商機的區域。
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 百分位數為準。
所幸,在測試面板中啟用 TRECS 和成效淡出功能後,廣告點閱率和每千次曝光收益 (RPM) 等業務指標並未受到負面影響。在 INP 方面取得正面進展後,廣告 KPI 沒有任何負面影響,Tabloa 將逐步改善發布商對產品的看法。
另一個針對先前所提客戶執行的 Lighthouse 顯示,在使用新引擎時,Tabloa 的主執行緒封鎖時間大幅改善。
這項研究顯示,使用 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,感謝他們對這項工作的貢獻。