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 notevolmente più velocemente per i visitatori di ritorno. Ma cosa significano questi guadagni per gli utenti reali? E come puoi misurarlo?

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

Questo case study spiega in che modo IOWA ha utilizzato Google Analytics per rispondere a domande chiave sul rendimento 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 tentando di rispondere sulla base dei dati che raccogli.

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

1. La memorizzazione nella cache del service worker è più efficiente rispetto ai meccanismi di memorizzazione nella cache HTTP esistenti disponibili in tutti i browser?

Ci aspettiamo già un caricamento più rapido delle pagine per i visitatori di ritorno rispetto ai nuovi visitatori, poiché i browser possono memorizzare le richieste nella cache e pubblicarle immediatamente in occasione di visite ripetute.

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

Questa iniziativa sarebbe comunque migliore di quella che già fa il browser per impostazione predefinita? E se sì, quanto migliore? 1

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

In altre parole, quanto è veloce la velocità di caricamento del sito, indipendentemente dai tempi di caricamento effettivi misurati dalle tradizionali metriche di caricamento delle pagine?

Rispondere a domande su come viene percepita un'esperienza non è ovviamente facile e nessuna metrica può rappresentare perfettamente un tale sentiment soggettivo. Detto questo, esistono sicuramente alcune metriche migliori di altre, quindi è importante scegliere quelle giuste.

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 del sito e li rende disponibili tramite metriche come Tempo di caricamento medio della pagina.

Il tempo di caricamento medio della pagina è una buona metrica per rispondere alla prima domanda, ma non è particolarmente indicato per rispondere alla seconda. Per prima cosa, 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, per un sito con una schermata iniziale o un indicatore di caricamento sembra essere molto più veloce rispetto a un sito che mostra soltanto una pagina vuota per diversi secondi.

In IOWA, abbiamo mostrato un'animazione con conto alla rovescia sulla schermata iniziale che (a mio parere) è stata utile per intrattenere l'utente mentre il resto dell'app veniva caricato in background. Per questo motivo, monitorare il tempo necessario per la visualizzazione della schermata iniziale è molto più logico come un modo per misurare le prestazioni percepite del caricamento. Per ottenere questo valore, abbiamo scelto la metrica tempo di visualizzazione per la prima volta.

Una volta individuate le metriche a cui volevamo rispondere e identificato le metriche utili per rispondere, è arrivato 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 nel 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 quali pagine vengono 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 appaiono sullo schermo.
  • Indica 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.

Calcolo del tempo per la prima colorazione

Alcuni browser registrano l'ora esatta in cui il primo pixel viene visualizzato sullo schermo e lo rendono disponibile agli sviluppatori. Questo valore, rispetto al valore navigationStart esposto tramite l'API Navigation Timing, ci offre un resoconto molto accurato di quanto tempo è passato tra la prima richiesta della pagina da parte dell'utente e la prima visualizzazione di qualcosa.

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

Per ottenere il primo valore di disegno 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 non interazione con il valore del tempo per la prima colorazione: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 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 sopra indicato, i pixel potrebbero essere già stati visualizzati sullo schermo. Per assicurarci di eseguire sempre questo codice dopo il primo disegno, 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 al termine del caricamento della pagina per garantire che queste richieste non competono 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 un rapporto firstpaint volte a Google Analytics, ma questo è solo un po'. Dovevamo comunque tenere traccia dello stato dei service worker, altrimenti non avremmo potuto confrontare i primi tempi di colorazione di una pagina controllata dai service worker e di una non controllata.

Determinazione dello stato dei service worker

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

  • controllato: un service worker sta controllando la pagina. Nel caso di IOWA, ciò significa anche che tutti gli asset sono stati memorizzati nella cache e che la pagina funziona offline.
  • supportato: il browser supporta il service worker, ma il service worker non sta ancora controllando la pagina. Questo è lo stato previsto per i nuovi visitatori.
  • 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; il passaggio successivo è stato associare questo stato ai dati che stavamo inviando 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 del dispositivo.

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

Per IOWA, abbiamo creato una dimensione personalizzata denominata Stato del worker di servizi e ne abbiamo impostato l'ambito su hit (ad esempio per interazione).4 A ogni dimensione personalizzata che crei in Google Analytics viene assegnato un indice univoco all'interno di quella 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 nostra 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()
});

Questa operazione andrà a buon fine, ma verrà associato solo lo stato del service worker a questo particolare evento. Poiché lo stato del service worker è 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 i 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, probabilmente verrà restituito un nuovo valore dalla funzione getServiceWorkerStatus(), 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 esegua la mappatura di 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, l'invio della dimensione Stato del service worker con ogni hit ci consente di utilizzarla per i report su qualsiasi metrica.

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

I risultati: la risposta alle nostre domande

