Cómo Taboola, un proveedor de recomendaciones de contenido, usó la LoAF para mejorar el INP en hasta un 36% para los sitios web de sus socios editores.

Cómo aprovechar la API de Long Animation Frames (LoAF) y la adopción de una estrategia de rendimiento inteligente permitió a Taboola mejorar la capacidad de respuesta del sitio web de los publicadores sin comprometer el rendimiento de los anuncios.

David Belford
David Belford

Interaction to Next Paint (INP) es una métrica que evalúa la capacidad de respuesta de un sitio web ante la entrada del usuario. INP mide el tiempo que transcurre desde que un usuario comienza una interacción (como cuando hace clic, presiona o escribe) hasta el resultado visual. El INP deberá reemplazar el retraso de primera entrada (FID) como Métrica web esencial en marzo de 2024.

Taboola es la plataforma de descubrimiento de contenido líder en el mundo, que brinda 500,000 recomendaciones por segundo en la Web abierta. Estas recomendaciones permiten que los 9,000 socios publicadores exclusivos de Taboola puedan monetizar y atraer a su público. Los publicadores renderizan las recomendaciones en sus páginas con JavaScript.

Debido a que el JavaScript de terceros puede afectar la capacidad de una página para responder rápidamente a la entrada del usuario, Taboola se ha invertido fuertemente en reducir los tamaños de los archivos JavaScript y el tiempo de ejecución. Taboola ha rediseñado todo su motor de representación, así como mediante el uso directo de API de navegador sin abstracciones para minimizar su impacto en INP.

Este caso práctico abarca el recorrido de Taboola para mejorar el INP utilizando la nueva API de Long Animation Frames (LoAF) para medir su impacto en la capacidad de respuesta de la página en el campo, y los esfuerzos posteriores para aplicar optimizaciones específicas a fin de mejorar la experiencia del usuario.

TBT como proxy del INP

El tiempo de bloqueo total (TBT) es una métrica basada en labs que identifica dónde se bloqueó el subproceso principal durante el tiempo suficiente como para afectar la capacidad de respuesta de la página. Las métricas de campo que miden la capacidad de respuesta, como INP, pueden verse afectadas por una TBT alta. Una investigación de Annie Sullivan sobre la correlación entre INP y TBT en dispositivos móviles indica que los sitios tienen más probabilidades de lograr buenas puntuaciones de INP cuando se minimiza el tiempo de bloqueo del subproceso principal.

Esta correlación, combinada con las preocupaciones de los editores de Taboola respecto a la alta TBT, llevó a Taboola a centrar su atención en minimizar su contribución a esta métrica.

Captura de pantalla de una auditoría de Lighthouse para el tiempo del subproceso principal bloqueado. Varias secuencias de comandos bloquearon el subproceso principal en total durante 2630 milisegundos. Hasta ese momento, JavaScript de terceros contribuyó 712 milisegundos. El script Release.js de Taboola es responsable de la mayor parte del tiempo de bloqueo por parte de terceros a 691 milisegundos.
Con el antiguo motor de Taboola, las secuencias de comandos como RELEASE.js bloquean el subproceso principal durante 691 milisegundos.

Usando TBT como métrica proxy para INP, Taboola comenzó a supervisar y optimizar el tiempo de ejecución de JavaScript para limitar su impacto potencial en las Métricas web esenciales. Comenzaron haciendo lo siguiente:

  • Identifica y optimiza las secuencias de comandos problemáticas en el campo con la API de Long Tasks.
  • Estimar las contribuciones TBT usando la API de PageSpeed Insights para evaluar entre 10,000 y 15,000 URLs por día

Sin embargo, Taboola observó que analizar la TBT con estas herramientas tenía algunas limitaciones:

  • La API de Long Tasks no puede atribuir la tarea al dominio de origen ni a una secuencia de comandos en particular, lo que dificulta la identificación de fuentes de tareas largas.
  • La API de Long Tasks solo identifica tareas largas, en lugar de una combinación de tareas y cambios de diseño que podrían provocar un retraso en la renderización.

Para abordar estos desafíos, Taboola se unió a la prueba de origen de la API de Long Animation Frames (LoAF) para comprender mejor su impacto real en la capacidad de respuesta de las entradas de los usuarios. Las pruebas de origen brindan acceso a funciones nuevas o experimentales, lo que permite a los desarrolladores probar funciones emergentes que sus usuarios pueden probar por un tiempo limitado.

Es fundamental destacar que el aspecto más difícil de este desafío fue mejorar el INP de forma exitosa sin comprometer ningún KPI de Google Ads(indicador clave de rendimiento) ni causar retrasos en los recursos para nuestros publicadores.

Uso de la LoAF para evaluar el impacto del INP

Un fotograma de animación largo se produce cuando una actualización de renderización se retrasa más de 50 milisegundos. Mediante la identificación de las causas de las actualizaciones lentas de la interfaz de usuario, en lugar de las tareas largas por sí solas, Taboola pudo analizar su impacto en la capacidad de respuesta de la página en el campo. La observación de la LoAF le permitió a Taboola hacer lo siguiente:

  1. Atribuye las entradas a tareas de Taboola específicas.
  2. Observa los problemas de rendimiento en funciones específicas antes de implementarlas en producción.
  3. Recopila datos agregados para comparar diferentes versiones de código en pruebas A/B y genera informes sobre métricas de éxito clave.

