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 in grado di memorizzare nella cache tutte le risorse necessarie dovrebbe caricarsi molto più velocemente per i visitatori di ritorno. Ma come appaiono concretamente questi guadagni agli utenti reali? E come si misura tutto questo?

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 quella delle app. Inoltre, ha utilizzato Google Analytics per acquisire dati chiave sulle prestazioni e sui modelli di utilizzo dal suo ampio e diversificato pubblico di utenti.

Questo case study esplora come IOWA ha utilizzato Google Analytics per rispondere a domande chiave sulle prestazioni e generare report sull'impatto reale dei service worker.

Iniziamo dalle domande

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

Anche se volevamo rispondere a diverse domande, ai fini di questo case study concentriamoci su due delle più interessanti.

1. La memorizzazione nella cache dei service worker è più efficace rispetto ai 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 a quelle per i nuovi visitatori, in quanto i browser possono memorizzare le richieste nella cache e inviarle immediatamente alle visite ripetute.

I Service worker offrono funzionalità di memorizzazione nella cache alternative che consentono agli sviluppatori di avere un controllo granulare su cosa esattamente e come viene eseguito il processo di memorizzazione nella cache. In IOWA, ottimizzavamo l'implementazione dei 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 meglio di quello che già fa il browser per impostazione predefinita? E se sì, quanto migliorerà? 1

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

In altre parole, che velocità ha la impressione del caricamento del sito, indipendentemente dai tempi di caricamento effettivi misurati dalle tradizionali metriche di caricamento delle pagine?

Rispondere a domande su come si percepisce un'esperienza non è ovviamente un compito facile e nessuna metrica potrà rappresentare perfettamente un sentiment così soggettivo. Detto questo, ci sono sicuramente alcune metriche migliori di altre, quindi scegliere quelle giuste è importante.

Scelta della metrica giusta

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

Media Tempo di caricamento della pagina è una buona metrica per rispondere alla prima domanda, ma non per la seconda. Da un lato, 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 che vengano caricate in modo molto diverso. Ad esempio, è probabile che un sito con una schermata iniziale o un indicatore di caricamento venga caricato molto più velocemente di un sito che mostra soltanto una pagina vuota per diversi secondi.

In IOWA, abbiamo mostrato un'animazione con conto alla rovescia nella schermata iniziale che (a mio parere) è stata utile per intrattenere l'utente mentre il resto dell'app si caricava in background. Per questo motivo, il monitoraggio del tempo necessario per la visualizzazione della schermata iniziale è molto più logico come modo per misurare il rendimento del carico percepito. Abbiamo scelto la metrica Tempo per la prima visualizzazione per ottenere questo valore.

Una volta definite le domande a cui volevamo rispondere e identificate le metriche utili a rispondere, era giunto il momento di implementare Google Analytics e iniziare la misurazione.

L'implementazione dell'analisi

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 visitano il tuo sito, ma non molto di più. Se vuoi monitorare altre interazioni degli utenti, devi farlo autonomamente.

Per IOWA, volevamo tenere traccia di altri due aspetti:

  • Il tempo che intercorre tra il primo caricamento della pagina e il momento in cui i pixel vengono visualizzati sullo schermo.
  • Se un service worker controlla o meno la pagina. Con queste informazioni abbiamo potuto segmentare i nostri report per confrontare i risultati con e senza il service worker.

Acquisizione del tempo per la prima colorazione

Alcuni browser registrano il momento esatto in cui il primo pixel viene visualizzato sullo schermo, rendendolo disponibile agli sviluppatori. Questo valore, confrontato con il valore navigationStart esposto tramite l'API Navigation Timing, ci permette di tenere conto in modo molto accurato del tempo trascorso tra la richiesta iniziale della pagina da parte dell'utente e la prima volta in cui ha visualizzato qualcosa.

Come già accennato, il tempo alla prima visualizzazione è una metrica importante da misurare perché è il primo punto in cui un utente rileva la velocità di caricamento del tuo sito. È la prima impressione ricevuta dagli utenti e una buona prima impressione può influire positivamente sul resto dell'esperienza utente.2

Per ottenere il primo valore di visualizzazione 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;
    }
  }
}

Con questo, ora potremmo 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
    });
  }
}

Una volta scritte entrambe le funzioni, il nostro codice di monitoraggio ha il seguente aspetto:

