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 dei lab: strumenti come Lighthouse, in cui la pagina viene caricata in un ambiente simulato in grado di imitare 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 agli utenti di Chrome. Tieni presente che i dati dei campi riportati da strumenti quali PageSpeed Insights e Search Console provengono dai dati di CrUX.

Mentre gli strumenti sul campo offrono dati più accurati, che rappresentano in effetti l'esperienza degli utenti reali, gli strumenti di lab sono spesso più utili per identificare e risolvere i problemi.

I dati di CrUX sono più rappresentativi del rendimento reale della tua pagina, ma conoscere i punteggi CrUX difficilmente ti aiuterà a capire come migliorare il rendimento.

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

Ciò solleva una domanda importante: come è possibile acquisire le informazioni di debug per Core Web Vitals o altre metriche relative alle prestazioni di utenti reali sul campo?

Questo post illustrerà in dettaglio quali API puoi utilizzare per raccogliere ulteriori informazioni di debug per ciascuna delle attuali metriche di Core Web Vitals e ti darà 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 Core Web Vitals, CLS è forse quella per cui la raccolta di informazioni di debug sul campo è più importante. Il CLS viene misurato durante l'intera durata della pagina, pertanto il modo in cui un utente interagisce con la pagina (la distanza percorsa dalla pagina di scorrimento, gli elementi su cui fa clic e così via) può avere un impatto significativo sull'eventuale presenza di variazioni del layout e sugli elementi che cambiano.

Prendi in considerazione il seguente report di PageSpeed Insights:

Un report PageSpeed Insights con diversi valori CLS

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

Tuttavia, anche se sei consapevole 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 questo.

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 Variazioni del layout del debug. Ai fini di questo post, la cosa principale da sapere è che, in qualità di sviluppatore, puoi osservare ogni variazione del layout che si verifica nella pagina e gli elementi che cambiano.

Di seguito è riportato un esempio di codice che registra ogni variazione del 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 dati al tuo strumento di analisi per ogni singola variazione del layout che si verifica. Tuttavia, monitorando tutte le variazioni, puoi tenere traccia delle variazioni peggiori e semplicemente fornire informazioni relative a queste variazioni.

L'obiettivo non è identificare e correggere ogni singola variazione del layout che si verifica per ogni utente, ma 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'è un cambiamento, devi farlo solo quando sei pronto a inviare il valore CLS allo strumento di analisi.

Il seguente codice 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;
    }
  }
}

Una volta identificato l'elemento più grande che contribuisce al cambiamento più ampio, puoi segnalarlo nel tuo strumento di analisi.

L'elemento che contribuisce maggiormente al CLS di una determinata pagina varia probabilmente da utente a utente, ma se aggreghi questi elementi tra tutti gli utenti, potrai generare un elenco di elementi variabili che interessano il maggior numero di utenti.

Dopo aver identificato e corretto la causa principale delle variazioni per questi elementi, il tuo codice di analisi inizierà a registrare variazioni più piccole come le variazioni "peggiori" 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.

Altri metadati che possono essere utili da acquisire insieme all'elemento di origine della variazione più grande sono:

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

LCP

Per eseguire il debug dell'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 comporta diversi layout di pagina e diversi elementi visibili all'interno dell'area visibile.
  • Non sempre gli utenti caricano le pagine che hanno raggiunto i livelli più alti. Spesso i link contengono identificatori di frammenti o anche frammenti di testo, il che significa che è possibile che le pagine vengano 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. Bisogna misurarli basandosi 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 delle 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 ciò 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 necessario per rendere interattivi i contenuti sia terminato 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 cercano di interagire con la pagina prima del completamento dell'idratazione, valuta la possibilità di visualizzare le pagine con lo stato disattivato o di caricamento anziché in uno stato interattivo.

Se il tuo framework di applicazione espone il timestamp di idratazione, puoi confrontarlo con il timestamp della voce first-input per determinare se il primo input si è verificato prima o dopo l'idratazione. Se il tuo framework non mostra questo timestamp o non usa 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, il che include l'attesa del caricamento di eventuali script sincroni, differiti o di modulo (inclusi tutti i moduli importati in modo statico). Quindi puoi utilizzare 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 FID e il tipo di evento

Altri indicatori di debug potenzialmente utili sono l'elemento con cui è stato interagito e il tipo di interazione (ad esempio mousedown, keydown, pointerdown). Sebbene l'interazione con l'elemento stesso non contribuisca al FID (ricorda che FID è solo la parte del ritardo della latenza totale dell'evento), sapere con quali elementi gli utenti stanno interagendo può essere utile per determinare il modo migliore per migliorare FID.

Ad esempio, se la maggior parte delle prime interazioni dell'utente avviene con un elemento specifico, valuta la possibilità di incorporare il codice JavaScript necessario per l'elemento nel codice HTML e di caricare il resto tramite il caricamento lento.

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

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

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

Come nel caso di FID, una delle cause principali delle interazioni lente è il blocco del thread principale, che può essere comune durante il caricamento di JavaScript. Sapere se si verifica la maggior parte delle interazioni lente 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 qualsiasi listener di eventi registrato e il tempo necessario per colorare il frame successivo dopo l'esecuzione di tutti gli eventi. Ciò significa che per INP è ancora più utile sapere quali elementi target tendono a generare interazioni lente e quali sono.

Poiché INP e FID si basano entrambi sull'API Event Timing, il modo in cui determini queste informazioni in JavaScript è molto simile all'esempio precedente. Il codice seguente 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ù coinvolta. Tuttavia, la seguente sezione spiega come ottenere queste informazioni utilizzando la libreria JavaScript web-vitals.

Utilizzo con la libreria JavaScript Web-vitals

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

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

Il seguente esempio di codice mostra come impostare un parametro evento aggiuntivo (o una 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 deve essere tradotta anche in altri strumenti di analisi.

Questo codice mostra anche solo come generare report su un singolo indicatore di debug, ma potrebbe essere utile 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 anche l'elemento con cui interagisci. La build di attribuzione web-vitals espone tutte queste informazioni, come mostrato nell'esempio che segue:

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 degli eventi web per l'elenco completo degli indicatori di debug esposti.

Crea report e visualizza 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 che gli utenti riscontrano, ma devi risolvere, soprattutto all'inizio, i problemi che interessano il maggior numero di utenti, che dovrebbero essere anche quelli che hanno 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

Spero che questo post ti sia stato utile per illustrare i modi specifici in cui puoi usare le API esistenti per le prestazioni e la libreria web-vitals per ottenere informazioni di debug al fine di diagnosticare le prestazioni in base alle visite di utenti reali sul campo. Questa guida è incentrata sui Segnali web essenziali, ma i concetti si applicano anche al debug di qualsiasi metrica relativa alle prestazioni misurabile in JavaScript.

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

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 in questo articolo, ma non limitarti solo alle idee presentate qui. Questo post è pensato per essere generalmente applicabile a tutti gli strumenti di analisi. Tuttavia, i singoli strumenti di analisi probabilmente possono (e dovrebbero) 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 a web-vitals-feedback@googlegroups.com.