Depura el rendimiento en el campo

Aprende a atribuir tus datos de rendimiento con información de depuración para ayudarte a identificar y corregir problemas de usuarios reales con Analytics

Google proporciona dos categorías de herramientas para medir y depurar el rendimiento:

  • Herramientas de laboratorio: Herramientas como Lighthouse, en las que tu página se carga en un entorno simulado que puede imitar varias condiciones (por ejemplo, una red lenta y un dispositivo móvil de gama baja).
  • Herramientas de campo: Herramientas como el Chrome User Experience Report (CrUX), que se basa en datos agregados de usuarios reales de Chrome. (Ten en cuenta que los datos de campo que informan herramientas como PageSpeed Insights y Search Console provienen de los datos de CrUX).

Si bien las herramientas de campo ofrecen datos más precisos (datos que realmente representan lo que experimentan los usuarios reales), las herramientas de laboratorio suelen ser mejores para ayudarte a identificar y corregir problemas.

Los datos de CrUX son más representativos del rendimiento real de tu página, pero es poco probable que conocer tus puntuaciones de CrUX te ayude a descubrir cómo mejorar tu rendimiento.

Por otro lado, Lighthouse identificará los problemas y hará sugerencias específicas para mejorar. Sin embargo, Lighthouse solo hará sugerencias para los problemas de rendimiento que descubra durante el tiempo de carga de la página. No detecta problemas que solo se manifiestan como resultado de la interacción del usuario, como desplazarse o hacer clic en los botones de la página.

Esto plantea una pregunta importante: ¿Cómo puedes capturar información de depuración para las Métricas web esenciales o para otras métricas de rendimiento de usuarios reales en el campo?

En esta publicación, se explicará en detalle qué APIs puedes usar para recopilar información de depuración adicional para cada una de las métricas actuales de Core Web Vitals y se te darán ideas para capturar estos datos en tu herramienta de análisis existente.

APIs para la atribución y la depuración

Cumulative Layout Shift (CLS)

De todas las métricas de Core Web Vitals, el CLS es quizás el que más requiere recopilar información de depuración en el campo. El CLS se mide durante todo el ciclo de vida de la página, por lo que la forma en que un usuario interactúa con ella (hasta dónde se desplaza, en qué hace clic, etcétera) puede tener un impacto significativo en si hay cambios de diseño y qué elementos cambian.

Considera el siguiente informe de PageSpeed Insights:

Un informe de PageSpeed Insights con diferentes valores de CLS
PageSpeed Insights muestra datos de campo y de lab cuando están disponibles, y estos pueden ser diferentes

El valor informado para el CLS del laboratorio (Lighthouse) en comparación con el CLS del campo (datos de CrUX) son bastante diferentes, lo que tiene sentido si se considera que la página puede tener mucho contenido interactivo que no se usa cuando se prueba en Lighthouse.

Sin embargo, incluso si comprendes que la interacción del usuario afecta los datos de campo, debes saber qué elementos de la página se desplazan para obtener una puntuación de 0.28 en el percentil 75. La interfaz LayoutShiftAttribution lo hace posible.

Obtén la atribución de cambios de diseño

La interfaz LayoutShiftAttribution se expone en cada entrada layout-shift que emite la API de Layout Instability.

Para obtener una explicación detallada de ambas interfaces, consulta Cómo depurar cambios de diseño. Para los fines de esta publicación, lo principal que debes saber es que, como desarrollador, puedes observar cada cambio de diseño que se produce en la página, así como los elementos que cambian.

Este es un ejemplo de código que registra cada cambio de diseño, así como los elementos que cambiaron:

new PerformanceObserver((list) => {
  for (const {value, startTime, sources} of list.getEntries()) {
    // Log the shift amount and other entry info.
    console.log('Layout shift:', {value, startTime});
    if (sources) {
      for (const {node, curRect, prevRect} of sources) {
        // Log the elements that shifted.
        console.log('  Shift source:', node, {curRect, prevRect});
      }
    }
  }
}).observe({type: 'layout-shift', buffered: true});

Probablemente no sea práctico medir y enviar datos a tu herramienta de análisis para cada cambio de diseño que se produzca. Sin embargo, si supervisas todos los cambios, puedes hacer un seguimiento de los peores y solo informar sobre ellos.

El objetivo no es identificar y corregir cada cambio de diseño que se produce para cada usuario, sino identificar los cambios que afectan a la mayor cantidad de usuarios y, por lo tanto, contribuyen más al CLS de tu página en el percentil 75.

Además, no es necesario que calcules el elemento de origen más grande cada vez que haya un cambio, sino que solo debes hacerlo cuando estés listo para enviar el valor de CLS a tu herramienta de análisis.

