Misurazione dell'impatto delle prestazioni reali dei lavoratori dei servizi

Uno dei vantaggi più significativi dei service worker (almeno dal punto di vista delle prestazioni) è la loro capacità di controllare in modo proattivo la memorizzazione nella cache degli asset. Un'applicazione web che può memorizzare nella cache tutte le risorse necessarie dovrebbe caricarsi notevolmente più velocemente per i visitatori di ritorno. Ma come si presentano questi vantaggi per gli utenti reali? E come fai a misurarlo?

L'app web Google I/O (in breve IOWA) è un'app web progressiva che ha sfruttato la maggior parte delle nuove funzionalità offerte dai service worker per offrire agli utenti un'esperienza completa simile a un'app. Ha inoltre utilizzato Google Analytics per acquisire dati chiave sul rendimento e modelli di utilizzo dal suo pubblico di utenti ampio e diversificato.

Questo caso di studio illustra in che modo l'Iowa ha utilizzato Google Analytics per rispondere a domande chiave sul rendimento e generare report sull'impatto reale dei worker di servizio.

Inizia con le domande

Ogni volta che implementi l'analisi in un sito web o un'applicazione, è importante iniziare identificando le domande a cui stai cercando di rispondere con i dati che raccoglierai.

Avevamo diverse domande a cui volevamo rispondere, ma per gli scopi di questo caso studio, concentriamoci su due delle più interessanti.

1. La memorizzazione nella cache dei worker di servizio è più efficiente dei meccanismi di memorizzazione nella cache HTTP esistenti disponibili in tutti i browser?

Ci aspettiamo già che le pagine vengano caricate più velocemente per i visitatori di ritorno rispetto ai nuovi visitatori, poiché i browser possono memorizzare nella cache le richieste e servirle immediatamente in caso di visite ripetute.

I worker di servizio offrono funzionalità di memorizzazione nella cache alternativa che offrono agli sviluppatori un controllo granulare su cosa e come viene eseguita la memorizzazione nella cache. In IOWA, abbiamo ottimizzato l'implementazione del nostro service worker in modo che ogni asset venisse memorizzato nella cache, in modo che i visitatori di ritorno potessero utilizzare l'app completamente offline.

Ma questo sforzo sarebbe migliore di quello che il browser fa già per impostazione predefinita? Se sì, quanto è migliore? 1

2. In che modo il service worker influisce sull'esperienza di caricamento del sito?

In altre parole, quanto sembra veloce il caricamento del sito, indipendentemente dai tempi di caricamento effettivi misurati dalle metriche di caricamento pagina tradizionali?

Ovviamente, rispondere a domande sul modo in cui si vive un'esperienza non è un compito facile e nessuna metrica può rappresentare perfettamente un sentimento così soggettivo. Detto questo, ci sono sicuramente alcune metriche migliori di altre, quindi è importante sceglierle correttamente.

Scegliere la metrica giusta