Una volta iniziato a raccogliere dati per rispondere alle nostre domande, abbiamo potuto generare un report su tali 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 abbiamo posto è stata: la memorizzazione nella cache del service worker è più efficiente rispetto ai meccanismi esistenti di memorizzazione nella cache HTTP disponibili in tutti i browser?

Per rispondere a questa domanda, abbiamo creato un report personalizzato che mostrava la metrica Tempi medi di caricamento della pagina in varie dimensioni. Questa metrica è particolarmente adatta a rispondere a questa domanda perché l'evento load si attiva solo dopo aver scaricato tutte le risorse iniziali. In questo modo viene indicato direttamente il tempo di caricamento totale per tutte le risorse fondamentali 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 dell'utente al sito o se quest'ultimo torna. Nota: un nuovo visitatore non avrà risorse memorizzate nella cache, mentre un visitatore di ritorno potrebbe farlo.
  • Categoria dispositivo, che ci consente di confrontare i risultati su dispositivi mobili e computer.

Per controllare la possibilità che fattori non correlati ai lavoratori dei servizi influiscano sui nostri risultati relativi al tempo di caricamento, abbiamo limitato la nostra query in modo da 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 un po' più velocemente delle visite non controllate, anche quelle di utenti di ritorno che probabilmente avevano memorizzato nella cache la maggior parte delle risorse della pagina. È inoltre interessante notare che, in media, i visitatori che utilizzano dispositivi mobili con un service worker hanno registrato caricamenti più rapidi rispetto ai nuovi visitatori che utilizzano un computer desktop.

"...le visite alla nostra app quando controllate da un service worker si caricano un po' più velocemente delle visite non controllate..."

Puoi visualizzare ulteriori 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) Dimensione campione
Hai controllato Visitatore di ritorno 2568 30860
Prove di supporto Visitatore di ritorno 3612 1289
Prove di supporto 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) Dimensione campione
Hai controllato Visitatore di ritorno 3760 8162
Prove di supporto Visitatore di ritorno 4843 676
Prove di supporto Nuovo visitatore 6158 5779

Forse ti starai chiedendo come è possibile per un visitatore di ritorno il cui browser supporta il service worker si trovi mai in uno stato non controllato. Ecco alcune possibili spiegazioni per questo problema:

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

Entrambe queste situazioni sono relativamente rare. Lo notiamo nei dati osservando i valori dell'esempio di caricamento pagina nella quarta colonna. Tieni presente che le righe centrali presentano un campione molto più ridotto 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 medio evento e filtrato i risultati in modo da includere solo i nostri eventi firstpaint. Abbiamo utilizzato le dimensioni Categoria dispositivo e la nostra dimensione personalizzata Stato del service worker.

Contrariamente a quanto mi sarei aspettato, il service worker sui dispositivi mobili ha avuto un impatto molto minore sul tempo per la prima colorazione rispetto al caricamento complessivo della pagina.

"...il service worker sui dispositivi mobili ha avuto un impatto molto inferiore in termini di tempo per la prima colorazione rispetto al caricamento complessivo della pagina."

Per capire il motivo, dobbiamo approfondire i dati. Le medie possono essere utili per panoramiche generali e tratti generici, ma per avere un'idea di come questi numeri si dividono in una fascia di utenti, dobbiamo guardare una distribuzione di firstpaint volte.

Ottenere la distribuzione di una metrica in Google Analytics

Per ottenere la distribuzione di firstpaint volte, dobbiamo accedere ai singoli risultati per ogni evento. Purtroppo, Google Analytics non rende tutto questo facile.

Google Analytics ci consente di suddividere un report in base alla dimensione desiderata, ma non di suddividerlo in base alle metriche. Ciò non significa che sia impossibile, significa solo che abbiamo dovuto personalizzare un po' di più l'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 abbiamo aggiornato la logica di monitoraggio di firstpaint nel seguente modo:

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

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

Ad esempio, la seguente configurazione di richieste API è stata utilizzata per ottenere una distribuzione di valori firstpaint su desktop 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, quindi queste righe rappresentano i tempi più rapidi.

Risultati delle risposte dell'API (prime cinque righe)
ga:dimensione2 ga:totalEvents
4 3
5 2
6 10
7 8
8 10

Ecco il significato di questi risultati in inglese:

  • Si sono verificati 3 eventi in cui il valore di firstpaint era di 4 ms
  • Si sono verificati 2 eventi in cui il valore di firstpaint era di 5 ms
  • Si sono verificati 10 eventi con il valore di firstpaint di 6 ms
  • Si sono verificati 8 eventi con il valore di firstpaint di 7 ms
  • Si sono verificati 10 eventi in cui il valore value di firstpaint era 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 ciascuna delle query eseguite.

Ecco l'aspetto della distribuzione su computer con un service worker non controllato (ma supportato):

