Prestazioni del debug sul campo

Scopri come attribuire i dati sul rendimento con le informazioni di debug per identificare e risolvere i problemi degli utenti reali

Google offre due categorie di strumenti per misurare il rendimento ed eseguirne il debug:

  • Strumenti di Labs: strumenti come Lighthouse, in cui la pagina viene caricata in un ambiente simulato in grado di simulare varie condizioni, ad esempio una rete lenta e un dispositivo mobile di fascia bassa.
  • Strumenti sul campo: strumenti come il Report sull'esperienza utente di Chrome (CrUX), che si basa su dati aggregati e reali relativi a utenti di Chrome. Tieni presente che i dati sul campo riportati da strumenti come PageSpeed Insights e Search Console provengono dai dati di CrUX.

Mentre gli strumenti sul campo offrono dati più accurati, che in realtà rappresentano l'esperienza utente reale, gli strumenti di lab sono spesso migliori nell'aiutarti a identificare e risolvere i problemi.

I dati CrUX sono più rappresentativi del rendimento reale della tua pagina, ma è improbabile che conoscere i tuoi punteggi CrUX ti aiuti a capire come migliorare il rendimento.

Lighthouse, invece, identificherà i problemi e fornirà suggerimenti specifici per migliorarli. Tuttavia, Lighthouse fornisce suggerimenti solo per i problemi di prestazioni rilevati al momento del caricamento della pagina. Non rileva i problemi che si manifestano solo a seguito di un'interazione dell'utente, ad esempio lo scorrimento o il clic sui pulsanti nella pagina.

Ciò solleva un'importante domanda: come è possibile acquisire informazioni di debug per Segnali web essenziali o altre metriche sulle prestazioni di utenti reali del settore?

Questo post spiegherà nel dettaglio quali API puoi utilizzare per raccogliere ulteriori informazioni di debug per ciascuna delle attuali metriche di Segnali web essenziali e ti offrirà idee su come acquisire questi dati nel tuo strumento di analisi esistente.

API per l'attribuzione e il debug

CLS

Di tutte le metriche di Segnali web essenziali, CLS è forse quella per cui la raccolta di informazioni di debug sul campo è più importante. La metrica CLS viene misurata durante l'intera durata della pagina, pertanto il modo in cui un utente interagisce con la pagina, ovvero quanto scorre, su quali elementi fa clic e così via, può avere un impatto significativo sull'eventuale presenza di variazioni del layout e sugli elementi che stanno cambiando.

Prendi in considerazione il seguente report di PageSpeed Insights:

Un report PageSpeed Insights con diversi valori CLS

Il valore riportato per il CLS del lab (Lighthouse) rispetto al CLS del campo (dati CrUX) è piuttosto diverso e questo ha senso se si considera che la pagina potrebbe avere molti contenuti interattivi che non vengono utilizzati durante il test in Lighthouse.

Tuttavia, anche se sai che l'interazione dell'utente influisce sui dati dei campi, devi comunque sapere quali elementi della pagina si stanno spostando per ottenere un punteggio di 0,3 al 75° percentile.

L'interfaccia LayoutShiftAttribution rende possibile tutto ciò.

Ottieni l'attribuzione della variazione del layout

L'interfaccia LayoutShiftAttribution è esposta su ogni voce layout-shift emessa dall'API Layout Instability.

Per una spiegazione dettagliata di entrambe le interfacce, consulta la pagina Debug delle variazioni di layout. Ai fini di questo post, la cosa principale che devi sapere è che, in qualità di sviluppatore, puoi osservare ogni variazione del layout che si verifica nella pagina, nonché gli elementi che si stanno spostando.

Di seguito è riportato un codice di esempio che registra ogni variazione di layout e gli elementi spostati:

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

Probabilmente non è pratico misurare e inviare i dati allo strumento di analisi per ogni singola variazione del layout; tuttavia, monitorando tutti i cambiamenti, puoi tenere traccia dei cambiamenti peggiori e semplicemente fornire informazioni al riguardo.

