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. INP mierzy czas od momentu, gdy użytkownik rozpoczyna interakcję (np. kliknięcie, dotknięcie lub wpisanie czegoś), do momentu, gdy otrzyma wizualną informację zwrotną. 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 Taboola może zarabiać i angażować odbiorców. Wydawcy renderują rekomendacje na swoich stronach za pomocą JavaScriptu.

Skrypty JavaScript innych firm mogą wpływać na zdolność strony do szybkiego reagowania na dane wejściowe użytkownika, dlatego firma Taboola intensywnie pracuje nad zmniejszeniem rozmiaru plików JavaScript i czasu wykonywania działań. Aby zminimalizować wpływ na INP, firma Taboola przeprojektowała cały silnik renderowania i korzystała bezpośrednio z interfejsów API przeglądarki bez żadnych abstrakcyjnych elementów.

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 responsywność strony w praktyce oraz późniejsze próby zastosowania konkretnych optymalizacji w celu poprawy komfortu użytkowników.

TBT jako serwer proxy INP

Całkowity czas blokowania (TBT) to dane oparte na laboratoriach, które identyfikują, gdzie wątek główny był zablokowany na wystarczająco długo, aby prawdopodobnie wpłynąć na responsywność stron. 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 czym 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.

Wykorzystując TBT jako wskaźnik pośredniczący dla INP, firma Taboola zaczęła monitorować i optymalizować czas wykonywania JavaScriptu, aby ograniczyć jego potencjalny wpływ na podstawowe wskaźniki internetowe. Na początek:

  • Zidentyfikować i zoptymalizować problematyczne skrypty w polu przy użyciu interfejsu Long Tasks API.
  • Szacowanie udziału w TBT przy użyciu interfejsu PageSpeed Insights API do oceny 10–15 tys. adresów URL dziennie.

Firma Taboola zauważyła jednak, że analizowanie TBT za pomocą tych narzędzi niesie ze sobą pewne ograniczenia:

  • 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.

Trzeba wyraźnie podkreślić, że najtrudniejszym aspektem tego wyzwania było pomyślne ulepszenie wartości INP bez negatywnego wpływu na KPI Google Ads(kluczowego wskaźnika wydajności) i opóźnienia w korzystaniu z zasobów naszych wydawców.

Używanie LoAF do oceny wpływu INP

Długa animacja występuje, gdy aktualizacja renderowania jest opóźniona o ponad 50 ms. Dzięki temu, że Taboola zidentyfikowała przyczyny powolnego aktualizowania interfejsu użytkownika, a nie tylko długie zadania, mogła przeanalizować wpływ na szybkość działania strony w praktyce. Obserwowanie LoAF pozwoliło Tabooli:

  1. Przypisz wpisy do określonych zadań Taboola.
  2. Obserwowanie problemów z wydajnością w konkretnych funkcjach przed wdrożeniem ich w środowisku produkcyjnym.
  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ólną ocenę 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 wykorzystania LoAF do lepszego zrozumienia możliwości optymalizacji skryptów Taboola przeprojektowała cały mechanizm renderowania, aby znacznie zminimalizować czas wykonywania i blokowania obsługi JavaScriptu.

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 następnie przekazać do wątku głównego za pomocą scheduler.postTask(). Taka konstrukcja daje pewność, że kluczowe zadania wykonywane przez użytkowników (takie jak aktualizacje renderowania) będą mogły zostać wykonane jak najszybciej, niezależnie od wszelkich istniejących zadań, które zajmują główny wątek.

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 korzysta z interfejsu 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 włączenie TRECS i suwaka skuteczności w panelu testowym nie wpłynęło negatywnie na dane biznesowe, takie jak współczynnik klikalności reklamy i przychody na 1000 wyświetleń (RPM). 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 na tym samym kliencie, który został wyróżniony wcześniej, pokazuje znaczną poprawę czasu blokowania głównego wątku przez Taboola przy użyciu nowego silnika.

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 wprowadzeniem optymalizacji.
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 strony.

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ą zysku, np. z zasadą scheduler.postTask(), LoAF może pomóc w zaobserwowaniu i zrozumieniu przyczyn słabej responsywności stron, co z kolei dostarcza informacji potrzebnych do poprawy wskaźnika INP witryny.

Szczególne podziękowania dla Gilberto Cocchiego, Noama Rosenthala i Ricka Viscomi z Google oraz Dedi Hakaka, Anat Dagana i Omriego Ariava z zespołu ds. inżynierii i produktu Taboola za ich wkład w realizację tego projektu.