Tempo per la prima colorazione della distribuzione su computer (supportato)

La durata media di firstpaint per la distribuzione indicata sopra è di 912 ms.

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

Tempo per la distribuzione della prima colorazione su computer (controllato)

Nota 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 che la prima visualizzazione è quasi immediata..."

Per avere un'idea migliore di come si rapportano tra loro queste due distribuzioni, il grafico successivo mostra una vista unita delle due. L'istogramma che mostra le visite dei service worker non controllati è sovrapposto all'istogramma che indica le visite controllate ed entrambe sono sovrapposte a un istogramma che mostra entrambe le visite combinate.

Tempo per la prima colorazione della distribuzione su computer

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

Esaminando la possibile causa del problema, ho scoperto che, anche se un service worker può controllare una pagina, il relativo thread può essere inattivo. Il browser lo fa per salvare risorse, ovviamente non occorre che ogni service worker per ogni sito che hai visitato sia attivo e pronto in un attimo. Questo spiega la coda della distribuzione. Per alcuni utenti si è verificato un ritardo durante l'avvio del thread del service worker.

Come puoi notare dalla distribuzione, però, anche con questo ritardo iniziale, i browser con service worker hanno fornito i contenuti più velocemente rispetto ai browser che attraversano la rete.

Ecco un esempio dell'aspetto sui dispositivi mobili:

Tempo per la distribuzione della prima colorazione su dispositivi mobili

Anche se abbiamo riscontrato un notevole aumento dei tempi di prima verniciatura quasi immediati, la coda era un po' più grande e più lunga. Il motivo è che, sui dispositivi mobili, l'avvio di un thread del service worker inattivo richiede più tempo di quanto avviene sui computer. Spiega inoltre perché la differenza tra la durata media di firstpaint e il tempo medio non era grande come mi aspettavo (discusso sopra).

"...sui dispositivi mobili, l'avvio di un thread del service worker inattivo richiede più tempo di quanto avviene sui computer."

Ecco la suddivisione di queste variazioni dei tempi mediani di prima colorazione su dispositivi mobili e desktop raggruppate per stato del service worker:

Tempo mediano per la prima visualizzazione (ms)
Stato del service worker Computer Dispositivo mobile
Hai controllato 583 1634
Supportato (non controllato) 912 1933

Anche se la creazione di queste visualizzazioni della distribuzione ha richiesto più tempo e più impegno rispetto alla creazione di un report personalizzato in Google Analytics, ci danno un'idea molto più chiara di come i service worker influenzano le prestazioni 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 tuo sito offline e sebbene un qualche tipo di supporto offline sia probabilmente fondamentale per qualsiasi app web progressiva, determinare quanto è 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 è necessario 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 uno scarto 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 avere un'idea di quanto sia comune per un utente essere offline durante l'utilizzo di IOWA, abbiamo creato un segmento che ha scelto come target gli utenti con almeno un'interazione offline. Abbiamo scoperto che era quasi il 5% degli utenti.

Notifiche push

I service worker consentono agli utenti di attivare la ricezione delle notifiche push. In IOWA, gli utenti ricevevano una notifica quando stava per iniziare una sessione della loro pianificazione.

Come per qualsiasi forma di notifica, è importante trovare l'equilibrio tra offrire valore all'utente e infastidirlo. Per capire meglio cosa accade, è importante monitorare se gli utenti attivano la ricezione di queste notifiche, se stanno interagendo con loro quando arrivano e se eventuali utenti che hanno attivato l'opzione in precedenza modificano la loro preferenza e disattivano la funzionalità.

In IOWA, inviavamo solo notifiche relative alla pianificazione personalizzata dell'utente, qualcosa che solo gli utenti che hanno eseguito l'accesso potevano creare. Ciò ha limitato il gruppo di utenti che potevano ricevere notifiche agli utenti che eseguono l'accesso (monitorati tramite una dimensione personalizzata denominata Con accesso eseguito) i cui browser supportavano le notifiche push (monitorate tramite un'altra dimensione personalizzata chiamata Autorizzazione alle notifiche).

Il seguente report si basa sulla metrica Utenti e sulla nostra dimensione personalizzata Autorizzazione alle notifiche, segmentati in base agli utenti che in un determinato momento hanno eseguito l'accesso e i cui browser supportano le notifiche push.

È fantastico vedere che più della metà degli 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 e viene utilizzata di frequente da un utente, quest'ultimo potrebbe visualizzare un banner di installazione dell'app che lo invita ad aggiungere l'app alla schermata Home.

In IOWA, abbiamo monitorato la frequenza con cui queste richieste sono state mostrate all'utente (e se sono state accettate) 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 monitoraggio (per la prossima volta)