El siguiente código toma una lista de entradas de layout-shift que contribuyeron al CLS y devuelve el elemento fuente más grande del cambio más grande:

function getCLSDebugTarget(entries) {
  const largestEntry = entries.reduce((a, b) => {
    return a && a.value > b.value ? a : b;
  });
  if (largestEntry && largestEntry.sources && largestEntry.sources.length) {
    const largestSource = largestEntry.sources.reduce((a, b) => {
      return a.node && a.previousRect.width * a.previousRect.height >
          b.previousRect.width * b.previousRect.height ? a : b;
    });
    if (largestSource) {
      return largestSource.node;
    }
  }
}

Una vez que hayas identificado el elemento más grande que contribuye al cambio más grande, puedes informarlo a tu herramienta de análisis.

Es probable que el elemento que más contribuya al CLS de una página determinada varíe de un usuario a otro, pero, si agregas esos elementos en todos los usuarios, podrás generar una lista de los elementos cambiantes que afectan a la mayor cantidad de usuarios.

Después de identificar y corregir la causa raíz de los cambios en esos elementos, tu código de Analytics comenzará a registrar cambios más pequeños como los "peores" cambios en tus páginas. Con el tiempo, todos los cambios informados serán lo suficientemente pequeños como para que tus páginas se encuentren dentro del umbral de "bueno" de 0.1.

Otros metadatos que pueden ser útiles para capturar junto con el elemento fuente del mayor cambio son los siguientes:

  • La hora del cambio más grande
  • Es la ruta de URL en el momento del mayor cambio (para los sitios que actualizan la URL de forma dinámica, como las aplicaciones de una sola página).

Largest Contentful Paint (LCP)

Para depurar el LCP en el campo, la información principal que necesitas es qué elemento en particular fue el más grande (el elemento candidato a LCP) para esa carga de página en particular.

Ten en cuenta que es muy posible (de hecho, es bastante común) que el elemento candidato al LCP sea diferente para cada usuario, incluso en la misma página.

Esto puede suceder por varios motivos:

  • Los dispositivos de los usuarios tienen diferentes resoluciones de pantalla, lo que genera diferentes diseños de página y, por lo tanto, diferentes elementos visibles dentro de la ventana gráfica.
  • Los usuarios no siempre cargan las páginas desplazadas hasta la parte superior. A menudo, los vínculos contienen identificadores de fragmentos o incluso fragmentos de texto, lo que significa que es posible que tus páginas se carguen y se muestren en cualquier posición de desplazamiento de la página.
  • El contenido puede personalizarse para el usuario actual, por lo que el elemento candidato al LCP podría variar mucho de un usuario a otro.

Esto significa que no puedes suponer qué elemento o conjunto de elementos será el candidato a LCP más común para una página en particular. Debes medirlo en función del comportamiento de los usuarios reales.

Identifica el elemento candidato al LCP

Para determinar el elemento candidato al LCP en JavaScript, puedes usar la API de Largest Contentful Paint, la misma que usas para determinar el valor del tiempo del LCP.

Cuando observas las entradas de largest-contentful-paint, puedes determinar el elemento candidato actual del LCP observando la propiedad element de la última entrada:

new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lastEntry = entries[entries.length - 1];

  console.log('LCP element:', lastEntry.element);
}).observe({type: 'largest-contentful-paint', buffered: true});

Una vez que conozcas el elemento candidato al LCP, puedes enviarlo a tu herramienta de análisis junto con el valor de la métrica. Al igual que con el CLS, esto te ayudará a identificar qué elementos son más importantes para optimizar primero.

Además del elemento candidato al LCP, también puede ser útil medir los tiempos de las partes secundarias del LCP, que pueden ser útiles para determinar qué pasos de optimización específicos son relevantes para tu sitio.

Interaction to Next Paint (INP)

Los datos más importantes que se deben capturar en el campo para el INP son los siguientes:

  1. Con qué elemento se interactuó
  2. Qué tipo de interacción fue
  3. Cuándo se produjo esa interacción

Una de las principales causas de las interacciones lentas es un subproceso principal bloqueado, lo que puede ser común mientras se carga JavaScript. Saber si la mayoría de las interacciones lentas ocurren durante la carga de la página es útil para determinar qué se debe hacer para solucionar el problema.

La métrica del INP considera la latencia completa de una interacción, incluido el tiempo que se tarda en ejecutar cualquier objeto de escucha de eventos registrado, así como el tiempo que se tarda en pintar el siguiente fotograma después de que se hayan ejecutado todos los objetos de escucha de eventos. Esto significa que, para el INP, es muy útil saber qué elementos objetivo suelen generar interacciones lentas y qué tipos de interacciones son.

