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 adoptar una estrategia de rendimiento inteligente permitió a Taboola mejorar la capacidad de respuesta de los sitios 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 las entradas del usuario. El INP mide el tiempo que transcurre desde que un usuario comienza una interacción (por ejemplo, cuando hace clic, presiona o escribe) hasta la respuesta visual que se genera. INP reemplazará al retraso de primera entrada (FID) como Métrica web esencial en marzo de 2024.

Taboola es la plataforma líder de descubrimiento de contenido del mundo, que ofrece 500,000 recomendaciones por segundo en la Web abierta. Estas recomendaciones permiten que los 9,000 socios publicadores exclusivos de Taboola moneticen sus públicos y generen participación en ellos. Los publicadores renderizan recomendaciones en sus páginas con JavaScript.

Dado que el código JavaScript de terceros puede afectar la capacidad de una página para responder rápidamente a las entradas del usuario, Taboola invirtió mucho en reducir el tamaño de los archivos JavaScript y el tiempo de ejecución. Taboola rediseñó todo su motor de renderización y usa las APIs del navegador directamente sin abstracciones para minimizar su impacto en la INP.

En este caso de éxito, se describe el recorrido de Taboola para mejorar la INP mediante el uso de 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 para mejorar la experiencia del usuario.

TBT como proxy de INP

El tiempo de bloqueo total (TBT) es una métrica basada en el lab 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 la INP, pueden verse afectadas por un TBT alto. Una investigación de Annie Sullivan sobre la correlación entre el TBT y el INP en dispositivos móviles indica que es más probable que los sitios obtengan buenas puntuaciones de INP cuando se minimiza el tiempo de bloqueo del subproceso principal.

Esta correlación, junto con las preocupaciones de los publicadores de Taboola sobre los altos valores de TBT, llevó a Taboola a enfocar su atención en minimizar su contribución a esta métrica.

Captura de pantalla de una auditoría de Lighthouse para el tiempo bloqueado del subproceso principal. Varias secuencias de comandos bloquearon el subproceso principal en total durante 2,630 milisegundos, y el JavaScript de terceros contribuyó con 712 milisegundos a ese tiempo. La secuencia de comandos RELEASE.js de Taboola es responsable de la mayor parte del tiempo de bloqueo de terceros con 691 milisegundos.
Con el motor anterior de Taboola, las secuencias de comandos como RELEASE.js bloquean el subproceso principal durante 691 milisegundos.

Con el uso de TBT como métrica de proxy para INP, Taboola comenzó a supervisar y optimizar el tiempo de ejecución de JavaScript para limitar su posible impacto en las Métricas web esenciales. Para comenzar, hizo lo siguiente:

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

Sin embargo, Taboola notó 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 las fuentes de las 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 causar una demora 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) con el objetivo de comprender mejor su impacto real en la capacidad de respuesta de las entradas del usuario. 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 con éxito la INP sin comprometer ningún KPI de Google Ads ni causar demoras en los recursos de nuestros publicadores.

Cómo usar LoAF para evaluar el impacto de la INP

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

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

El siguiente código JavaScript es una versión simplificada que se usa en producción para recopilar 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ó a Taboola identificar las entradas en las que es un colaborador importante.
  • Taboola se considera un elemento que contribuye de forma importante si Taboola causa más de la mitad de la duración total de la secuencia de comandos o si una secuencia de comandos de Taboola tarda más de 50 milisegundos en ejecutarse.
  • Se genera un firstUIEventTimeStamp si la interacción del usuario se retrasa debido a un fotograma 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 LoAF ayudaron a Taboola a crear la siguiente tabla de atribución, que identifica las áreas en las que puede aplicar oportunidades de rendimiento.

Secuencia de comandos 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 de la secuencia de comandos de LoAF capturadas por la RUM de Taboola

Motor TRECS: 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 cliente extensible de recomendaciones de Taboola) mantiene la renderización del cliente y el código JS actual del publicador, a la vez que reduce la cantidad y el tamaño de los archivos obligatorios necesarios para cargar las recomendaciones de Taboola.

Una vez que se identifican las tareas de bloqueo de renderización con LoAF, el "atenuador de rendimiento" puede dividir esas tareas antes de ceder al subproceso principal con scheduler.postTask(). Este diseño garantiza que el trabajo fundamental para el usuario, como la renderización de actualizaciones, 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:

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

Métricas comerciales

Gracias a LoAF, Taboola pudo comprender mejor su impacto en la INP. La herramienta también destacó las oportunidades de optimización de secuencias de comandos que se podrían usar 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ó la INP en comparación con el motor existente sin generar una secuencia de comandos en un panel de socios publicadores.

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

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

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

Otra ejecución de Lighthouse en el mismo cliente que se destacó anteriormente demuestra una mejora significativa en el tiempo de bloqueo del subproceso principal de Taboola cuando se usa el nuevo motor.

Captura de pantalla de una auditoría de Lighthouse para el tiempo bloqueado del subproceso principal después de aplicar los nuevos motores TRECS y Performance Fader para mejorar el tiempo de bloqueo del subproceso principal. La auditoría se redujo a solo 206 milisegundos, en comparación con los 712 milisegundos anteriores a las optimizaciones.
El nuevo motor de Taboola ayudó a que secuencias de comandos como RELEASE.js reduzcan el TBT en 485 ms (-70%).

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

Conclusión

La optimización de la INP es un proceso complejo, en especial cuando se usan secuencias de comandos de terceros en sitios web de socios. Antes de que pueda comenzar la optimización, la atribución de la 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 los problemas de INP, en particular para los terceros incorporados, ya que les permite identificar sus oportunidades específicas de mejora del SDK y, al mismo tiempo, eliminar la interferencia de otras tecnologías presentes en la página.

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

Agradecemos especialmente 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 Producto de Taboola por su contribución a este trabajo.