Jak dostawca rekomendacji treści, firma Taboola, użyła LoAF, by zwiększyć wartość INP w witrynach partnerów wydawców nawet o 36%.

Jak dzięki korzystaniu z interfejsu Long Animation Frames API (LoAF) i zastosowanie strategii inteligentnego generowania przychodów Taboola poprawiła responsywność witryn wydawców bez uszczerbku na skuteczność reklam.

David Belford
David Belford

Czas od interakcji do kolejnego wyrenderowania (INP) to dane, które oceniają responsywność witryny na dane wprowadzane przez użytkownika. Czas od interakcji do kolejnego wyrenderowania mierzy czas od momentu, gdy użytkownik rozpoczyna interakcję (np. kliknięcie, dotknięcie lub wpisanie), do momentu wizualnej reakcji. W marcu 2024 r. INP zastąpi opóźnienie przy pierwszym działaniu (FID) jako podstawowy wskaźnik internetowy.

Taboola to największa na świecie platforma do odkrywania treści, która w ogólnodostępnym internecie generuje 500 tys. rekomendacji na sekundę. Dzięki tym rekomendacjom 9000 wydawców będących partnerami firmy Taboola może zarabiać i angażować odbiorców. Wydawcy renderują rekomendacje na swoich stronach za pomocą JavaScriptu.

Ponieważ kod JavaScript firm zewnętrznych może wpływać na szybkość reakcji strony na działania użytkowników, Taboola zainwestowała znaczne środki w zmniejszenie rozmiarów plików JavaScript i czasu ich wykonywania. Aby zminimalizować wpływ na INP, Taboola przeprojektowała cały silnik renderowania, a także zaczęła bezpośrednio korzystać z interfejsów API przeglądarki bez abstrakcji.

Ten przypadek analizy obejmuje działania Taboola zmierzające do poprawy INP za pomocą nowego interfejsu API Long Animation Frames (LoAF) w celu pomiaru wpływu na szybkość wczytywania strony oraz późniejsze próby zastosowania konkretnych optymalizacji w celu poprawy wrażeń użytkownika.

TBT jako serwer proxy INP

Łączny czas blokowania (TBT) to wskaźnik oparty na danych laboratoryjnych, który wskazuje, w którym miejscu wątek główny był zablokowany na tyle długo, że mogło to wpłynąć na szybkość reakcji strony. Na dane dotyczące pól, które mierzą responsywność, np. INP, może mieć wpływ wysoka wartość TBT. Annie Sullivan przeprowadziła badania nad powiązaniem między czasem blokowania wątku głównego (TBT) a wskaźnikiem INP na urządzeniach mobilnych. Wyniki wskazują, że strony mają większe szanse na uzyskanie dobrych wyników INP, gdy czas blokowania wątku głównego jest zminimalizowany.

Ta korelacja oraz obawy wydawców Tabooli związane z wysoką wartością TBT spowodowały, że Taboola skupiła się na minimalizowaniu swojego udziału w tym wskaźniku.

Zrzut ekranu z audytem Lighthouse dotyczącym czasu blokowania wątku głównego Wątek główny był blokowany przez kilka skryptów przez łącznie 2630 ms, z których 712 ms przypadało na kod JavaScript pochodzący od zewnętrznego dostawcy. Skrypt RELEASE.js firmy Taboola odpowiada za większość czasu blokowania przez firmy zewnętrzne (691 ms).
Przy starym silniku Taboola skrypty takie jak RELEASE.js blokują wątek główny przez 691 milisekund.

Taboola zaczęła monitorować i optymalizować czas wykonywania JavaScriptu, używając do tego celu wartości TBT jako przybliżonego pomiaru INP, aby ograniczyć jego potencjalny wpływ na podstawowe wskaźniki internetowe. Na początek:

  • Identyfikowanie i optymalizowanie problematycznych skryptów w polu za pomocą interfejsu Long Tasks API.
  • Oszacowanie udziału w TBT za pomocą interfejsu PageSpeed Insights API do oceny 10 tys. do 15 tys. adresów URL dziennie.