// 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 possono essere o meno già visualizzati sullo schermo. Per assicurarci di eseguire sempre questo codice dopo il primo rendering, abbiamo posticipato la chiamata a sendTimeToFirstPaint() fino al termine dell'evento load. Infatti, 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 fossero in concorrenza 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 segnala firstpaint volte a Google Analytics, ma questo è solo un esempio. Dovevamo comunque monitorare lo stato del service worker; altrimenti non saremmo in grado di confrontare i tempi di first paint di una pagina controllata dai service worker e di una non controllata.

Determinazione dello stato del service worker in corso...

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

  • controllato: un service worker controlla la pagina. Nel caso di IOWA, significa anche che tutte le risorse sono state memorizzate nella cache e la pagina funziona offline.
  • supported: il browser supporta il service worker, ma quest'ultimo non sta ancora controllando la pagina. Questo è lo stato previsto per i visitatori alla prima visita.
  • unsupported: il browser dell'utente non supporta il service worker.
function getServiceWorkerStatus() {
  if ('serviceWorker' in navigator) {
    return navigator.serviceWorker.controller ? 'controlled' : 'supported';
  } else {
    return 'unsupported';
  }
}

Questa funzione ha ottenuto lo stato del service worker per noi; il passaggio successivo è stato associare questo stato ai dati che abbiamo inviato a Google Analytics.

Monitorare i dati personalizzati con le 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 del dispositivo.

Lo stato del service worker non è una dimensione fornita da Google Analytics per impostazione predefinita; Tuttavia, Google Analytics ti dà la possibilità di creare dimensioni personalizzate e definirle come preferisci.

Per IOWA, abbiamo creato una dimensione personalizzata denominata Stato del service worker e 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 appena creata fosse 1, potremmo aggiornare la logica come segue per inviare l'evento firstpaint in modo da includere lo stato del service 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()
});

Funziona, ma lo stato del service worker verrà associato solo a questo particolare evento. Poiché lo stato del service worker è un valore potenzialmente utile per qualsiasi interazione, ti consigliamo di 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 nell'oggetto tracker stesso, prima di inviare dati a Google Analytics.

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

Una volta impostato, questo valore viene inviato con tutti gli hit successivi per il caricamento 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 osservano questo codice potrebbero non sapere a cosa si riferisce dimension1, è sempre meglio creare una variabile che mappa 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 già detto, inviare la dimensione Stato del worker di servizio con ogni hit ci consente di utilizzarla quando generiamo report su qualsiasi metrica.

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

I risultati: risposte alle nostre domande

Dopo aver iniziato a raccogliere dati per rispondere alle nostre domande, potremmo creare un report su questi dati per vedere i risultati. Nota: tutti i dati di Google Analytics mostrati qui rappresentano il traffico web effettivo sul sito IOWA dal 16 al 22 maggio 2016.

La prima domanda è stata: La memorizzazione nella cache dei service worker è più efficace 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 CPC Tempi di caricamento della pagina in varie dimensioni. Questa metrica è adatta a rispondere a questa domanda perché l'evento load viene attivato solo dopo aver scaricato tutte le risorse iniziali. Quindi riflette direttamente il tempo di caricamento totale per tutte le risorse critiche del sito.5

Le dimensioni che abbiamo scelto erano:

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

Per controllare la possibilità che fattori non correlati al worker di servizio stiano alterando i risultati del tempo di caricamento, abbiamo limitato la nostra query a includere solo i browser che supportano i Service worker.

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

"...le visite alla nostra app quando sono controllate da un service worker vengono caricate molto più velocemente rispetto alle visite non controllate..."

Puoi trovare ulteriori dettagli nelle due tabelle seguenti:

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

Forse ti starai chiedendo come sia possibile che un visitatore di ritorno il cui browser supporti il service worker si trovi in uno stato non controllato. Ecco alcune possibili spiegazioni al riguardo:

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

Entrambe queste situazioni sono relativamente rare. Lo possiamo vedere nei dati osservando i valori Esempio di caricamento pagina nella quarta colonna. Nota 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 Posizione Valore evento e filtrato i risultati per includere solo i nostri eventi firstpaint. Abbiamo utilizzato le dimensioni Categoria dispositivo e la dimensione personalizzata Stato del service worker.