L'obiettivo non è identificare e correggere ogni singola variazione del layout che si verifica per ogni utente, ma solo identificare le variazioni che interessano il maggior numero di utenti e che, di conseguenza, contribuiscono maggiormente al CLS della pagina al 75° percentile.

Inoltre, non devi calcolare l'elemento di origine più grande ogni volta che c'è una variazione, devi farlo solo quando sei pronto a inviare il valore CLS allo strumento di analisi.

Il codice seguente prende un elenco di voci layout-shift che hanno contribuito a CLS e restituisce l'elemento di origine più grande dalla variazione più 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;
    }
  }
}

Dopo aver identificato l'elemento più grande che contribuisce al cambiamento maggiore, puoi segnalarlo al tuo strumento di analisi.

L'elemento che contribuisce maggiormente al CLS di una determinata pagina probabilmente varierà da utente a utente, ma se aggreghi questi elementi per tutti gli utenti, potrai generare un elenco di elementi in continuo cambiamento che interessano il maggior numero di utenti.

Dopo che avrai identificato e corretto la causa principale delle variazioni per questi elementi, il tuo codice di analisi inizierà a segnalare variazioni più piccole come i "peggiori" cambiamenti per le tue pagine. Alla fine, tutti i cambiamenti segnalati saranno abbastanza ridotti da far rientrare le pagine entro la soglia "buona" di 0,1.

Alcuni altri metadati che possono essere utili da acquisire insieme all'elemento di origine del cambio più grande sono:

  • L'ora del cambiamento più grande
  • Il percorso dell'URL nel momento della variazione massima (per i siti che aggiornano l'URL in modo dinamico, ad esempio le applicazioni a pagina singola).

LCP

Per eseguire il debug di LCP nel campo, le informazioni principali necessarie sono l'elemento più grande (l'elemento candidato LCP) per quel particolare caricamento pagina.

Tieni presente che è del tutto possibile, anzi è piuttosto comune, che l'elemento candidato LCP sia diverso da utente a utente, anche per la stessa pagina.

Questo può accadere per diversi motivi:

  • I dispositivi degli utenti hanno risoluzioni dello schermo diverse, il che genera layout di pagina diversi e diversi elementi visibili all'interno dell'area visibile.
  • Gli utenti non sempre caricano le pagine scorrette fino alla parte superiore. Spesso i link contengono identificatori di frammenti o anche frammenti di testo, il che significa che le pagine possono essere caricate e visualizzate in qualsiasi posizione di scorrimento sulla pagina.
  • I contenuti possono essere personalizzati in base all'utente corrente, quindi l'elemento candidato LCP potrebbe variare notevolmente da utente a utente.

Ciò significa che non puoi fare ipotesi su quale elemento o insieme di elementi sarà l'elemento candidato LCP più comune per una determinata pagina. Devi misurarli basandoti sul comportamento degli utenti reali.

Identificare l'elemento candidato LCP

Per determinare l'elemento candidato LCP in JavaScript, puoi utilizzare l'API Largest Contentful Paint, la stessa API che utilizzi per determinare il valore temporale LCP.

Quando esamini le voci largest-contentful-paint, puoi determinare l'attuale elemento candidato LCP osservando la proprietà element dell'ultima voce:

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 volta individuato l'elemento candidato LCP, puoi inviarlo al tuo strumento di analisi insieme al valore della metrica. Come con CLS, questo ti aiuterà a identificare gli elementi più importanti da ottimizzare per primi.

Oltre all'elemento candidato LCP, può essere utile anche misurare i tempi di sottoparte LCP, che possono essere utili per determinare quali passaggi di ottimizzazione specifici sono pertinenti per il tuo sito.

FID

Per eseguire il debug del FID sul campo, è importante ricordare che FID misura solo la parte di ritardo della latenza complessiva del primo evento di input. Ciò significa che ciò con cui l'utente ha interagito non è così importante come quello che stava accadendo nel thread principale al momento dell'interazione.

Ad esempio, molte applicazioni JavaScript che supportano il rendering lato server (SSR) forniscono codice HTML statico che può essere visualizzato sullo schermo prima che sia interattivo all'input dell'utente, ossia prima che il codice JavaScript richiesto per rendere interattivi i contenuti termini il caricamento.