Taboola zauważyła jednak, że analizowanie TBT za pomocą tych narzędzi wiąże się z pewnymi ograniczeniami:

  • Interfejs API Long Tasks nie może przypisać zadania do domeny źródłowej ani do konkretnego skryptu, co utrudnia identyfikację źródeł długich zadań.
  • Interfejs Long Tasks API identyfikuje tylko długie zadania, a nie kombinację zadań i zmian układu, które mogą spowodować opóźnienie renderowania.

Aby rozwiązać te problemy, Taboola wzięła udział w testach źródła Long Animation Frames (LoAF) API, aby lepiej poznać ich rzeczywisty wpływ na szybkość reakcji na dane wprowadzane przez użytkownika. Weryfikacja origin daje dostęp do nowych lub eksperymentalnych funkcji, co pozwala deweloperom testować nowe funkcje, które użytkownicy mogą wypróbować przez ograniczony czas.

Najtrudniejszym aspektem tego wyzwania było zwiększenie skuteczności INP bez obniżania wskaźnika KPI(kluczowego wskaźnika wydajności) reklam lub opóźniania dostępu do zasobów przez wydawców.

Używanie LoAF do oceny wpływu na INP

Długi klatka animacji występuje, gdy aktualizacja renderowania jest opóźniona o więcej niż 50 ms. Dzięki temu, że Taboola zidentyfikowała przyczyny powolnego aktualizowania interfejsu użytkownika, a nie tylko długie zadania, mogła zbadać wpływ tych przyczyn na szybkość działania strony w praktyce. Obserwowanie LoAF umożliwiło Tabooli:

  1. przypisywanie wpisów do konkretnych zadań Taboola;
  2. Obserwowanie problemów z wydajnością w przypadku konkretnych funkcji przed wdrożeniem ich w produkcji.
  3. Zbieraj zbiorcze dane, aby porównywać różne wersje kodu w testach A/B i tworzyć raporty o kluczowych wskaźnikach sukcesu.

Ten kod JavaScript to uproszczona wersja kodu używanego w wersji produkcyjnej do zbierania danych LoAF, aby wyodrębnić wpływ 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 });
  • Dzięki funkcji loafEntryAnalysis Taboola mogła zidentyfikować wpisy, w których jest głównym współtwórcą.
  • Taboola jest uznawana za główne źródło, jeśli ponad połowa łącznego czasu trwania skryptu jest spowodowana przez Taboola lub jeśli wykonanie skryptu Taboola zajmuje więcej niż 50 milisekund.
  • Jeśli interakcja użytkownika jest opóźniona z powodu długiego kadru animacji, generowany jest firstUIEventTimeStamp. Najdłuższy czas blokowania jest uznawany za ogólny wynik INP. Możemy też określić, kiedy Taboola wywołała firstUIEventTimeStamp, aby obliczyć wynik INP Taboola.

Dane zebrane za pomocą LoAF pomogły firmie Taboola utworzyć poniższą tabelę atrybucji, która wskazuje obszary, w których można stosować opłacalne możliwości.

Skrypt Czas trwania (milisekundy)
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
Wpisy skryptu LoAF zarejestrowane przez Taboola RUM

TRECS Engine: nowa strategia uzyskiwania zysków

Oprócz korzystania z LoAF do lepszego poznawania możliwości optymalizacji skryptów Taboola przeprojektowała cały mechanizm renderowania, aby znacznie zminimalizować czas wykonywania i blokowania kodu JavaScript.

TRECS (Taboola Recommendations Extensible Client Service) obsługuje renderowanie po stronie klienta i aktualny kod JS wydawcy, a zarazem zmniejsza liczbę i rozmiar plików wymaganych do wczytania rekomendacji Taboola.

Gdy zadania blokujące renderowanie zostaną zidentyfikowane za pomocą LoAF, „Performance Fader” może je podzielić, a potem przekazać do wątku głównego za pomocą scheduler.postTask(). Dzięki temu ważne zadania związane z użytkownikiem, takie jak renderowanie aktualizacji, mogą być wykonywane możliwie najszybciej, niezależnie od tego, jakie zadania mogą być wykonywane w głównym wątku.

