Depura el rendimiento en el campo

Obtén información para atribuir tus datos de rendimiento con información de depuración para ayudarte a identificar y corregir problemas de usuarios reales con las estadísticas

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

  • Herramientas de lab: 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 Informe sobre la experiencia del usuario en Chrome (CrUX), que se basa en datos agregados de usuarios reales de Chrome. (Ten en cuenta que los datos de campo que registran herramientas como PageSpeed Insights y Search Console provienen de los datos de CrUX).

Si bien las herramientas de campo ofrecen datos más precisos, que representan lo que experimentan los usuarios reales, las herramientas de lab suelen ser más útiles para identificar y solucionar 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.

Lighthouse, por otro lado, identificará problemas y hará sugerencias específicas para mejorar. Sin embargo, Lighthouse solo hará sugerencias para los problemas de rendimiento que detecte 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 botones de la página.

Esto plantea una pregunta importante: ¿cómo puedes capturar información de depuración de las Métricas web esenciales o de 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 las Métricas web esenciales y te brindará ideas para capturar estos datos en tu herramienta de estadísticas existente.

APIs para la atribución y la depuración

Cumulative Layout Shift (CLS)

De todas las métricas de las Métricas web esenciales, CLS es quizás la que requiere más 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 en qué elementos se producen.

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) es bastante diferente, y esto tiene sentido si consideras 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 cambian para obtener una puntuación de 0.28 en el percentil 75. La interfaz LayoutShiftAttribution lo hace posible.

Obtén la atribución de cambio 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 Cambios de diseño de depuración. A los efectos 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 se desplazan.

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

Es probable que no sea práctico medir y enviar datos a tu herramienta de estadísticas para cada cambio de diseño que se produce. Sin embargo, si supervisas todos los cambios, puedes hacer un seguimiento de los peores y solo informar información sobre ellos.

El objetivo no es identificar y corregir cada cambio de diseño que ocurre 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. Solo debes hacerlo cuando tengas todo listo para enviar el valor de CLS a tu herramienta de estadísticas.

El siguiente código toma una lista de entradas layout-shift que contribuyeron a CLS y muestra el elemento de origen 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 estadísticas.

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 a todos los usuarios, podrás generar una lista de elementos cambiantes que afectan a la mayor cantidad de usuarios.

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

Estos son otros metadatos que pueden ser útiles para capturar junto con el elemento fuente de cambio más grande:

  • La hora del cambio más grande
  • Es la ruta de URL en el momento del cambio más grande (para 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 de 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 de la LCP sea diferente de un usuario a otro, incluso para 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 del viewport.
  • Los usuarios no siempre cargan páginas que se desplazaron 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 de la LCP podría variar mucho de un usuario a otro.

Esto significa que no puedes suponer qué elemento o conjunto de elementos será el elemento candidato de 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 de LCP

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

Cuando observas las entradas de largest-contentful-paint, puedes determinar el elemento candidato de LCP actual si observas 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 de la 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 cuáles son los elementos más importantes para optimizar primero.

Además del elemento candidato de la LCP, también puede ser útil medir los tiempos de las subpartes de la 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 de INP son los siguientes:

  1. Con qué elemento se interactuó
  2. Tipo de interacción
  3. Cuándo ocurrió esa interacción

Una de las principales causas de las interacciones lentas es un subproceso principal bloqueado, 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 INP considera la latencia completa de una interacción, incluido el tiempo que tarda en ejecutarse cualquier objeto de escucha de eventos registrado, así como el tiempo que tarda en pintarse el siguiente fotograma después de que se ejecutaron todos los objetos de escucha de eventos. Esto significa que, para la INP, es muy útil saber qué elementos objetivo suelen generar interacciones lentas y qué tipos de interacciones son.

El siguiente código registra el elemento de destino y la hora de la entrada de 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 de 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 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 incluirá en los datos que envíes 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 y algunos indicadores adicionales.

En el siguiente ejemplo de código, se muestra cómo puedes establecer un parámetro de evento adicional (o una dimensión personalizada) que contenga una cadena de depuración útil para ayudar a 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 estadísticas.

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 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 fotogramas de animación largos).

La compilación de atribución web-vitals expone información de atribución adicional, como se muestra en el siguiente ejemplo de 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 de 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 hayas comenzado a recopilar información de depuración junto con los valores de las métricas, el siguiente paso es 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 encuentran los usuarios. Debes abordar, especialmente al principio, 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 métricas principales de la Web.

En el caso de GA4, consulta el artículo específico 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 las 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 Métricas web esenciales, los conceptos también se aplican a la depuración de cualquier métrica de rendimiento que se pueda medir en JavaScript.

Si estás empezando a medir el rendimiento y ya eres usuario de Google Analytics, la herramienta Informe de métricas web esenciales puede ser un buen lugar para comenzar, ya que ya admite la información de depuración de informes para las métricas de Métricas web esenciales.

Si eres proveedor de análisis y deseas mejorar tus productos y proporcionar más información de depuración a tus usuarios, considera algunas de las técnicas que se describen aquí, pero no te limites a solo las ideas que se presentan aquí. El objetivo de esta publicación es que se aplique de forma general a todas las herramientas de estadísticas. Sin embargo, es probable que las herramientas de estadísticas individuales puedan (y deban) capturar e informar aún más información de depuración.

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