Contrariamente a quanto mi sarei aspettato, il service worker su dispositivo mobile ha avuto un impatto molto inferiore sui tempi di visualizzazione della prima visualizzazione rispetto al caricamento complessivo della pagina.

"...il service worker su dispositivo mobile ha avuto un impatto sui tempi di visualizzazione della prima visualizzazione molto inferiore rispetto al caricamento complessivo della pagina."

Per capire perché è successo, dobbiamo approfondire i dati. I valori medi possono essere utili per panoramiche generali e tratti generici, ma per avere un'idea reale di come questi valori si suddividono in una serie di utenti, dobbiamo osservare una distribuzione di firstpaint volte.

Ottenere la distribuzione di una metrica in Google Analytics

Per ottenere la distribuzione di firstpaint volte, abbiamo bisogno di accedere ai singoli risultati per ogni evento. Purtroppo, Google Analytics non semplifica queste operazioni.

Google Analytics ci consente di suddividere un report in base a qualsiasi dimensione desiderata, ma non di suddividere un report in base a metriche. Ciò non vuol dire che sia impossibile, ma significa 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 firstpaint volta) come dimensione personalizzata per l'evento. A questo scopo, abbiamo creato un'altra dimensione personalizzata denominata Valore metrica e 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 consente di visualizzare la distribuzione dei valori arbitrari delle metriche, ma con l'aiuto dell'API Core Reporting di Google Analytics e della libreria dei grafici di Google abbiamo potuto eseguire query sui risultati non elaborati e poi creare personalmente un istogramma.

Ad esempio, è stata utilizzata la seguente configurazione delle richieste API per ottenere una distribuzione di valori firstpaint su computer con un service 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 simili a questo (nota: questi sono solo i primi cinque risultati). I risultati sono ordinati dal più piccolo al più grande, in modo che queste righe rappresentino i tempi più veloci.

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 inglese:

  • Si sono verificati 3 eventi in cui il valore firstpaint era 4 ms
  • Si sono verificati 2 eventi in cui il valore firstpaint è stato pari a 5 ms
  • Si sono verificati 10 eventi in cui il valore firstpaint era 6 ms
  • Si sono verificati 8 eventi in cui il valore firstpaint era 7 ms
  • Si sono verificati 10 eventi in cui il valore di firstpaint value è stato di 8 ms
  • e così via

Da questi risultati possiamo estrapolare il valore firstpaint per ogni singolo evento e creare un istogramma della distribuzione. Abbiamo eseguito questa operazione per ogni query eseguita.

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

Tempo per la prima visualizzazione su computer (supportato)

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

La forma di questa curva è piuttosto tipica delle distribuzioni del tempo di caricamento. Sono messi a confronto con l'istogramma riportato di seguito, che mostra la distribuzione degli eventi First Paint per le visite in cui un service worker controllava la pagina.

Distribuzione tempo per la prima visualizzazione su computer (controllato)

Puoi notare che, quando un service worker controllava la pagina, molti visitatori hanno riscontrato una prima visualizzazione quasi immediata, con una media di 583 ms.

"...quando un service worker controllava la pagina, molti visitatori hanno riscontrato la prima visualizzazione quasi immediata..."

Per avere un'idea migliore del confronto tra queste due distribuzioni, il grafico successivo mostra una visualizzazione unificata delle due distribuzioni. L'istogramma che mostra le visite non controllate dai service worker è sovrapposto all'istogramma che mostra visite controllate ed entrambi sono sovrapposti a un istogramma che mostra entrambe le combinazioni.

Tempo per la prima visualizzazione della distribuzione su computer

Una cosa che ho trovato interessante di questi risultati è che la distribuzione con un service worker controllato presentava ancora una curva a forma di campana dopo il picco iniziale. Mi aspettavo un grande picco iniziale e poi un sentiero graduale in discesa, non mi aspettavo un secondo picco nella curva.

Esaminando la causa, ho scoperto che anche se un service worker può controllare una pagina, il suo thread può essere inattivo. Il browser fa questo per risparmiare risorse: ovviamente non è necessario che ogni service worker per ogni sito visitato sia attivo e pronto all'istante. Questo spiega la coda della distribuzione. Per alcuni utenti, si è verificato un ritardo durante l'avvio del thread del worker di servizio.

Tuttavia, come si può vedere dalla distribuzione, anche con questo ritardo iniziale, i browser con il service worker hanno distribuito i contenuti più velocemente di quelli che passano attraverso la rete.