Oto fragment kodu JS wykonawcy zadania „Performance Fader”:

/**
* 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);
}

Funkcja sendTaskToFader:

  • Używa interfejsu runAsPostTask, który korzysta z interfejsu scheduler.postTask() (jeśli jest dostępny), lub używa setTimeout.
  • Ta funkcja otacza wywołania funkcji w sekcjach kodu, które powodują długie klatki animacji i INP. Dzieli te sekcje kodu na krótsze zadania, co zmniejsza INP.

Dane biznesowe

Dzięki LoAF Taboola mogła lepiej poznać wpływ na INP. Narzędzie wskazało też możliwości optymalizacji skryptu, które można wykorzystać w ramach nowego mechanizmu TRECS.

Aby określić wpływ TRECS i Performance Fader, Taboola przeprowadziła test A/B, w którym zmierzono INP w porównaniu z dotychczasowym silnikiem bez skryptu na panelu partnerów wydawców.

W tabeli poniżej podano wyniki INP w milisekundach w 75. percentylu dla 4 anonimowych wydawców w sieci Taboola.

Wydawcy INP z TRECS + Performance Fader INP z obecnym silnikiem Spadek INP (%)
Wydawca A 48 75 36%
Wydawca B 153 163 6%
Wydawca C 92 135 33%
Wydawca D 37 52 29%

Na szczęście, gdy w panelu testowym włączono TRECS i Performance Fader, dane biznesowe,takie jak współczynnik klikalności reklamy i przychody z 1000 wyświetleń (RPM), nie uległy pogorszeniu. Dzięki tej pozytywnej poprawie INP bez żadnych negatywnych skutków w przypadku wskaźników KPI reklam Taboola będzie stopniowo poprawiać postrzeganie swojego produktu przez wydawców.

Kolejne uruchomienie Lighthouse w przypadku tego samego klienta, który został wcześniej wyróżniony, pokazuje znaczną poprawę czasu blokowania głównego wątku przez Taboola po zastosowaniu nowego mechanizmu.

Zrzut ekranu z audytem Lighthouse dotyczącym czasu blokowania wątku głównego po zastosowaniu nowych mechanizmów TRECS i Performance Fader w celu skrócenia czasu blokowania wątku głównego Czas wykonania audytu skrócił się do zaledwie 206 milisekund w porównaniu z 712 milisekundami przed optymalizacją.
Nowy mechanizm Taboola pomógł skryptom takim jak RELEASE.js zmniejszyć TBT o 485 ms (-70%).

Pokazuje to, że korzystanie z LoAF do identyfikowania przyczyn INP i wdrażanie kolejnych technik Yielding za pomocą Performance Fader umożliwia partnerom Taboola osiąganie maksymalnej skuteczności reklam i wydajności stron.

Podsumowanie

Optymalizacja INP jest złożonym procesem, zwłaszcza gdy w witrynach partnerów są używane skrypty innych firm. Przed rozpoczęciem optymalizacji przypisanie INP do konkretnych skryptów eliminuje konieczność zgadywania i potencjalne uszkodzenia innych danych dotyczących wydajności witryny.Interfejs LoAF API okazał się przydatnym narzędziem do identyfikowania i rozwiązywania problemów z INPs, zwłaszcza w przypadku wbudowanych aplikacji innych firm, ponieważ pozwala on wskazywać konkretne możliwości ulepszenia SDK, eliminując przy tym zakłócenia powodowane przez inne technologie obecne na stronie.

W połączeniu z dobrą strategią dotyczącą uzyskiwania wyników, np. z użyciem scheduler.postTask(), LoAF może pomóc w obserwowaniu i rozumieniu przyczyny słabej responsywności strony, co z kolei dostarcza informacji potrzebnych do poprawy INP witryny.

Szczególne podziękowania należą się Gilberto Cocchi, Noam Rosenthal i Rickowi Viscomi z Google oraz Dedi Hakak, Anat Dagan i Omri Ariav z zespołu ds. inżynierii i produktu Taboola za ich wkład w realizację tego projektu.