Depura el rendimiento en el campo

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

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

  • Herramientas del lab: Herramientas como Lighthouse, en la que tu página se carga en un entorno simulado que puede imitar varias condiciones (por ejemplo, una red lento y un dispositivo móvil de baja gama).
  • 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 informan herramientas como PageSpeed Insights y Search Console provienen de datos de CrUX.

Si bien las herramientas de campo ofrecen datos más precisos (datos que realmente representan la experiencia de los usuarios reales), las herramientas de lab suelen ser mejores para ayudarte a 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 cuando se cargue 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 genera una pregunta importante: ¿Cómo puedes capturar información de depuración para las Métricas web esenciales y 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 de 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 estadísticas existente.

APIs para atribución y depuración

Cambio de diseño acumulado (CLS)

De todas las métricas de las Métricas web esenciales, CLS es quizás la más importante para recopilar información de depuración en el campo. CLS se mide a lo largo de toda la vida útil de la página, por lo que la forma en que un usuario interactúa con la página (qué tan lejos se desplaza, en qué hace clic, etc.) puede tener un impacto significativo sobre si hay cambios de diseño y qué elementos.

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 pueden ser diferentes

El valor que se informó para CLS en el lab (Lighthouse) en comparación con el CLS desde el 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 del campo, debes saber qué elementos de la página están cambiando para dar como resultado una puntuación de 0.28 en el percentil 75. Eso es posible gracias a la interfaz de LayoutShiftAttribution.

Cómo obtener la atribución de cambio de diseño

La interfaz de LayoutShiftAttribution se expone en cada entrada de layout-shift que emite la API de inestabilidad de diseño.

Para obtener una explicación detallada de ambas interfaces, consulta Cómo depurar cambios de diseño. A los fines de esta entrada, lo más importante que debes saber es que, como desarrollador, puedes observar todos los cambios de diseño que ocurren en la página, así como los elementos que cambian.

A continuación, se muestra un código de ejemplo que registra cada cambio de diseño y 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 ocurra. Sin embargo, si supervisas todos los cambios, puedes hacer un seguimiento de los peores cambios y solo informar información sobre ellos.

El objetivo no es identificar y corregir todos los cambios de diseño que se producen para todos los usuarios, 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 necesitas procesar el elemento de origen más grande cada vez que se produce 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 las 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 contribuye a CLS para 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.

Una vez que hayas identificado y corregido la causa raíz de los cambios de esos elementos, tu código de estadísticas 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 de "bueno" de 0.1.

Estos son algunos otros metadatos que pueden ser útiles para capturar junto con el elemento de origen del 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).

Procesamiento de imagen con contenido más grande (LCP)

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

Ten en cuenta que es posible (de hecho, es bastante común) que el elemento candidato de 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 distintos diseños de página y, por lo tanto, diferentes elementos son visibles dentro del viewport.
  • Los usuarios no siempre cargan 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 tus páginas se pueden cargar y mostrar en cualquier posición de desplazamiento.
  • Se puede personalizar el contenido para el usuario actual, por lo que el elemento candidato de LCP puede variar ampliamente de un usuario a otro.

Esto significa que no puedes hacer suposiciones sobre qué elemento o conjunto de elementos será el elemento candidato de LCP más común para una página en particular. Debes medirlo según el comportamiento del usuario real.

Identifica el elemento candidato de LCP

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

Cuando observas entradas 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 LCP, puedes enviarlo a tu herramienta de estadísticas junto con el valor de la métrica. Al igual que con CLS, esto te ayudará a identificar qué elementos es más importante optimizar primero.

Además del elemento candidato de LCP, también podría ser útil medir los tiempos de las subpartes de LCP, que pueden servir para determinar qué pasos de optimización específicos son relevantes para tu sitio.

Interacción con el siguiente procesamiento de imagen (INP)

Los fragmentos más importantes de información que se deben capturar en el campo para el INP son los siguientes:

  1. Con qué elemento se interactuó
  2. ¿Por qué fue el tipo de interacción?
  3. Cuándo ocurrió esa interacción

Una de las principales causas de las interacciones lentas es el bloqueo de un subproceso principal, 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 ejecutar cualquier objeto de escucha de eventos registrado, así como el tiempo que lleva pintar el siguiente fotograma después de que se ejecutan todos los objetos de escucha de eventos. Esto significa que, para INP, es realmente útil saber qué elementos objetivo tienden a dar como resultado interacciones lentas y qué tipos de interacciones son.

El siguiente código registra el elemento objetivo 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 event es la entrada 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 a fin de incluirla en los datos que envías a tu herramienta de estadísticas.

A partir de la versión 3, la biblioteca de JavaScript web-vitals incluye una compilación de atribución que muestra toda esta información, además de algunos indicadores adicionales.

En el siguiente ejemplo de código, se muestra cómo podrías configurar 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);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

Este código es específico de Google Analytics, pero la idea general también debería traducirse en 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 también informar 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, el tiempo, el loadState, las fases de interacción y mucho más (como los datos de Long Animation Frame).

La compilación de atribución web-vitals expone información de atribución adicional, como se muestra en el siguiente ejemplo para 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);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

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

Informar y visualizar los datos

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

Como se mencionó antes, no es necesario que abordes todos los problemas que encuentran los usuarios, pero 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 web esenciales.

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

Resumen

Esperamos que esta publicación 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 y diagnosticar el rendimiento en función de las visitas de usuarios reales en el campo. Si bien esta guía se centra 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 recién comienzas a medir el rendimiento y ya eres usuario de Google Analytics, la herramienta del informe de Métricas web puede ser un buen punto de partida, ya que admite los informes de información de depuración para las métricas esenciales de Web Vitals.

Si eres proveedor de estadísticas y quieres mejorar tus productos y proporcionar más información de depuración a tus usuarios, ten en cuenta algunas de las técnicas que se describen aquí, pero no te limites solo a las ideas que se presentan aquí. El objetivo de esta entrada es que se pueda aplicar en general a todas las herramientas de estadísticas. Sin embargo, es probable que las herramientas de estadísticas individuales puedan (y deben) capturar y enviar 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 información o funciones faltantes en las APIs, envía tus comentarios a web-vitals-feedback@googlegroups.com.