Ecco com'erano le cose sui dispositivi mobili:

Tempo per la prima visualizzazione della distribuzione su dispositivo mobile

Anche se abbiamo avuto un notevole aumento nei tempi di prima verniciatura quasi immediati, la coda era molto più grande e più lunga. Questo è probabilmente dovuto al fatto che, sui dispositivi mobili, l'avvio di un thread del service worker inattivo richiede più tempo rispetto a quando avviene su desktop. Spiega inoltre perché la differenza tra il tempo medio di firstpaint non è stato così grande come mi aspettavo (esaminato sopra).

"...sui dispositivi mobili, l'avvio di un thread del service worker inattivo richiede più tempo rispetto a quando avviene su desktop."

Di seguito è riportata la suddivisione di queste varianti dei tempi mediani di prima visualizzazione su dispositivi mobili e desktop raggruppate per stato del service worker:

Tempo medio per prima colorazione (ms)
Stato service worker Desktop Dispositivi mobili
Hai controllato 583 1634
Supportata (non controllata) 912 1933

Queste visualizzazioni di distribuzione, 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 danno un'idea migliore dell'impatto dei service worker sul rendimento del nostro sito rispetto alle sole medie.

Altro impatto dei service worker

Oltre all'impatto sulle prestazioni, i service worker influiscono sull'esperienza utente anche in molti altri modi misurabili con Google Analytics.

Accesso offline

I service worker consentono agli utenti di interagire con il sito in modalità offline e, sebbene un qualche tipo di supporto offline sia probabilmente fondamentale per qualsiasi app web progressiva, determinare quanto sia fondamentale nel tuo caso dipende in gran parte dall'utilizzo offline. Ma come possiamo misurarlo?

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

Negli ultimi due anni IOWA ha utilizzato uno script del service worker che rileva gli hit non riusciti in Google Analytics quando l'utente è offline e li riproduce di nuovo 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 abbiamo 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 quasi il 5% degli utenti.

Notifiche push

I Service worker 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 un equilibrio tra l'offerta di valore per gli utenti e i loro infastiditori. Per capire meglio cosa sta succedendo, è 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 la disattivano.

In IOWA, inviavamo solo notifiche relative alla programmazione personalizzata dell'utente, qualcosa che solo gli utenti che hanno eseguito l'accesso potevano creare. Questo limitava il gruppo di utenti che potevano ricevere notifiche per gli utenti che hanno eseguito l'accesso (monitorati tramite una dimensione personalizzata denominata Accesso eseguito) i cui browser supportavano le notifiche push (monitorate tramite un'altra dimensione personalizzata denominata Autorizzazione alle notifiche).

Il seguente report è basato sulla metrica Utenti e sulla nostra dimensione personalizzata Autorizzazione alle notifiche, segmentata in base agli utenti che hanno eseguito l'accesso in un determinato momento 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 di installazione di app

Se un'app web di avanzamento soddisfa i criteri e viene utilizzata di frequente da un utente, quest'ultimo potrebbe visualizzare un banner di installazione dell'app, che invita l'utente ad aggiungere l'app alla schermata Home.

In IOWA, abbiamo monitorato la frequenza con cui questi prompt venivano mostrati all'utente (e se erano 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
    });
  });
});

Tra gli utenti che hanno visto un banner per l'installazione di app, circa il 10% ha scelto di aggiungerlo alla schermata Home.

Possibili miglioramenti del tracciamento (per la prossima volta)

I dati di analisi che abbiamo raccolto da IOWA quest'anno sono stati preziosissimi. Il senno di poi, però, porta sempre alla luce dei vuoti e delle opportunità di miglioramento delle cose per la prossima volta. Dopo aver concluso l'analisi di quest'anno, ecco due cose che vorrei fare in modo diverso e che i lettori che vogliono implementare una strategia simile potrebbero prendere in considerazione:

1. Monitorare altri eventi correlati 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 è stata eseguita in modo asincrono, il punto in cui questi eventi sono stati attivati non corrisponde necessariamente a un momento specifico dell'esperienza di caricamento complessiva.

L'evento principale relativo al caricamento che non abbiamo monitorato (ma che avremmo voluto) è il punto in cui la schermata iniziale è scomparsa e l'utente ha potuto visualizzare i contenuti della pagina.

2. Archivia l'ID client di analisi in IndexedDB