En el siguiente código, se registran el elemento objetivo y la hora de la entrada del INP.

function logINPDebugInfo(inpEntry) {
  console.log('INP target element:', inpEntry.target);
  console.log('INP interaction type:', inpEntry.name);
  console.log('INP time:', inpEntry.startTime);
}

Ten en cuenta que este código no muestra cómo determinar qué entrada de event es la entrada del INP, ya que esa lógica es más compleja. Sin embargo, en la siguiente sección, se explica cómo obtener esta información con la biblioteca de JavaScript web-vitals.

Uso con la biblioteca de JavaScript de web-vitals

En las secciones anteriores, se ofrecen algunas sugerencias generales y ejemplos de código para capturar información de depuración que se puede incluir en los datos que envías a tu herramienta de estadísticas.

Desde la versión 3, la biblioteca de JavaScript web-vitals incluye una compilación de atribución que muestra toda esta información, así como algunos indicadores adicionales.

En el siguiente ejemplo de código, se muestra cómo puedes establecer un parámetro del evento adicional (o una dimensión personalizada) que contenga una cadena de depuración útil para identificar la causa raíz de los problemas de rendimiento.

import {onCLS, onINP, onLCP} from 'web-vitals/attribution';

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'CLS':
      eventParams.debug_target = attribution.largestShiftTarget;
      break;
    case 'LCP':
      eventParams.debug_target = attribution.element;
      break;
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      break;
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

Este código es específico de Google Analytics, pero la idea general también debería aplicarse a otras herramientas de análisis.

Este código también muestra cómo generar informes sobre un solo indicador de depuración, pero es útil poder recopilar y generar informes sobre varios indicadores diferentes por métrica.

Por ejemplo, para depurar el INP, es posible que desees recopilar el elemento con el que se interactúa, el tipo de interacción, la hora, el loadState, las fases de interacción y mucho más (como los datos de Long Animation Frame).

La compilación de atribución de web-vitals expone información de atribución adicional, como se muestra en el siguiente ejemplo para el INP:

import {onCLS, onINP, onLCP} from 'web-vitals/attribution';

function sendToGoogleAnalytics({name, value, id, attribution}) {
  const eventParams = {
    metric_value: value,
    metric_id: id,
  }

  switch (name) {
    case 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      eventParams.debug_type = attribution.interactionType;
      eventParams.debug_time = attribution.interactionTime;
      eventParams.debug_load_state = attribution.loadState;
      eventParams.debug_interaction_delay = Math.round(attribution.inputDelay);
      eventParams.debug_processing_duration = Math.round(attribution.processingDuration);
      eventParams.debug_presentation_delay =  Math.round(attribution.presentationDelay);
      break;

    // Additional metric logic...
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

Consulta la documentación sobre la atribución de web-vitals para obtener la lista completa de indicadores de depuración expuestos.

Genera informes y visualiza los datos

Una vez que comiences a recopilar información de depuración junto con los valores de las métricas, el siguiente paso será agregar los datos de todos tus usuarios para comenzar a buscar patrones y tendencias.

Como se mencionó anteriormente, no es necesario que abordes todos los problemas que experimentan tus usuarios. En primer lugar, debes abordar los problemas que afectan a la mayor cantidad de usuarios, que también deberían ser los que tienen el mayor impacto negativo en tus puntuaciones de Core Web Vitals.

En el caso de GA4, consulta el artículo dedicado sobre cómo consultar y visualizar los datos con BigQuery.

Resumen

Esperamos que esta publicación te haya ayudado a describir las formas específicas en que puedes usar las APIs de rendimiento existentes y la biblioteca web-vitals para obtener información de depuración que te ayude a diagnosticar el rendimiento en función de las visitas de usuarios reales en el campo. Si bien esta guía se enfoca en las Core Web Vitals, los conceptos también se aplican a la depuración de cualquier métrica de rendimiento que se pueda medir en JavaScript.

Si eres proveedor de análisis y deseas mejorar tus productos y brindar más información de depuración a tus usuarios, considera algunas de las técnicas que se describen aquí, pero no te limites solo a las ideas que se presentan. Esta publicación está diseñada para ser aplicable de forma general a todas las herramientas de análisis. Sin embargo, es probable que las herramientas de análisis individuales puedan (y deban) capturar y generar informes con aún más información de depuración.

Por último, si crees que hay brechas en tu capacidad para depurar estas métricas debido a la falta de funciones o información en las APIs, envía tus comentarios a web-vitals-feedback@googlegroups.com.