Per impostazione predefinita, Google Analytics monitora i tempi di caricamento delle pagine (tramite l'API Navigation Timing) per l'1% dei visitatori di un sito e rende disponibili questi dati tramite metriche come Tempo di caricamento pagina medio.

Tempo di caricamento della pagina medio è una buona metrica per rispondere alla prima domanda, ma non è particolarmente utile per rispondere alla seconda. Innanzitutto, l'evento load non corrisponde necessariamente al momento in cui l'utente può effettivamente interagire con l'app. Inoltre, due app con lo stesso tempo di caricamento potrebbero sembrare caricarsi in modo molto diverso. Ad esempio, un sito con una schermata iniziale o un indicatore di caricamento sembra caricarsi molto più velocemente di un sito che mostra solo una pagina vuota per diversi secondi.

In IOWA, abbiamo mostrato un'animazione di conto alla rovescia nella schermata iniziale che (a mio avviso) ha intrattenuto molto bene l'utente mentre il resto dell'app si caricava in background. Per questo motivo, monitorare il tempo necessario per visualizzare la schermata iniziale ha molto più senso come metodo per misurare il rendimento del caricamento percepito. Per ottenere questo valore, abbiamo scelto la metrica Tempo di visualizzazione della prima pagina.

Una volta stabilite le domande a cui volevamo rispondere e identificate le metriche utili per rispondere, era giunto il momento di implementare Google Analytics e iniziare a misurare.

L'implementazione di Analytics

Se hai già utilizzato Google Analytics, probabilmente conosci lo snippet di monitoraggio JavaScript consigliato. Ha questo aspetto:

<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>

La prima riga del codice riportato sopra inizializza una funzione ga() globale (se non esiste già) e l'ultima riga scarica in modo asincrono la libreria analytics.js.

La parte centrale contiene queste due righe:

ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');

Questi due comandi monitorano le pagine visitate dagli utenti che accedono al tuo sito, ma non molto di più. Se vuoi monitorare altre interazioni utente, devi farlo autonomamente.

Per la campagna IOWA, volevamo monitorare altri due elementi:

  • Il tempo trascorso tra l'inizio del caricamento della pagina e la visualizzazione dei pixel sullo schermo.
  • Indica se la pagina è controllata o meno da un service worker. Con queste informazioni, potremmo segmentare i report per confrontare i risultati con e senza il servizio worker.

Acquisizione del tempo per il primo paint

Alcuni browser registrano l'ora esatta in cui viene visualizzato il primo pixel sullo schermo e la rendono disponibile per gli sviluppatori. Questo valore, rispetto al valore navigationStart esposto tramite l'API Navigation Timing, ci fornisce un conteggio molto preciso del tempo trascorso tra la richiesta iniziale della pagina da parte dell'utente e la prima visualizzazione di un elemento.

Come ho già detto, il tempo di visualizzazione iniziale è una metrica importante da misurare perché è il primo punto in cui un utente sperimenta la velocità di caricamento del tuo sito. È la prima impressione che gli utenti ricevono e una buona prima impressione può influire positivamente sul resto dell'esperienza utente.2

Per ottenere il primo valore di paint nei browser che lo espongono, abbiamo creato la funzione di utilità getTimeToFirstPaintIfSupported:

function getTimeToFirstPaintIfSupported() {
  // Ignores browsers that don't support the Performance Timing API.
  if (window.performance && window.performance.timing) {
    var navTiming = window.performance.timing;
    var navStart = navTiming.navigationStart;
    var fpTime;

    // If chrome, get first paint time from `chrome.loadTimes`.
    if (window.chrome && window.chrome.loadTimes) {
      fpTime = window.chrome.loadTimes().firstPaintTime * 1000;
    }
    // If IE/Edge, use the prefixed `msFirstPaint` property.
    // See http://msdn.microsoft.com/ff974719
    else if (navTiming.msFirstPaint) {
      fpTime = navTiming.msFirstPaint;
    }

    if (fpTime && navStart) {
      return fpTime - navStart;
    }
  }
}

Ora possiamo scrivere un'altra funzione che invia un evento di non interazione con il tempo di visualizzazione iniziale come valore:3

function sendTimeToFirstPaint() {
  var timeToFirstPaint = getTimeToFirstPaintIfSupported();

  if (timeToFirstPaint) {
    ga('send', 'event', {
      eventCategory: 'Performance',
      eventAction: 'firstpaint',
      // Rounds to the nearest millisecond since
      // event values in Google Analytics must be integers.
      eventValue: Math.round(timeToFirstPaint)
      // Sends this as a non-interaction event,
      // so it doesn't affect bounce rate.
      nonInteraction: true
    });
  }
}

Dopo aver scritto entrambe le funzioni, il codice di monitoraggio sarà il seguente:

// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');

// Sends a pageview for the initial pageload.
ga('send', 'pageview');

// Sends an event with the time to first paint data.
sendTimeToFirstPaint();

Tieni presente che, a seconda di quando viene eseguito il codice riportato sopra, i pixel potrebbero essere già stati visualizzati sullo schermo o meno. Per assicurarci di eseguire sempre questo codice dopo la prima applicazione della pittura, abbiamo posticipato la chiamata a sendTimeToFirstPaint() fino a dopo l'evento load. Di fatto, abbiamo deciso di posticipare l'invio di tutti i dati di analisi fino al termine del caricamento della pagina per garantire che queste richieste non interferissero con il caricamento di altre risorse.

// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');

// Postpones sending any hits until after the page has fully loaded.
// This prevents analytics requests from delaying the loading of the page.
window.addEventListener('load', function() {
  // Sends a pageview for the initial pageload.
  ga('send', 'pageview');

  // Sends an event with the time to first paint data.
  sendTimeToFirstPaint();
});

Il codice riportato sopra genera firstpaint report in Google Analytics, ma non è tutto. Dovevamo comunque monitorare lo stato del service worker, altrimenti non avremmo potuto confrontare i tempi di primo rendering di una pagina controllata da un service worker e di una pagina non controllata.

Determinare lo stato del service worker

Per determinare lo stato attuale del servizio worker, abbiamo creato una funzione di utilità che restituisce uno di tre valori:

  • controllata: la pagina è controllata da un service worker. Nel caso di IOWA, significa anche che tutti gli asset sono stati memorizzati nella cache e la pagina funziona offline.
  • supportato: il browser supporta i service worker, ma il service worker non controlla ancora la pagina. Questo è lo stato previsto per i visitatori che accedono per la prima volta.
  • unsupported: il browser dell'utente non supporta i worker di servizio.
function getServiceWorkerStatus() {
  if ('serviceWorker' in navigator) {
    return navigator.serviceWorker.controller ? 'controlled' : 'supported';
  } else {
    return 'unsupported';
  }
}

Questa funzione ha recuperato lo stato del worker del servizio. Il passaggio successivo è stato associare questo stato ai dati che inviavamo a Google Analytics.

Monitoraggio dei dati personalizzati con dimensioni personalizzate

Per impostazione predefinita, Google Analytics offre molti modi per suddividere il traffico totale in gruppi in base agli attributi dell'utente, della sessione o dell'interazione. Questi attributi sono noti come dimensioni. Le dimensioni comuni che interessano agli sviluppatori web sono, ad esempio, Browser, Sistema operativo o Categoria dispositivo.

Lo stato del servizio worker non è una dimensione fornita da Google Analytics per impostazione predefinita. Tuttavia, Google Analytics ti consente di creare le tue dimensioni personalizzate e definirle come preferisci.

Per IOWA, abbiamo creato una dimensione personalizzata denominata Stato del servizio di lavoro e ne abbiamo impostato l'ambito su hit (ovvero per interazione).4 A ogni dimensione personalizzata creata in Google Analytics viene assegnato un indice univoco all'interno della proprietà e nel codice di monitoraggio puoi fare riferimento a questa dimensione tramite il relativo indice. Ad esempio, se l'indice della dimensione che abbiamo appena creato fosse 1, potremmo aggiornare la nostra logica come segue per inviare l'evento firstpaint in modo da includere lo stato del servizio worker:

ga('send', 'event', {
  eventCategory: 'Performance',
  eventAction: 'firstpaint',
  // Rounds to the nearest millisecond since
  // event values in Google Analytics must be integers.
  eventValue: Math.round(timeToFirstPaint)
  // Sends this as a non-interaction event,
  // so it doesn't affect bounce rate.
  nonInteraction: true,

  // Sets the current service worker status as the value of
  // `dimension1` for this event.
  dimension1: getServiceWorkerStatus()
});

Questo funziona, ma associa lo stato del service worker solo a questo evento specifico. Poiché lo stato del worker di servizio è un dato potenzialmente utile per qualsiasi interazione, è meglio includerlo in tutti i dati inviati a Google Analytics.

Per includere queste informazioni in tutti gli hit (ad es. tutte le visualizzazioni di pagina, gli eventi e così via), impostiamo il valore della dimensione personalizzata sull'oggetto tracker stesso, prima di inviare qualsiasi dato a Google Analytics.

ga('set', 'dimension1', getServiceWorkerStatus());

Una volta impostato, questo valore viene inviato con tutti gli hit successivi per il caricamento della pagina corrente. Se l'utente carica di nuovo la pagina in un secondo momento, è probabile che la funzione getServiceWorkerStatus() restituisca un nuovo valore, che verrà impostato sull'oggetto tracker.

Una breve nota sulla chiarezza e sulla leggibilità del codice: poiché altre persone che esaminano questo codice potrebbero non sapere a cosa si riferisce dimension1, è sempre meglio creare una variabile che mappi nomi di dimensioni significativi ai valori utilizzati da analytics.js.

// Creates a map between custom dimension names and their index.
// This is particularly useful if you define lots of custom dimensions.
var customDimensions = {
  SERVICE_WORKER_STATUS: 'dimension1'
};

// Creates the tracker object.
ga('create', 'UA-XXXXX-Y', 'auto');

// Sets the service worker status on the tracker,
// so its value is included in all future hits.
ga('set', customDimensions.SERVICE_WORKER_STATUS, getServiceWorkerStatus());

// Postpones sending any hits until after the page has fully loaded.
// This prevents analytics requests from delaying the loading of the page.
window.addEventListener('load', function() {
  // Sends a pageview for the initial pageload.
  ga('send', 'pageview');

  // Sends an event with the time to first paint data.
  sendTimeToFirstPaint();
});

Come ho accennato, l'invio della dimensione Stato del servizio worker con ogni hit ci consente di utilizzarla per generare report su qualsiasi metrica.

Come puoi vedere, quasi l'85% di tutte le visualizzazioni di pagina per l'Iowa proveniva da browser che supportano i worker di servizio.

Risultati: le risposte alle nostre domande

Una volta iniziato a raccogliere dati per rispondere alle nostre domande, abbiamo potuto generare report su questi dati per vedere i risultati. (Nota: tutti i dati di Google Analytics mostrati qui rappresentano il traffico web effettivo verso il sito IOWA dal 16 al 22 maggio 2016).

La prima domanda che ci siamo posti è stata: la memorizzazione nella cache dei worker di servizio è più performante rispetto ai meccanismi di memorizzazione nella cache HTTP esistenti disponibili in tutti i browser?

Per rispondere a questa domanda, abbiamo creato un report personalizzato che esaminava la metrica Tempi di caricamento pagina medi in varie dimensioni. Questa metrica è adatta per rispondere a questa domanda perché l'evento load viene attivato solo dopo il download di tutte le risorse iniziali. Pertanto, riflette direttamente il tempo di caricamento totale di tutte le risorse critiche del sito.5

Le dimensioni che abbiamo scelto sono:

  • La nostra dimensione personalizzata Stato del service worker.
  • Tipo di utente, che indica se si tratta della prima visita dell'utente al sito o se è un utente di ritorno. Nota: un nuovo visitatore non avrà risorse memorizzate nella cache, mentre un visitatore di ritorno potrebbe averne.
  • Categoria del dispositivo, che ci consente di confrontare i risultati su dispositivi mobili e computer.

Per verificare la possibilità che fattori non correlati ai worker di servizio stessero alterando i risultati relativi ai tempi di caricamento, abbiamo limitato la query in modo da includere solo i browser che supportano i worker di servizio.

Come puoi vedere, le visite alla nostra app controllate da un service worker si sono caricate molto più velocemente rispetto alle visite non controllate, anche quelle degli utenti di ritorno che probabilmente avevano memorizzato nella cache la maggior parte delle risorse della pagina. È interessante notare anche che, in media, i visitatori su dispositivi mobili con un worker di servizio hanno registrato caricamenti più rapidi rispetto ai nuovi visitatori su computer.

"…le visite alla nostra app controllate da un service worker si caricano molto più velocemente rispetto alle visite non controllate…"

Puoi trovare maggiori dettagli nelle due tabelle seguenti:

Tempo di caricamento medio della pagina (computer)
Stato del service worker Tipo di utente Tempo medio di caricamento pagina (ms) Dimensioni del campione
Hai controllato Visitatore di ritorno 2568 30860
Supportato Visitatore di ritorno 3612 1289
Supportato Nuovo visitatore 4664 21991
Tempo di caricamento medio della pagina (dispositivi mobili)
Stato del service worker Tipo di utente Tempo medio di caricamento pagina (ms) Dimensioni del campione
Hai controllato Visitatore di ritorno 3760 8162
Supportato Visitatore di ritorno 4843 676
Supportato Nuovo visitatore 6158 5779

Potresti chiederti come sia possibile che un visitatore di ritorno il cui browser supporta i service worker si trovi mai in uno stato non controllato. Ecco alcune spiegazioni possibili:

  • L'utente ha abbandonato la pagina durante la visita iniziale prima che il service worker avesse la possibilità di completare l'inizializzazione.
  • L'utente ha disinstallato il service worker tramite gli strumenti per sviluppatori.

Entrambe queste situazioni sono relativamente rare. Possiamo vederlo nei dati esaminando i valori di Sample di caricamento pagina nella quarta colonna. Tieni presente che le righe centrali hanno un campione molto più piccolo rispetto alle altre due.

La seconda domanda era: In che modo il service worker influisce sull'esperienza di caricamento del sito?

Per rispondere a questa domanda, abbiamo creato un altro report personalizzato per la metrica Valore evento medio e abbiamo filtrato i risultati in modo da includere solo i nostri eventi firstpaint. Abbiamo utilizzato le dimensioni Categoria del dispositivo e la nostra dimensione personalizzata Stato del servizio di lavoro.

Contrariamente a quanto mi aspettassi, il service worker sui dispositivi mobili ha avuto un impatto molto minore sul tempo di visualizzazione della prima pagina rispetto al caricamento complessivo della pagina.

"…il service worker sui dispositivi mobili ha avuto un impatto molto minore sul tempo di visualizzazione della prima pagina rispetto al caricamento complessivo della pagina."

Per capire perché, dobbiamo esaminare più in dettaglio i dati. Le medie possono essere utili per panoramiche generali e approssimazioni, ma per avere un'idea precisa di come questi numeri si suddividono in un raggio di utenti, dobbiamo esaminare una distribuzione di firstpaint volte.

Ottenere la distribuzione di una metrica in Google Analytics

Per ottenere la distribuzione dei tempi firstpaint, abbiamo bisogno di accedere ai singoli risultati per ogni evento. Purtroppo, Google Analytics non semplifica questa operazione.

Google Analytics ci consente di suddividere un report in base a qualsiasi dimensione, ma non ci consente di suddividere un report in base alle metriche. Ciò non significa che sia impossibile, ma solo che abbiamo dovuto personalizzare un po' di più la nostra implementazione per ottenere il risultato desiderato.

Poiché i risultati dei report possono essere suddivisi solo per dimensioni, abbiamo dovuto impostare il valore della metrica (in questo caso l'ora firstpaint) come dimensione personalizzata per l'evento. Per farlo, abbiamo creato un'altra dimensione personalizzata denominata Valore metrica e abbiamo aggiornato la logica di monitoraggio firstpaint come segue:

var customDimensions = {
  SERVICE_WORKER_STATUS: 'dimension1',
  <strong>METRIC_VALUE: 'dimension2'</strong>
};

// ...

function sendTimeToFirstPaint() {
  var timeToFirstPaint = getTimeToFirstPaintIfSupported();

  if (timeToFirstPaint) {
    var fields = {
      eventCategory: 'Performance',
      eventAction: 'firstpaint',
      // Rounds to the nearest millisecond since
      // event values in Google Analytics must be integers.
      eventValue: Math.round(timeToFirstPaint)
      // Sends this as a non-interaction event,
      // so it doesn't affect bounce rate.
      nonInteraction: true
    }

    <strong>// Sets the event value as a dimension to allow for breaking down the
    // results by individual metric values at reporting time.
    fields[customDimensions.METRIC_VALUE] = String(fields.eventValue);</strong>

    ga('send', 'event', fields);
  }
}

Al momento, l'interfaccia web di Google Analytics non fornisce un modo per visualizzare la distribuzione di valori arbitrari delle metriche, ma con l'aiuto dell'API Core Reporting di Google Analytics e della libreria Google Charts possiamo eseguire query sui risultati non elaborati e poi creare un istogramma.

Ad esempio, è stata utilizzata la seguente configurazione della richiesta API per ottenere una distribuzione dei valori firstpaint su computer con un servizio worker non controllato.

{
  dateRanges: [{startDate: '2016-05-16', endDate: '2016-05-22'}],
  metrics: [{expression: 'ga:totalEvents'}],
  dimensions: [{name: 'ga:dimension2'}],
  dimensionFilterClauses: [
    {
      operator: 'AND',
      filters: [
        {
          dimensionName: 'ga:eventAction',
          operator: 'EXACT',
          expressions: ['firstpaint']
        },
        {
          dimensionName: 'ga:dimension1',
          operator: 'EXACT',
          expressions: ['supported']
        },
        {
          dimensionName: 'ga:deviceCategory',
          operator: 'EXACT',
          expressions: ['desktop']
        }
      ],
    }
  ],
  orderBys: [
    {
      fieldName: 'ga:dimension2',
      orderType: 'DIMENSION_AS_INTEGER'
    }
  ]
}

Questa richiesta API restituisce un array di valori simile al seguente (nota: questi sono solo i primi cinque risultati). I risultati sono ordinati dal più piccolo al più grande, quindi queste righe rappresentano i tempi più rapidi.

Risultati della risposta dell'API (prime cinque righe)
ga:dimension2 ga:totalEvents
4 3
5 2
6 10
7 8
8 10

Ecco cosa significano questi risultati in termini semplici:

  • Sono stati registrati 3 eventi in cui il valore firstpaint era 4 ms
  • Sono stati registrati 2 eventi in cui il valore di firstpaint era 5 ms
  • Sono stati registrati 10 eventi in cui il valore di firstpaint era 6 ms
  • Sono stati registrati 8 eventi in cui il valore di firstpaint era 7 ms
  • Sono stati registrati 10 eventi in cui firstpaint value era pari a 8 ms
  • e così via

Da questi risultati possiamo estrapolare il valore firstpaint per ogni singolo evento e creare un'istogramma della distribuzione. Lo abbiamo fatto per ogni query eseguita.

Ecco come appariva la distribuzione su computer con un service worker non controllato (ma supportato):

Distribuzione del tempo di prima visualizzazione su computer (supportata)

Il tempo firstpaint mediano per la distribuzione sopra indicata è 912 ms.

La forma di questa curva è abbastanza tipica delle distribuzioni dei tempi di caricamento. Confrontalo con l'istogramma seguente, che mostra la distribuzione degli eventi di primo rendering per le visite in cui un worker di servizio controllava la pagina.

Distribuzione del tempo di First Paint su computer (controllata)

Tieni presente che quando un service worker controllava la pagina, molti visitatori hanno riscontrato un primo rendering quasi immediato, con una media di 583 ms.

"…quando un service worker controllava la pagina, molti visitatori hanno riscontrato un primo rendering quasi immediato…"

Per comprendere meglio il confronto tra queste due distribuzioni, il grafico seguente mostra una vista combinata delle due. L'istogramma che mostra le visite dei worker di servizio non controllate è sovrapposto all'istogramma che mostra le visite controllate e entrambi sono sovrapposti a un istogramma che mostra entrambe le visite combinate.

Distribuzione del tempo di First Paint su computer

Un aspetto interessante di questi risultati è che la distribuzione con un worker di servizio controllato aveva ancora una curva a forma di campana dopo il picco iniziale. Mi aspettavo un picco iniziale elevato e poi un calo graduale, non mi aspettavo un secondo picco nella curva.

Quando ho esaminato la causa del problema, ho scoperto che anche se un service worker può controllare una pagina, il relativo thread può essere inattivo. Il browser esegue questa operazione per risparmiare risorse: ovviamente non è necessario che tutti i worker per ogni sito che hai visitato siano attivi e pronti in qualsiasi momento. Questo spiega la coda della distribuzione. Per alcuni utenti si è verificato un ritardo durante l'avvio del thread del worker di servizio.

Tuttavia, come puoi vedere dalla distribuzione, anche con questo ritardo iniziale, i browser con il servizio worker hanno caricato i contenuti più velocemente rispetto ai browser che passano attraverso la rete.

Ecco come apparivano le cose sui dispositivi mobili:

Distribuzione del tempo di First Paint sui dispositivi mobili

Abbiamo registrato un aumento significativo dei tempi di prima pittura quasi immediata, ma la coda era molto più grande e lunga. Questo è probabilmente dovuto al fatto che, sui dispositivi mobili, l'avvio di un thread di worker di servizio inattivo richiede più tempo che su computer. Spiega anche perché la differenza tra il tempo firstpaint medio non era così grande come mi aspettavo (discussa sopra).

"…sui dispositivi mobili, l'avvio di un thread di worker di servizio inattivo richiede più tempo che su computer."

Ecco la suddivisione di queste variazioni dei tempi medi della prima pittura su dispositivi mobili e computer raggruppati in base allo stato del worker di servizio:

Tempo mediano al primo rendering (ms)
Stato del service worker Desktop Dispositivi mobili
Hai controllato 583 1634
Supportato (non controllato) 912 1933

Sebbene la creazione di queste visualizzazioni di distribuzione abbia richiesto un po' più di tempo e impegno rispetto alla creazione di un report personalizzato in Google Analytics, ci offrono una comprensione molto più approfondita di come i worker influiscono sul rendimento del nostro sito rispetto alle sole medie.

Altro impatto dei service worker

Oltre all'impatto sul rendimento, i worker dei servizi influiscono anche sull'esperienza utente in diversi altri modi misurabili con Google Analytics.

Accesso offline

I service worker consentono agli utenti di interagire con il tuo sito quando sono offline e, anche se una sorta di supporto offline è probabilmente fondamentale per qualsiasi app web progressiva, stabilire quanto sia fondamentale nel tuo caso dipende in gran parte dall'utilizzo offline. Ma come si misura?

L'invio dei dati a Google Analytics richiede una connessione a internet, ma non richiede che i dati vengano inviati nell'istante esatto in cui si è verificata l'interazione. Google Analytics supporta l'invio dei dati sulle interazioni in un secondo momento specificando un offset di tempo (tramite il parametro qt).

Negli ultimi due anni, IOWA utilizza uno script di worker di servizio che rileva gli hit non riusciti in Google Analytics quando l'utente è offline e li riproduce in un secondo momento con il parametro qt.

Per monitorare se l'utente era online o offline, abbiamo creato una dimensione personalizzata denominata Online e l'abbiamo impostata sul valore navigator.onLine, quindi abbiamo ascoltato gli eventi online e offline e aggiornato la dimensione di conseguenza.

Per capire quanto fosse comune per un utente essere offline durante l'utilizzo di IOWA, abbiamo creato un segmento che aveva come target gli utenti con almeno un'interazione offline. Si è scoperto che si trattava del 5% degli utenti.

Notifiche push

I worker di servizio consentono agli utenti di attivare la ricezione di notifiche push. In Iowa, gli utenti ricevevano una notifica quando stava per iniziare una sessione nel loro programma.

Come per qualsiasi forma di notifica, è importante trovare il giusto equilibrio tra offrire valore all'utente e non infastidirlo. Per capire meglio cosa succede, è importante monitorare se gli utenti attivano la ricezione di queste notifiche, se interagiscono con loro quando arrivano e se gli utenti che le hanno attivate in precedenza cambiano la loro preferenza e le disattivano.

In Iowa abbiamo inviato solo notifiche relative alla programmazione personalizzata dell'utente, che solo gli utenti che hanno eseguito l'accesso potevano creare. Ciò ha limitato l'insieme di utenti che potevano ricevere notifiche agli utenti che avevano eseguito l'accesso (monitorati tramite una dimensione personalizzata denominata Accesso) i cui browser supportavano le notifiche push (monitorati tramite un'altra dimensione personalizzata denominata Autorizzazione di notifica).

Il report riportato di seguito si basa sulla metrica Utenti e sulla nostra dimensione personalizzata Autorizzazione di notifica, segmentata in base agli utenti che hanno eseguito l'accesso a un certo punto e i cui browser supportano le notifiche push.

È fantastico vedere che più della metà dei nostri utenti che hanno eseguito l'accesso ha scelto di ricevere notifiche push.

Banner per l'installazione di app

Se un'app web di avanzamento soddisfa i criteri ed è utilizzata di frequente da un utente, a quest'ultimo potrebbe essere mostrato un banner di installazione dell'app che lo invita ad aggiungere l'app alla schermata Home.

In Iowa, abbiamo monitorato la frequenza con cui questi prompt sono stati mostrati all'utente (e se sono stati accettati) con il seguente codice:

window.addEventListener('beforeinstallprompt', function(event) {
  // Tracks that the user saw a prompt.
  ga('send', 'event', {
    eventCategory: 'installprompt',
    eventAction: 'fired'
  });

  event.userChoice.then(function(choiceResult) {
    // Tracks the users choice.
    ga('send', 'event', {
      eventCategory: 'installprompt',
      // `choiceResult.outcome` will be 'accepted' or 'dismissed'.
      eventAction: choiceResult.outcome,
      // `choiceResult.platform` will be 'web' or 'android' if the prompt was
      // accepted, or '' if the prompt was dismissed.
      eventLabel: choiceResult.platform
    });
  });
});

Degli utenti che hanno visto un banner di installazione di app, circa il 10% ha scelto di aggiungerlo alla schermata Home.

Possibili miglioramenti al monitoraggio (per la prossima volta)

I dati di analisi che abbiamo raccolto da IOWA quest'anno sono stati inestimabili. Ma il senno di poi mette sempre in luce lacune e opportunità di miglioramento per la prossima volta. Dopo aver completato l'analisi di quest'anno, ecco due cose che avrei voluto fare in modo diverso e che i lettori che vogliono implementare una strategia simile potrebbero prendere in considerazione:

1. Monitorare più eventi relativi all'esperienza di caricamento

Abbiamo monitorato diversi eventi che corrispondono a una metrica tecnica (ad es. HTMLImportsLoaded, WebComponentsReady e così via), ma poiché gran parte del caricamento è stato eseguito in modo asincrono, il punto in cui sono stati attivati questi eventi non corrispondeva necessariamente a un determinato momento nell'esperienza di caricamento complessiva.

L'evento principale relativo al caricamento che non abbiamo monitorato (ma ci sarebbe piaciuto farlo) è il punto in cui la schermata di benvenuto è scomparsa e l'utente ha potuto vedere i contenuti della pagina.

2. Memorizzare l'ID client di Analytics in IndexedDB

Per impostazione predefinita, analytics.js memorizza il campo ID cliente nei cookie del browser. Purtroppo, gli script di service worker non possono accedere ai cookie.

Questo ha rappresentato un problema per noi quando abbiamo cercato di implementare il monitoraggio delle notifiche. Volevamo inviare un evento dal service worker (tramite Measurement Protocol) ogni volta che veniva inviata una notifica a un utente e poi monitorare il successo del ricoinvolgimento della notifica se l'utente ci faceva clic sopra e tornava nell'app.

Sebbene sia stato possibile monitorare il successo delle notifiche in generale tramite il utm_source parametro della campagna, non è stato possibile associare una determinata sessione di ricoinvolgimento a un determinato utente.

Per aggirare questa limitazione, avremmo potuto memorizzare l'ID cliente tramite IndexedDB nel nostro codice di monitoraggio, in modo che il valore fosse accessibile allo script del servizio worker.

3. Consenti al service worker di segnalare lo stato online/offline

L'ispezione di navigator.onLine ti consente di sapere se il browser è in grado di connettersi al router o alla rete locale, ma non indica necessariamente se l'utente dispone di una connettività reale. Inoltre, poiché il nostro script worker del servizio di analisi offline riproduceva semplicemente gli hit non riusciti (senza modificarli o contrassegnarli come non riusciti), probabilmente sottostimavamo il nostro utilizzo offline.

In futuro dovremmo monitorare sia lo stato di navigator.onLine sia se l'hit è stato riprodotto dal service worker a causa di un errore di rete iniziale. In questo modo, avremo un quadro più preciso del vero utilizzo offline.

In sintesi

Questo caso di studio ha dimostrato che l'utilizzo di service worker ha effettivamente migliorato le prestazioni di caricamento della web app Google I/O su una vasta gamma di browser, reti e dispositivi. È emerso inoltre che, quando esamini una distribuzione dei dati di caricamento su una vasta gamma di browser, reti e dispositivi, ottieni molte più informazioni su come questa tecnologia gestisce gli scenari reali e scopri caratteristiche di prestazioni che potresti non aver previsto.

Ecco alcuni dei punti chiave dello studio IOWA:

  • In media, le pagine si caricavano molto più velocemente quando erano controllate da un service worker rispetto a quando non lo erano, sia per i visitatori nuovi che di ritorno.
  • Le visite alle pagine controllate da un service worker si caricavano quasi istantaneamente per molti utenti.
  • Quando non sono attivi, i worker di servizio richiedono un po' di tempo per l'avvio. Tuttavia, un service worker inattivo ha comunque registrato un rendimento migliore rispetto a un servizio senza service worker.
  • Il tempo di avvio di un service worker inattivo era più lungo sui dispositivi mobili rispetto ai computer.

Sebbene i miglioramenti del rendimento osservati in una determinata applicazione siano generalmente utili da segnalare alla più ampia community di sviluppatori, è importante ricordare che questi risultati sono specifici per il tipo di sito di IOWA (un sito di eventi) e per il tipo di pubblico di IOWA (principalmente sviluppatori).

Se stai implementando il servizio worker nella tua applicazione, è importante che implementi la tua strategia di misurazione per poter valutare il tuo rendimento ed evitare una futura regressione. In questo caso, condividi i risultati in modo che tutti possano trarne vantaggio.

Note a piè di pagina

  1. Non è del tutto corretto confrontare le prestazioni dell'implementazione della cache del nostro service worker con quelle del nostro sito con solo la cache HTTP. Poiché stavamo ottimizzando IOWA per i worker di servizio, non abbiamo dedicato molto tempo all'ottimizzazione per la cache HTTP. Se l'avessimo fatto, i risultati probabilmente sarebbero stati diversi. Per scoprire di più sull'ottimizzazione del sito per la cache HTTP, leggi l'articolo Ottimizzare i contenuti in modo efficiente.
  2. A seconda di come il tuo sito carica gli stili e i contenuti, è possibile che il browser sia in grado di eseguire la pittura prima che i contenuti o gli stili siano disponibili. In questi casi, firstpaint potrebbe corrispondere a una schermata bianca vuota. Se utilizzi firstpaint, è importante assicurarti che corrisponda a un punto significativo nel caricamento delle risorse del tuo sito.
  3. Tecnicamente, potremmo inviare un hit timing (che per impostazione predefinita non è un'interazione) per acquisire queste informazioni anziché un evento. Infatti, i hit relativi ai tempi sono stati aggiunti a Google Analytics appositamente per monitorare le metriche di caricamento come questa. Tuttavia, i hit relativi ai tempi vengono sottoposti a un campionamento elevato al momento dell'elaborazione e i relativi valori non possono essere utilizzati nei segmenti. Date queste limitazioni attuali, gli eventi non di interazione rimangono più adatti.
  4. Per comprendere meglio quale ambito assegnare a una dimensione personalizzata in Google Analytics, consulta la sezione Dimensione personalizzata del Centro assistenza Analytics. È inoltre importante comprendere il modello di dati di Google Analytics, composto da utenti, sessioni e interazioni (hit). Per scoprire di più, guarda la lezione di Analytics Academy sul modello di dati di Google Analytics.
  5. Non vengono prese in considerazione le risorse caricate in modo lazy dopo l'evento di caricamento.