El siguiente JavaScript es una versión simplificada que se utiliza en la producción para recopilar la LoAF y aislar el impacto de 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 });
  • El uso de la función loafEntryAnalysis permitió que Taboola identificara las entradas en las que es un colaborador importante.
  • El taboola se considera un colaborador principal si más de la mitad de la duración total del guion se debe a taboola o si un guion de Taboola tarda más de 50 milisegundos en ejecutarse.
  • Se genera un firstUIEventTimeStamp si se retrasa la interacción del usuario debido a un marco de animación largo. La duración de bloqueo más larga se considera la puntuación general de INP. También podemos identificar cuándo Taboola activó un firstUIEventTimeStamp para calcular una puntuación de INP de Taboola.

Los datos recopilados con la LOAF ayudaron a Taboola a crear la siguiente tabla de atribución, que identifica las áreas en las que puede aplicar oportunidades de producción.

Script Duración (milisegundos)
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
Entradas del guion de la LOAF capturadas por Taboola RUM

TRECS Engine: la nueva estrategia de rendimiento

Además de usar LoAF para comprender mejor las oportunidades de optimización de secuencias de comandos, Taboola rediseñó todo su motor de renderización para minimizar significativamente la ejecución de JavaScript y el tiempo de bloqueo.

TRECS (servicio extensible para clientes de Taboola Recomendaciones) mantiene la renderización del cliente y el código JS actual del editor, al mismo tiempo que reduce la cantidad y el tamaño de los archivos obligatorios necesarios para cargar las recomendaciones de Taboola.

Una vez que se hayan identificado las tareas que bloquean la renderización con la LOAF, el " atenuador de rendimiento" puede dividir esas tareas antes de cederlas al subproceso principal mediante scheduler.postTask(). Este diseño garantiza que el trabajo crucial para el usuario, como las actualizaciones de renderización, se pueda ejecutar lo antes posible, independientemente de las tareas existentes que puedan ocupar el subproceso principal.

Este es el fragmento de JS del ejecutor de tareas "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);
}

La función sendTaskToFader realiza lo siguiente:

  • Utiliza runAsPostTask, que usa scheduler.postTask() de forma interna (si la API está disponible), o recurre a setTimeout.
  • Esta función une las llamadas a funciones en las secciones de código que causan INP y marcos de animación largos. Divide estas secciones de código en tareas más cortas y, por lo tanto, reduce el INP.

Métricas empresariales

Gracias a la LoAF, Taboola pudo comprender mejor su impacto en el INP. La herramienta también destacó oportunidades de optimización de secuencias de comandos que se podrían utilizar como parte del nuevo motor TRECS.

Para determinar el impacto de TRECS y el atenuador de rendimiento, Taboola realizó una prueba A/B que midió el INP en comparación con el motor existente sin generación de secuencias de comandos en un panel de socios editores.

En la siguiente tabla, se muestran los resultados de INP en milisegundos en el percentil 75 de cuatro editores anónimos en la red Taboola.

Publicadores INP con TRECS y atenuador de rendimiento INP con el motor existente Disminución del INP (%)
Publicador A 48 75 36%
Publicador B 153 163 6%
Publicador C 92 135 33%
Publicador D 37 52. 29%

Afortunadamente, las métricas comerciales, como la tasa de clics en el anuncio y los ingresos por cada 1,000 impresiones (RPM), no se vieron afectadas negativamente cuando TRECS y el atenuador de rendimiento se habilitaron en el panel de prueba. Con esta mejora positiva en el INP sin ningún resultado negativo como se esperaba en los KPIs de los anuncios, Taboola mejorará gradualmente la percepción de sus publicadores sobre su producto.

Otro Lighthouse ejecutado en el mismo cliente destacado anteriormente demuestra una mejora significativa en el tiempo de bloqueo del subproceso principal por parte de Taboola al usar el nuevo motor.

Captura de pantalla de una auditoría de Lighthouse para el tiempo de bloqueo del subproceso principal después de que se aplicaron los nuevos TRECS y los nuevos motores de atenuador de rendimiento para mejorar el tiempo de bloqueo del subproceso principal. La auditoría se redujo a solo 206 milisegundos, en comparación con los 712 que se habían obtenido antes de las optimizaciones.
El nuevo motor de Taboola ayudó a secuencias de comandos como RELEASE.js a reducir la TBT en 485 ms (-70%).

Esto demuestra que usar LoAF para identificar las causas de INP y también implementar las técnicas de rendimiento posteriores con el atenuador de rendimiento permite a los socios de Taboola alcanzar el máximo éxito en el rendimiento de anuncios y páginas.

Conclusión

La optimización de INP es un proceso complejo, especialmente cuando se utilizan secuencias de comandos de terceros en sitios web asociados. Antes de que comience la optimización, la atribución de INP a secuencias de comandos específicas elimina cualquier conjetura y posible daño a otras métricas de rendimiento del sitio.La API de LoAF demostró ser una herramienta valiosa para identificar y abordar problemas de INP, particularmente para terceros incorporados, ya que les permite identificar sus oportunidades de mejora de SDK específicas y eliminar la interferencia de otras tecnologías presentes en la página.

Cuando se combina con una buena estrategia de rendimiento, como scheduler.postTask(), LoAF puede ayudarte a observar y comprender la causa de la baja capacidad de respuesta de una página, lo que, a su vez, te brinda la información que necesitas para mejorar el INP de tu sitio web.

Queremos dar un agradecimiento especial a Gilberto Cocchi, Noam Rosenthal y Rick Viscomi de Google, y a Dedi Hakak, Anat Dagan y Omri Ariav del equipo de Ingeniería y Productos de Taboola por su contribución a este trabajo.