Per impostazione predefinita, analytics.js archivia il campo ID client nei cookie del browser; purtroppo gli script dei service worker non possono accedere ai cookie.

Questo ci ha causato un problema quando abbiamo tentato 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, quindi monitorare l'efficacia del ricoinvolgimento di quella notifica se l'utente faceva clic su di essa e ritornava nell'app.

Anche se siamo riusciti a monitorare l'efficacia delle notifiche in generale tramite il parametro della campagna utm_source, non siamo stati in grado di collegare una particolare sessione di ricoinvolgimento a un determinato utente.

Per aggirare questa limitazione, avremmo potuto archiviare l'ID client tramite IndexedDB nel nostro codice di monitoraggio e quel valore sarebbe stato accessibile allo script del service worker.

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

Il controllo di navigator.onLine consente di sapere se il browser è in grado di connettersi al router o alla rete LAN (Local Area Network), ma non indica necessariamente se l'utente dispone di una connettività reale. E poiché il nostro script del service worker di analisi offline semplicemente ripeteva gli hit non riusciti (senza modificarli o contrassegnarli come non riusciti), probabilmente stavamo sottostimando il nostro utilizzo offline.

In futuro dovremmo tenere traccia sia dello stato di navigator.onLine sia del fatto che l'hit sia stato ripetuto dal service worker a causa di un errore di rete iniziale. Questo ci darà un quadro più preciso dell'effettivo utilizzo offline.

In sintesi

Questo case study ha dimostrato che l'utilizzo del service worker ha effettivamente migliorato le prestazioni di caricamento dell'app web Google I/O su un'ampia gamma di browser, reti e dispositivi. Inoltre, ha dimostrato che quando esamini una distribuzione dei dati di carico su un'ampia gamma di browser, reti e dispositivi, ottieni molte più informazioni su come questa tecnologia gestisce scenari reali e scopri caratteristiche in termini di prestazioni che non ti aspettavi.

Ecco alcuni dei concetti chiave emersi dallo studio IOWA:

  • In media, il caricamento delle pagine è piuttosto veloce quando un service worker controllava la pagina rispetto a quando lo faceva senza un service worker, sia per i visitatori nuovi che per quelli di ritorno.
  • Le visite alle pagine controllate da un service worker sono state caricate quasi istantaneamente per molti utenti.
  • I Service worker, quando inattivi, hanno richiesto un po' di tempo per l'avvio. Tuttavia, un service worker inattivo ha comunque prestazioni migliori di nessun service worker.
  • Il tempo di avvio di un service worker inattivo è stato più lungo sul dispositivo mobile che sul desktop.

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

Se stai implementando il service worker nella tua applicazione, è importante implementare la tua strategia di misurazione in modo da poter valutare le tue prestazioni ed evitare una regressione futura. Se è così, condividi i tuoi 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 dei service worker con quelle del nostro sito con la sola cache HTTP. Poiché stavamo ottimizzando IOWA per il service worker, non abbiamo dedicato molto tempo all'ottimizzazione per la cache HTTP. Se lo avessimo fatto, probabilmente i risultati 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 della modalità di caricamento degli stili e dei contenuti del sito, è possibile che il browser sia in grado di visualizzarli prima che i contenuti o gli stili siano disponibili. In questi casi, firstpaint potrebbe corrispondere a una schermata bianca vuota. Se utilizzi firstpaint, è importante verificare che corrisponda a un punto significativo nel caricamento delle risorse del sito.
  3. Tecnicamente, per acquisire queste informazioni, potremmo inviare un hit a tempo (che per impostazione predefinita non corrisponde all'interazione) anziché un evento. Infatti, gli hit di temporizzazione sono stati aggiunti a Google Analytics appositamente per monitorare metriche di carico come questa; tuttavia, gli hit di tempo vengono sottoposti a un elevato campionamento al momento dell'elaborazione e i loro valori non possono essere utilizzati nei segmenti. Date queste limitazioni attuali, gli eventi diversi dall'interazione rimangono più adatti.
  4. Per capire 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 dei dati di Google Analytics, composto da utenti, sessioni e interazioni (hit). Per ulteriori informazioni, guarda la lezione di Analytics Academy sul modello di dati di Google Analytics.
  5. Non vengono prese in considerazione le risorse caricate tramite caricamento lento dopo l'evento di caricamento.