Per questi tipi di applicazioni, può essere molto importante sapere se il primo input si è verificato prima o dopo l'idratazione. Se risulta che molte persone tentano di interagire con la pagina prima che l'idratazione sia completata, valuta la possibilità di rendere le tue pagine disattivate o di caricamento anziché in uno stato che sembra interattivo.

Se il framework dell'applicazione espone il timestamp di idratazione, puoi confrontarlo con il timestamp della voce first-input per determinare se il primo input è avvenuto prima o dopo l'idratazione. Se il framework non mostra quel timestamp o non utilizza affatto l'idratazione, un altro indicatore utile potrebbe essere se l'input si è verificato prima o dopo il termine del caricamento di JavaScript.

L'evento DOMContentLoaded viene attivato dopo che l'HTML della pagina è stato completamente caricato e analizzato, inclusa l'attesa del caricamento di eventuali script sincroni, differiti o di modulo (inclusi tutti i moduli importati in modo statico). Quindi puoi usare la tempistica dell'evento e confrontarla con il momento in cui si è verificato il FID.

Il codice seguente osserva le voci e i log first-input, indipendentemente dal fatto che il primo input si sia verificato o meno prima della fine dell'evento DOMContentLoaded:

new PerformanceObserver((list) => {
  const fidEntry = list.getEntries()[0];
  const navEntry = performance.getEntriesByType('navigation')[0];
  const wasFIDBeforeDCL =
    fidEntry.startTime < navEntry.domContentLoadedEventStart;

  console.log('FID occurred before DOMContentLoaded:', wasFIDBeforeDCL);
}).observe({type: 'first-input', buffered: true});

Identificare l'elemento target e il tipo di evento FID

Altri indicatori di debug potenzialmente utili sono l'elemento con cui è stata eseguita l'interazione e il tipo di interazione (ad esempio mousedown, keydown e pointerdown). Sebbene l'interazione con l'elemento stesso non contribuisce al FID (ricorda che il valore FID è solo la parte di ritardo della latenza totale dell'evento), conoscere gli elementi con cui gli utenti interagiscono può essere utile per determinare il modo migliore per migliorare il valore FID.

Ad esempio, se la maggior parte delle prime interazioni dell'utente avviene con un elemento specifico, considera l'incorporamento del codice JavaScript necessario per quell'elemento nell'HTML e il caricamento lento del resto.

Per ottenere il tipo di interazione e l'elemento associati al primo evento di input, puoi fare riferimento alle proprietà target e name della voce first-input:

new PerformanceObserver((list) => {
  const fidEntry = list.getEntries()[0];

  console.log('FID target element:', fidEntry.target);
  console.log('FID interaction type:', fidEntry.name);
}).observe({type: 'first-input', buffered: true});

INP

INP è molto simile a FID in quanto i bit di informazioni più utili da acquisire sul campo sono:

  1. Con quale elemento è stato interagito
  2. Perché il tipo di interazione era
  3. Quando è avvenuta l'interazione

Come il FID, una delle cause principali delle interazioni lente è il blocco del thread principale, che può essere comune durante il caricamento di JavaScript. Sapere se la maggior parte delle interazioni lente si verificano durante il caricamento della pagina è utile per determinare cosa è necessario fare per risolvere il problema.

A differenza del FID, la metrica INP considera la latenza completa di un'interazione, incluso il tempo necessario per eseguire i listener di eventi registrati e il tempo necessario per colorare il frame successivo dopo l'esecuzione di tutti i listener di eventi. Ciò significa che per INP è ancora più utile sapere quali elementi target tendono a generare interazioni lente e quali sono i tipi di interazioni.

Poiché INP e FID sono entrambi basati sull'API Event Timing, il modo in cui determini queste informazioni in JavaScript è molto simile all'esempio precedente. Il seguente codice registra l'elemento target e l'ora (relativi a DOMContentLoaded) della voce INP.

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

  const navEntry = performance.getEntriesByType('navigation')[0];
  const wasINPBeforeDCL =
    inpEntry.startTime < navEntry.domContentLoadedEventStart;

  console.log('INP occurred before DCL:', wasINPBeforeDCL);
}