I dati analitici che abbiamo raccolto da IOWA quest'anno sono stati preziosi. Ma il retroscena porta sempre a punti di vista e opportunità per migliorare le cose per la prossima volta. Dopo aver concluso l'analisi di quest'anno, ecco due cose che avrei voluto fare in modo diverso e che i lettori che volevano implementare una strategia simile potrebbero prendere in considerazione:

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

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

2. archivia l'ID client di analisi in IndexedDB

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

Questo ha presentato un problema quando abbiamo provato a 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, per poi monitorare l'esito positivo del ricoinvolgimento della notifica se l'utente fa clic sulla notifica e torna nell'app.

Siamo riusciti a monitorare l'efficacia delle notifiche in generale tramite il parametro della campagna utm_source, ma non siamo riusciti a legare una particolare sessione di ricoinvolgimento a un determinato utente.

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

3. Consenti al service worker di generare report sullo stato online/offline

Il controllo di navigator.onLine ti consente di sapere se il browser riesce a connettersi al router o alla local area network, ma non indica necessariamente se l'utente dispone di una connettività reale. Inoltre, poiché il nostro script del service worker di analisi offline ripeteva semplicemente gli hit non riusciti (senza modificarli o contrassegnarli come non riusciti), probabilmente stavamo sottostimando il nostro utilizzo offline.

In futuro dovremmo monitorare sia lo stato di navigator.onLine sia l'eventuale riproduzione dell'hit dal service worker a causa di un errore di rete iniziale. In questo modo potremo avere un quadro più preciso dell'effettivo utilizzo offline.

In sintesi

Questo case study ha dimostrato che l'utilizzo del service worker ha migliorato di fatto le prestazioni di caricamento dell'app web Google I/O su un'ampia gamma di browser, reti e dispositivi. Inoltre, è emerso che quando esamini una distribuzione dei dati di caricamento tra un'ampia gamma di browser, reti e dispositivi, ottieni informazioni molto più dettagliate su come questa tecnologia gestisce scenari reali e scopri caratteristiche di rendimento che potresti non avere previsto.

Ecco alcuni dei concetti chiave dello studio IOWA:

  • In media, le pagine si caricano in media un po' più velocemente quando un service worker controllava la pagina rispetto a quanto accadeva 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.
  • L'avvio dei service worker, quando non attivi, ha richiesto un po' di tempo. Tuttavia, un service worker inattivo ha comunque ottenuto prestazioni migliori di nessun service worker.
  • Il tempo di avvio di un service worker inattivo è stato più lungo sui dispositivi mobili che sul computer.

Sebbene i miglioramenti in termini di prestazioni osservati in una particolare applicazione siano generalmente utili da comunicare alla più ampia comunità di sviluppatori, è importante ricordare che questi risultati sono specifici per il tipo di sito utilizzato da IOWA (un sito di eventi) e per il tipo di pubblico di cui dispone IOWA (soprattutto gli sviluppatori).

Se implementi il service worker nell'applicazione, è importante implementare una tua strategia di misurazione in modo da poter valutare le tue prestazioni ed evitare regressioni future. Se sì, condividi i risultati in modo che tutti possano trarne vantaggio.

Note a piè di pagina

  1. Non è del tutto equo confrontare le prestazioni dell'implementazione della cache del service worker con quelle del nostro sito solo con la cache HTTP. Poiché stavamo ottimizzando IOWA per il service worker, non abbiamo dedicato molto tempo all'ottimizzazione della cache HTTP. Se fosse stato possibile, i risultati sarebbero stati probabilmente diversi. Per scoprire di più sull'ottimizzazione del tuo sito per la cache HTTP, consulta Optimizing Content Efficiently.
  2. A seconda del modo in cui il sito carica gli stili e i contenuti, è possibile che il browser sia in grado di colorare prima che i contenuti o gli stili siano disponibili. In questi casi, firstpaint potrebbe corrispondere a una schermata bianca vuota. Se utilizzi firstpaint, devi assicurarti che corrisponda a un punto significativo del caricamento delle risorse del sito.
  3. Tecnicamente potremmo inviare un hit timing (che per impostazione predefinita non è interazione) per acquisire queste informazioni invece di un evento. Infatti, gli hit di tempo sono stati aggiunti a Google Analytics appositamente per monitorare metriche di caricamento come questa; tuttavia, gli hit di tempo vengono campionati in modo significativo al momento dell'elaborazione e i relativi valori non possono essere utilizzati nei segmenti. Date queste attuali limitazioni, gli eventi diversi dalle interazioni 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. È importante anche capire il modello dei dati di Google Analytics, composto da utenti, sessioni e interazioni (hit). Per saperne di più, guarda la lezione di Analytics Academy sul modello di dati di Google Analytics.
  5. Questo non tiene conto delle risorse caricate lentamente dopo l'evento di caricamento.