Long Animation Frames API(LoAF)を活用し、スマートなイールド戦略を採用することで、Taboola は広告のパフォーマンスを損なうことなく、パブリッシャーのウェブサイトの応答性を向上させることができました。
Interaction to Next Paint(INP)は、ユーザー入力に対するウェブサイトの応答性を評価する指標です。INP は、ユーザーが操作(クリック、タップ、入力など)を開始してから、その結果として視覚的なフィードバックが表示されるまでの時間を測定します。INP は、2024 年 3 月にウェブに関する主な指標として First Input Delay(FID)に置き換わる予定です。
Taboola は、世界をリードするコンテンツ ディスカバリ プラットフォームであり、オープンウェブ上で毎秒 50 万件のレコメンデーションを提供しています。これらの推奨事項により、Taboola の 9,000 社の独占的なパブリッシャー パートナーは、視聴者を収益化し、エンゲージメントを高めることができます。パブリッシャーは、JavaScript を使用してページにレコメンデーションを表示します。
サードパーティの JavaScript は、ユーザーの入力にすばやく応答するページの機能に影響を与える可能性があるため、Taboola は JavaScript ファイルのサイズと実行時間を短縮することに力を入れています。Taboola は、レンダリング エンジン全体を再設計し、抽象化なしでブラウザ API を直接使用して、INP への影響を最小限に抑えています。
このケーススタディでは、Taboola が新しい Long Animation Frames(LoAF)API を使用してフィールドでのページの応答性に対する影響を測定し、ユーザー エクスペリエンスを改善するために特定の最適化を適用する取り組みを続けながら、INP を改善してきた過程を紹介します。
INP のプロキシとしての TBT
Total Blocking Time(TBT)は、メインスレッドがページ応答性に影響するほど長くブロックされた場所を特定するラボベースの指標です。INP などの応答性を測定するフィールド指標は、TBT が高いと影響を受ける可能性があります。Annie Sullivan によるモバイル デバイスでの TBT と INP の相関関係の調査によると、メインスレッドのブロック時間を最小限に抑えると、サイトで INP のスコアが良好になる可能性が高くなります。
この相関関係と、TBT の高さに関する Taboola のパブリッシャーの懸念から、Taboola はこの指標への影響を最小限に抑えることに注力しました。
RELEASE.js などのスクリプトがメインスレッドを 691 ミリ秒間ブロックします。
Taboola は、INP のプロキシ指標として TBT を使用し、JavaScript の実行時間をモニタリングして最適化し、Core Web Vitals への影響を最小限に抑え始めました。まず、次のことを行いました。
- Long Tasks API を使用して、フィールド内の問題のあるスクリプトを特定して最適化します。
- PageSpeed Insights API を使用して、毎日 10,000 ~ 15,000 個の URL を評価し、TBT の貢献度を推定します。
しかし、Taboola は、これらのツールで TBT を分析することにはいくつかの制限があることに気づきました。
- Long Tasks API では、タスクをオリジン ドメインや特定のスクリプトに関連付けることができないため、長いタスクの発生源を特定することが難しくなります。
- Long Tasks API は、レンダリングの遅延を引き起こす可能性のあるタスクとレイアウト変更の組み合わせではなく、長いタスクのみを特定します。
こうした課題に対処するため、Taboola は Long Animation Frames(LoAF)API のオリジン トライアルに参加し、ユーザー入力の応答性に対する実際の影響をより深く理解しようとしました。オリジン トライアルでは、新しい機能や試験運用版の機能をご利用いただけます。デベロッパーは、ユーザーが期間限定で試せる新機能をテストできます。
この課題で最も難しかったのは、広告の KPI(重要業績評価指標)を損なうことなく、パブリッシャーのリソースの遅延を引き起こすことなく、INP を改善することでした。
LoAF を使用して INP の影響を評価する
レンダリングの更新が 50 ミリ秒を超えて遅延すると、長いアニメーション フレームが発生します。Taboola は、長いタスクだけでなく、ユーザー インターフェースの更新が遅くなる原因を特定することで、フィールドでのページ応答性への影響を分析することができました。LoAF を観察することで、Taboola は次のことを行えるようになりました。
- エントリを特定の Taboola タスクに帰属させます。
- 特定の機能のパフォーマンスの問題を本番環境にデプロイする前に確認します。
- 集計データを収集して、A/B テストでさまざまなコード バージョンを比較し、主要な成功指標をレポートします。
次の JavaScript は、Taboola の影響を分離するために LoAF を収集する本番環境で使用される簡略版です。
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 が次のアトリビューション テーブルを作成するのに役立ちました。このテーブルは、収益化の機会を適用できる領域を特定します。
TRECS エンジン: 新しい収益化戦略
Taboola は、LoAF を使用してスクリプトの最適化の機会をよりよく理解するとともに、レンダリング エンジン全体を再設計して、JavaScript の実行時間とブロック時間を大幅に短縮しています。
TRECS(Taboola Recommendations Extensible Client Service)は、クライアントサイド レンダリングとパブリッシャーの現在の JS コードを維持しながら、Taboola のレコメンデーションを読み込むために必要な必須ファイルの数とサイズを削減します。
LoAF を使用してレンダリング ブロック タスクを特定したら、「パフォーマンス フェーダー」は scheduler.postTask() を使用してメインスレッドに処理を渡す前に、それらのタスクを分割できます。この設計により、メインスレッドを占有している既存のタスクに関係なく、レンダリングの更新などの重要なユーザー向け作業をできるだけ早く実行できます。
「パフォーマンス フェーダー」タスクランナーの 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 とパフォーマンス フェーダーの影響を判断するため、Taboola はパブリッシャー パートナーのパネルで、スクリプトのイールドがない既存のエンジンに対して INP を測定する A/B テストを実施しました。
次の表は、Taboola ネットワークの 4 つの匿名パブリッシャーの 75 パーセンタイルの INP の結果をミリ秒単位で示しています。
幸いなことに、テストパネルで TRECS とパフォーマンス フェーダーを有効にしても、広告のクリック率やインプレッション単価(RPM)などのビジネス指標に悪影響はありませんでした。INP が改善され、広告の KPI に悪影響が及ばないことが確認されたため、Taboola はパブリッシャーのプロダクトに対する認識を徐々に改善していきます。
前述の同じお客様の別の Lighthouse 実行では、新しいエンジンを使用すると、Taboola によるメインスレッドのブロック時間が大幅に改善されることが示されています。
RELEASE.js などのスクリプトで TBT を 485 ミリ秒(-70%)短縮できました。
この結果から、LoAF を使用して INP の原因を特定し、パフォーマンス フェーダーで後続のイールド手法をデプロイすることで、Taboola のパートナーは広告とページのパフォーマンスで最大限の成功を収められることが実証されました。
まとめ
INP の最適化は複雑なプロセスです。特に、パートナーのウェブサイトでサードパーティ スクリプトを使用している場合は複雑になります。最適化を開始する前に、INP を特定のスクリプトに帰属させることで、推測や他のサイト パフォーマンス指標への潜在的な影響を排除できます。LoAF API は、特に埋め込まれたサードパーティの INP の問題を特定して対処するうえで、貴重なツールであることが証明されています。この API を使用することで、ページに存在する他のテクノロジーからの干渉を排除しながら、特定の SDK の改善機会を特定できます。
LoAF は、scheduler.postTask() の使用など、適切なイールド戦略と組み合わせて使用すると、ページの応答性が低い原因を特定して把握するのに役立ちます。これにより、ウェブサイトの INP を改善するために必要な情報を得ることができます。
この作業にご協力いただいた、Google の Gilberto Cocchi、Noam Rosenthal、Rick Viscomi、Taboola のエンジニアリング チームとプロダクト チームの Dedi Hakak、Anat Dagan、Omri Ariav に感謝いたします。