Tieni presente che questo codice non mostra come determinare quale voce event è la voce INP, poiché questa logica è più complessa. Tuttavia, la seguente sezione spiega come ottenere queste informazioni utilizzando la libreria JavaScript dei vitali web.

Utilizzo con la libreria JavaScript dei file web-vitals

Le sezioni precedenti offrono alcuni suggerimenti generali ed esempi di codice per acquisire le informazioni di debug da includere nei dati inviati al tuo strumento di analisi.

Dalla versione 3, la libreria JavaScript dei vitali web include una build di attribuzione che fornisce tutte queste informazioni e anche alcuni indicatori aggiuntivi.

Il seguente esempio di codice mostra come impostare un parametro evento aggiuntivo (o dimensione personalizzata) contenente una stringa di debug utile per identificare la causa principale dei problemi di prestazioni.

import {onCLS, onFID, 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 'FID':
    case 'INP':
      eventParams.debug_target = attribution.eventTarget;
      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);

Questo codice è specifico di Google Analytics, ma l'idea generale dovrebbe essere traducibile anche in altri strumenti di analisi.

Questo codice mostra anche come generare report su un singolo indicatore di debug, ma potrebbe essere utile poter raccogliere e generare report su più indicatori diversi per metrica. Ad esempio, per eseguire il debug INP, potresti voler raccogliere il tipo di interazione, l'ora e l'elemento con cui interagisci. La build di attribuzione web-vitals mostra tutte queste informazioni, come mostrato nel seguente esempio:

import {onCLS, onFID, 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.eventTarget;
      eventParams.debug_type = attribution.eventType;
      eventParams.debug_time = attribution.eventTime;
      eventParams.debug_load_state = attribution.loadState;
      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 documentazione sull'attribuzione dei vitali web per l'elenco completo degli indicatori di debug esposti.

Generare report e visualizzare i dati

Dopo aver iniziato a raccogliere le informazioni di debug insieme ai valori delle metriche, il passaggio successivo consiste nell'aggregare i dati di tutti gli utenti per iniziare a cercare pattern e tendenze.

Come accennato in precedenza, non devi necessariamente risolvere ogni singolo problema riscontrato dagli utenti, devi risolvere, soprattutto all'inizio, i problemi che interessano il maggior numero di utenti, che dovrebbero essere anche quelli con il maggiore impatto negativo sui punteggi di Segnali web essenziali.

Per GA4, consulta l'articolo dedicato su come eseguire query e visualizzare i dati utilizzando BigQuery.

Riepilogo

Speriamo che questo post ti sia stato utile per descrivere i modi specifici in cui puoi utilizzare le API per le prestazioni esistenti e la libreria web-vitals per ottenere informazioni di debug al fine di diagnosticare le prestazioni in base alle visite degli utenti reali sul campo. Sebbene questa guida sia incentrata sui Segnali web essenziali, i concetti si applicano anche al debug di qualsiasi metrica delle prestazioni misurabile in JavaScript.

Se hai appena iniziato a misurare le prestazioni e sei già un utente di Google Analytics, lo strumento di report Web Vitals può essere un buon punto di partenza perché supporta già le informazioni di debug dei report per le metriche di Segnali web essenziali.

Se sei un fornitore di soluzioni di analisi e vuoi migliorare i tuoi prodotti e fornire ulteriori informazioni di debug agli utenti, prendi in considerazione alcune delle tecniche descritte di seguito, ma non limitarti a solo le idee presentate qui. Questo post è pensato per essere generalmente applicabile a tutti gli strumenti di analisi. Tuttavia, i singoli strumenti di analisi potrebbero (e devono) acquisire e segnalare ancora più informazioni di debug.

Infine, se ritieni che ci siano lacune nella tua capacità di eseguire il debug di queste metriche a causa di funzionalità o informazioni mancanti nelle API stesse, invia il tuo feedback all'indirizzo web-vitals-feedback@googlegroups.com.