In questo codelab imparerai a utilizzare Google Analytics e l'API User Timing per misurare le prestazioni reali del tuo sito web o della tua applicazione e ottimizzarle per migliorare l'esperienza degli utenti.
Strumenti come WebPagetest.org sono un ottimo punto di partenza per le ottimizzazioni del rendimento, ma il vero test delle prestazioni del sito saranno sempre i dati reali degli utenti effettivi.
Se gestisci un sito web, è molto probabile che tu stia già utilizzando Google Analytics per misurare il traffico, nonché l'utilizzo di dispositivi e browser. Con poche righe di codice aggiuntive, puoi aggiungere le metriche di rendimento.
Obiettivi didattici
- Come misurare in modo accurato ed efficace le metriche relative alle prestazioni utilizzando l'API User Timings
- Come inviare questi dati a Google Analytics in modo che possano essere incorporati nei report
Che cosa ti serve
- Un browser con una console per gli sviluppatori
- Web Server for Chrome o utilizza il tuo web server preferito
- Il codice di esempio
- Un editor di testo
- (Facoltativo) Un account Google Analytics
Come utilizzerai questo tutorial?
Come valuti la tua esperienza di creazione di siti web o applicazioni?
Puoi scaricare tutto il codice di esempio sul tuo computer...
… o clona il repository GitHub dalla riga di comando.
git clone https://github.com/googlecodelabs/performance-analytics.git
Il codice campione è suddiviso in sottodirectory che corrispondono a ciascuno dei passaggi numerati di questo lab di codifica. Puoi utilizzarlo per spostarti facilmente nel codelab o verificare che l'implementazione sia corretta.
Se hai accesso a un programma di confronto, puoi utilizzarlo per vedere esattamente cosa è cambiato da un passaggio all'altro.
In questo lab di programmazione, prenderai un singolo file HTML che carica i seguenti asset:
- Caratteri web
- Fogli di stile
- Immagini
- JavaScript
Scriverai un nuovo codice che misuri le metriche di rendimento chiave per ciascuno di questi tipi di asset.
Considerazioni sul rendimento degli asset
Se hai mai letto qualcosa sull'ottimizzazione del rendimento, probabilmente sai già che ciascuno di questi tipi di asset ha le proprie peculiarità e può influire sul rendimento percepito complessivo in vari modi.
CSS
Ad esempio, i fogli di stile bloccano il rendering di tutti gli elementi nel DOM che li seguono, il che significa che il browser deve effettuare una richiesta per il foglio di stile, scaricarlo e analizzarlo prima di poter eseguire il rendering di qualsiasi contenuto nel DOM che lo segue. Per questo motivo, in genere è meglio inserire i fogli di stile nell'intestazione <head> del documento. A causa della natura di blocco del CSS, spesso è consigliabile inserire solo il CSS critico nella sezione <head> e caricare il CSS non critico in modo asincrono in un secondo momento.
JavaScript
JavaScript, d'altra parte, non blocca il rendering, ma blocca l'analisi e la costruzione del DOM. Ciò è necessario perché JavaScript può modificare il DOM, il che significa che ogni volta che il browser rileva un tag <script> (esclusi gli script asincroni), deve eseguire il codice prima di passare al tag successivo. Se il tag <script> fa riferimento a un file JavaScript esterno, deve scaricare ed eseguire il codice prima di procedere.
Per questo motivo, spesso si consiglia di caricare JavaScript subito prima del tag di chiusura </body>, in modo che la maggior parte del DOM sia disponibile il più rapidamente possibile.
Caratteri web
Se carichi caratteri web, puoi anche scegliere di bloccare il rendering del documento finché il carattere non è disponibile per l'uso. In questo caso, è fondamentale capire quanto tempo impiegano effettivamente gli utenti. Un carattere web potrebbe caricarsi rapidamente per te, ma molto lentamente per la maggior parte degli utenti che visitano il tuo sito. Per questo motivo, la misurazione e le decisioni basate su dati reali sono così importanti.
Immagini
Infine, le immagini possono dare vita a un sito, ma spesso sono anche quelle che richiedono più tempo per il caricamento. Comprendere il significato di questi dati e individuare eventuali correlazioni tra i pattern di utilizzo e i tempi di caricamento delle pagine è fondamentale per capire come ottimizzare.
Il primo passaggio di questo codelab consiste nel visualizzare l'aspetto della pagina demo prima di aggiungere qualsiasi codice di misurazione del rendimento.
Per visualizzare la demo, crea una nuova cartella e aggiungi al suo interno un file denominato index.html. Quindi, copia e incolla il codice riportato di seguito nel file index.html.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Performance Analytics Demo</title>
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<!-- End CSS -->
</head>
<body>
<div class="container">
<!-- Start images -->
<div class="gallery">
<img src="http://lorempixel.com/380/200/animals/1/">
<img src="http://lorempixel.com/380/200/animals/2/">
<img src="http://lorempixel.com/380/200/animals/3/">
</div>
<!-- End images -->
<h1>Performance Analytics Demo</h1>
<p>Real performance data from real users.</p>
</div>
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- End JavaScript -->
</body>
</html>Poi, apri Web Server for Chrome e avvia un server locale nella directory che hai appena creato. Assicurati che la casella di controllo "Mostra automaticamente index.html" sia selezionata.

Ora dovresti essere in grado di andare all'indirizzo http://127.0.0.1:8887/ nel browser e visualizzare il file demo. Il sito dovrebbe avere il seguente aspetto:

Una volta eseguita la pagina demo, dai un'occhiata al codice e vedi tutti i vari tipi di asset caricati. Nei passaggi successivi, aggiungerai il codice per misurare quando questi asset vengono caricati e possono essere utilizzati dall'utente.
Come accennato in precedenza nella sezione relativa alle considerazioni sul rendimento degli asset, il CSS blocca il rendering degli elementi DOM e l'esecuzione degli script che lo seguono nel DOM.
Il file demo che hai appena creato contiene il seguente CSS, che fa riferimento a Bootstrap e ad alcuni stili in linea.
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<!-- End CSS -->Poiché CSS blocca sia il rendering degli elementi DOM sia l'esecuzione degli script, è possibile determinare quando CSS ha terminato il blocco aggiungendo un tag <script> immediatamente dopo il CSS che memorizza l'ora corrente.
Potresti farlo creando una variabile e assegnandole new Date(), ma grazie all'API User Timings, esiste un modo molto più semplice: il metodo performance.mark.
Per indicare quando il CSS ha terminato il blocco del rendering e dell'esecuzione degli script, aggiungi la seguente riga di codice immediatamente prima del commento di chiusura <!-- End CSS -->.
<script>performance.mark('css:unblock');</script>Il metodo performance.mark crea un timestamp ad alta risoluzione in questo momento esatto e lo associa al nome passato al metodo. In questo caso, hai chiamato il segno "css:unblock".
Il metodo performance.mark va di pari passo con il metodo performance.measure, che viene utilizzato per calcolare la differenza di tempo tra due segni (oltre ai segni che fai, puoi anche utilizzare i segni che il browser crea automaticamente per i vari punti dell'API Navigation Timing).
La seguente funzione di utilità misura e restituisce la durata di tempo tra un indicatore che hai aggiunto e l'indicatore responseEnd creato dall'API Navigation Timing.
function measureDuration(mark, opt_reference) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return measure.duration;
}Per iniziare a utilizzare questa funzione di utilità, crea un nuovo file denominato perf-analytics.js (nella stessa directory del file index.html) e copia e incolla il codice riportato sopra.
Ora che questa funzione è definita, puoi chiamarla e passare il nome del segno "css:unblock". Per non interferire con il caricamento di altre risorse, devi posticipare l'esecuzione di queste misurazioni fino a quando non viene attivato l'evento di caricamento della finestra.
Dopo aver scritto una funzione per chiamare questo codice, il file perf-analytics.js dovrebbe avere un aspetto simile al seguente:
window.onload = function() {
measureCssUnblockTime();
};
/**
* Calculates the time duration between the responseEnd timing event and when
* the CSS stops blocking rendering, then logs that value to the console.
*/
function measureCssUnblockTime() {
console.log('CSS', 'unblock', measureDuration('css:unblock'));
}
/**
* Accepts a mark name and an optional reference point in the navigation timing
* API and returns the time duration between the reference point and the last
* mark (chronologically).
* @param {string} mark The mark name.
* @param {string=} opt_reference An optional reference point from the
* navigation timing API. Defaults to 'responseEnd'.
* @return {number} The time duration
*/
function measureDuration(mark, opt_reference) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return measure.duration;
}Infine, dovrai caricare lo script perf-analytics.js da index.html. Per farlo, aggiungi il seguente tag script al documento principale. Assicurati di aggiungerlo per ultimo in modo che non interferisca con il caricamento di altre risorse.
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->Una volta completato questo passaggio, il codice dovrebbe corrispondere a quello presente nella directory 01-css del repository del codelab.
Se carichi la pagina in un browser e apri la console per gli sviluppatori, dovresti visualizzare un output simile al seguente:

I caratteri web vengono in genere caricati tramite un foglio di stile esterno, come mostrato nel file demo iniziale:
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->Poiché si tratta di un tag <link> per un file CSS, potrebbe sembrare che determinare quando i caratteri vengono caricati e sono pronti per l'uso sia semplice come aggiungere un segno all'interno di un tag <script> immediatamente dopo <link>, proprio come nel passaggio 1.
Purtroppo, non è così semplice.
I fogli di stile bloccano l'esecuzione di JavaScript perché i contenuti dei fogli di stile vengono utilizzati per costruire il CSSOM e, poiché è possibile che il codice JavaScript caricato debba accedere al CSSOM, l'esecuzione deve essere ritardata fino a quando il CSSOM non è completamente costruito.
Il problema è che il browser può costruire il CSSOM senza scaricare effettivamente il carattere, il che significa che se aggiungi un segno al DOM tramite un tag dello script incorporato subito dopo il tag <link> del foglio di stile del carattere, è probabile che il segno venga inserito prima che il carattere venga caricato completamente.
Finché gli eventi di caricamento dei caratteri non saranno disponibili nei browser, è necessario JavaScript per determinare quando un carattere è effettivamente attivo e pronto per l'uso nella pagina. Fortunatamente, il caricamento dei caratteri tramite JavaScript migliora anche le prestazioni, in quanto non richiede una richiesta di blocco aggiuntiva a un file CSS.
La maggior parte dei caratteri web (inclusi i caratteri Google, Typekit e font.com) può essere caricata tramite lo script webfont.js, sviluppato congiuntamente da Google e Typekit.
Per aggiornare il documento principale in modo che utilizzi webfont.js per caricare i caratteri (anziché il tag <link>), sostituisci la sezione dei caratteri del codice con quanto segue:
<!-- Start fonts -->
<script>
window.WebFontConfig = {
google: {families: ['Roboto:400,700,400italic']},
timeout: 10000,
active: function() {
performance.mark('fonts:active');
}
};
</script>
<script async src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
<!-- End fonts -->Ci sono due aspetti importanti da notare nel codice riportato sopra:
- Crea un indicatore "fonts:active" nel callback attivo, in modo da poter misurare in un secondo momento il tempo impiegato per caricare i caratteri.
- Il tag
<script>che carica webfonts.js contiene l'attributoasync, quindi non bloccherà l'analisi o il rendering del resto del documento (il che non è vero per i tag<link>).
Sebbene i codici riportati sopra creino un segno "fonts:active", misurare questo segno e registrarlo nella console non è semplice come per il segno "css:unblock". Il motivo è che il caricamento dei caratteri ora avviene in modo asincrono, quindi se provi a misurare il segno "fonts:active" nel gestore window.onload (come hai fatto con "css:unblock"), è molto probabile che il carattere non sia ancora stato caricato.
Per risolvere il problema, puoi creare una promessa che viene risolta una volta caricato il carattere. La seguente funzione esegue questa operazione per te. Copia e incollalo nel file perf-analytics.js:
/**
* Creates a promise that is resolved once the web fonts are fully load or
* is reject if the fonts fail to load. The resolved callback calculates the
* time duration between the responseEnd timing event and when the web fonts
* are downloaded and active. If an error occurs loading the font, this fact
* is logged to the console.
*/
function measureWebfontPerfAndFailures() {
new Promise(function(resolve, reject) {
// The classes `wf-active` or `wf-inactive` are added to the <html>
// element once the fonts are loaded (or error).
var loaded = /wf-(in)?active/.exec(document.documentElement.className);
var success = loaded && !loaded[1]; // No "in" in the capture group.
// If the fonts are already done loading, resolve immediately.
// Otherwise resolve/reject in the active/inactive callbacks, respectively.
if (loaded) {
success ? resolve() : reject();
}
else {
var originalAciveCallback = WebFontConfig.active;
WebFontConfig.inactive = reject;
WebFontConfig.active = function() {
originalAciveCallback();
resolve();
};
// In case the webfont.js script fails to load, always reject the
// promise after the timeout amount.
setTimeout(reject, WebFontConfig.timeout);
}
})
.then(function() {
console.log('Fonts', 'active', measureDuration('fonts:active'));
})
.catch(function() {
console.error('Error loading web fonts')
});
}Aggiorna anche il gestore window.onload per chiamare questa nuova funzione
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
};Una volta completato questo passaggio, il codice dovrebbe corrispondere a quello presente nella directory 02-fonts del repository del codelab.
Se carichi la pagina in un browser e apri la console per gli sviluppatori, dovresti visualizzare un output simile al seguente:

Sapere quando un'immagine è visibile non è così semplice come potrebbe sembrare. Dai passaggi precedenti sai che i fogli di stile e i tag <script> sincroni possono bloccare il rendering, l'analisi e l'esecuzione degli script. Quello che forse non sai è che nessuno dei due blocca lo scanner di precaricamento del browser.
Uno scanner di precaricamento è qualcosa che tutti i browser moderni implementano come uno dei tanti tentativi di migliorare le prestazioni, anche su siti non orientati alle prestazioni che contengono molte risorse di blocco. L'idea è che, sebbene alcuni asset possano bloccare l'analisi, il rendering o l'esecuzione di script, non devono bloccare i download. Pertanto, il browser analizza il file HTML prima di iniziare a creare il DOM e cerca gli asset che può iniziare a scaricare immediatamente.
Per quanto riguarda le immagini, ciò significa che è molto probabile che vengano scaricate prima di essere aggiunte al DOM. Ciò significa anche che il momento in cui un'immagine viene scaricata non è necessariamente una buona metrica sul rendimento. La metrica di rendimento che ti interessa è il momento in cui un'immagine è visibile all'utente.
Quando un'immagine viene scaricata prima di essere aggiunta al DOM, il punto in cui diventa visibile è il punto in cui si trova nel DOM. D'altra parte, se un'immagine non viene scaricata prima di essere aggiunta al DOM, il punto in cui diventa visibile è quando viene attivato il relativo gestore onload.
Pertanto, per sapere quando un'immagine è visibile, devi gestire entrambi i casi.
Puoi farlo aggiungendo dei segni nel gestore onload di ogni immagine e in un tag <script > incorporato subito dopo l'ultima immagine nel DOM. L'idea è che il segno che si verifica per ultimo rappresenti il momento in cui tutte le immagini sono visibili.
Per aggiungere indicatori sia per il caricamento che per il rendering delle immagini, aggiorna il codice delle immagini in index.html nel seguente modo:
<!-- Start images -->
<div class="gallery">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>performance.mark('img:visible')</script>
<!-- End images -->Poiché il metodo performance.measure per un determinato nome di segno utilizza sempre l'ultimo segno (se trova più segni con lo stesso nome), la funzione di utilità measureDuration nel file perf-analytics.js può essere utilizzata per questo senza modifiche aggiuntive:
/**
* Calculates the time duration between the responseEnd timing event and when
* all images are loaded and visible on the page, then logs that value to the
* console.
*/
function measureImagesVisibleTime() {
console.log('Images', 'visible', measureDuration('img:visible'));
}Aggiungi la funzione precedente al file perf-analytics.js, quindi aggiorna il gestore window.onload per chiamarla:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
};Una volta completato questo passaggio, il codice dovrebbe corrispondere a quello presente nella directory 03-images del repository del codelab.
Se carichi la pagina in un browser e apri la console per gli sviluppatori, dovresti visualizzare un output simile al seguente:

Poiché i tag <script> senza l'attributo async bloccano l'analisi DOM finché non sono stati scaricati ed eseguiti, puoi determinare il punto in cui tutti gli script hanno terminato l'esecuzione aggiungendo un segno in un tag script incorporato subito dopo l'ultimo <script> sincrono nel DOM.
Tieni presente che l'utilizzo dei gestori onload non funzionerà in questo caso, poiché il browser deve eseguire lo script dopo averlo caricato e questo richiede tempo. Uno script che si carica rapidamente ma viene eseguito lentamente può essere altrettanto problematico di uno script a caricamento lento.
Per monitorare il caricamento e l'esecuzione di tutto il codice JavaScript nel documento principale, aggiorna la sezione JavaScript in index.html con il seguente codice:
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>performance.mark('js:execute');</script>
<!-- End JavaScript -->Verrà aggiunta un'indicazione denominata "js:execute" subito dopo il download e l'esecuzione degli script per i plug-in di jQuery e Bootstrap.
Per misurare il tempo necessario, aggiungi la seguente funzione a perf-analytics.js:
/**
* Calculates the time duration between the responseEnd timing event and when
* all synchronous JavaScript files have been downloaded and executed, then
* logs that value to the console.
*/
function measureJavaSciptExecutionTime() {
console.log('JavaScript', 'execute', measureDuration('js:execute'));
}e poi invocarlo dal gestore window.onload:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};Una volta completato questo passaggio, il codice dovrebbe corrispondere a quello presente nella directory 04-javascript del repository del codelab.
Se carichi la pagina in un browser e apri la console per gli sviluppatori, dovresti visualizzare un output simile al seguente:

Non tutti i browser supportano le promesse JavaScript o le API User Timing e, se esegui il codice che hai scritto finora in un browser che non supporta una di queste funzionalità, riceverai errori.
Per risolvere questo problema, puoi utilizzare il rilevamento delle funzionalità. Aggiungi il seguente snippet di codice immediatamente prima della sezione dei caratteri. Questa riga di JavaScript rileva il supporto del metodo performance.mark, pertanto deve essere aggiunta alla pagina prima che venga utilizzato:
<!-- Start feature detects -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End feature detects -->Successivamente, in qualsiasi punto di index.html in cui chiami performance.mark, anteponi il rilevamento della funzionalità. Ecco un esempio che aggiorna il codice nel blocco immagine, ma devi assicurarti di aggiornare anche le altre sezioni.
<!-- Start images -->
<div class="gallery">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>__perf && performance.mark('img:visible')</script>
<!-- End images -->Ora che la variabile __perf è impostata su window, puoi utilizzarla anche in perf-analytics.js per assicurarti di non chiamare un metodo non supportato nel browser corrente.
La funzione measureDuration deve essere aggiornata per aggiungere la seguente condizione:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
}
}Infine, poiché non tutti i browser supportano le promesse JavaScript, anche la funzione measureWebfontPerfAndFailures deve essere racchiusa in una condizione:
function measureWebfontPerfAndFailures() {
if (window.Promise) {
// ...
}
}Ora dovresti essere in grado di eseguire il codice in qualsiasi browser senza problemi.
Una volta completato questo passaggio, il codice dovrebbe corrispondere a quello presente nella directory 05-feature-detects del repository del codelab.
L'ultimo passaggio di questo codelab consiste nel prendere i dati registrati nella console e inviarli a Google Analytics. Prima di poter inviare dati a Google Analytics, devi aggiungere alla pagina la libreria analytics.js e lo snippet di monitoraggio predefinito.
Aggiungi il seguente codice a index.html dopo il blocco JavaScript principale, ma prima che venga caricato lo script perf-analytics.js:
<!-- Start analytics tracking snippet -->
<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_debug.js"></script>
<!-- End analytics tracking snippet -->Se hai già aggiunto Google Analytics a un sito web, saprai che devi sostituire il segnaposto "UA-XXXXX-Y" con l'ID monitoraggio che hai ricevuto quando hai creato una nuova proprietà in Google Analytics.
Lo snippet di monitoraggio analytics.js svolge quattro funzioni principali:
- Crea un elemento
<script>asincrono che scarica la libreria JavaScript analytics.js. - Inizializza una funzione globale
ga()(chiamata coda di comandi ga()) che ti consente di pianificare l'esecuzione dei comandi una volta caricata e pronta la libreria analytics.js. - Aggiunge un comando alla coda di comandi
ga()per creare un nuovo oggetto tracker per la proprietà specificata tramite il parametro "UA-XXXXX-Y". - Aggiunge un altro comando alla coda di comandi
ga()per inviare una visualizzazione di pagina a Google Analytics per la pagina corrente.
Sebbene i dati raccolti dalle visualizzazioni di pagina siano utili, non forniscono un quadro completo. Per avere un quadro più preciso dell'esperienza degli utenti sul tuo sito o nella tua applicazione, devi inviare dati di interazione aggiuntivi a Google Analytics.
Google Analytics supporta diversi tipi di dati di interazione: visualizzazioni di pagina, eventi, interazioni social, eccezioni e (ultimo, ma non meno importante) tempistiche utente. Per inviare i dati sul timing degli utenti a Google Analytics, puoi utilizzare la seguente firma del comando:
ga('send', 'timing', timingCategory, timingVar, timingValue);Dove timingCategory è una stringa che ti consente di organizzare gli hit di temporizzazione in un gruppo logico, timingVar è la variabile che stai misurando e timingValue è la durata effettiva in millisecondi.
Per vedere come funziona in pratica, l'istruzione console.log nella funzione measureCssUnblockTime può essere aggiornata nel seguente modo:
ga('send', 'timing', 'CSS', 'unblock', measureDuration('css:unblock'));Sebbene il codice riportato sopra funzioni in alcune situazioni, ci sono due importanti aspetti da tenere presenti:
- Il passaggio precedente ha aggiornato la funzione
measureDurationin modo che venga eseguita solo se il browser supporta l'API User Timings, il che significa che a volte restituiràundefined. Poiché non c'è motivo di inviare dati non definiti a Google Analytics (in alcuni casi potrebbero persino rovinare i report), devi inviare questo hit di temporizzazione solo semeasureDurationrestituisce un valore. - Quando
measureDurationrestituisce un valore, si tratta di unDOMHighResTimeStamp, che avrà una precisione superiore al millisecondo. PoichétimingValuein Google Analytics deve essere un numero intero, devi arrotondare il valore restituito dameasureDuration.
Per tenere conto di questi problemi, aggiorna l'istruzione return nella funzione measureDuration per arrotondare il valore restituito:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
return Math.round(measure.duration);
}
}e aggiorna i comandi di temporizzazione in modo che vengano eseguiti solo se esiste un valore per la metrica in questione. Ad esempio, la funzione measureCssUnblockTime deve essere aggiornata in modo simile al seguente:
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}Dovrai apportare aggiornamenti simili a tutte le altre funzioni di misurazione. Al termine, il file perf-analytics.js finale dovrebbe avere il seguente aspetto:
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};
/**
* Calculates the time duration between the responseEnd timing event and when
* the CSS stops blocking rendering, then sends this measurement to Google
* Analytics via a timing hit.
*/
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* the web fonts are downloaded and active, then sends this measurement to
* Google Analytics via a timing hit. If an error occurs loading the font, an
* error event is sent to Google Analytics.
*/
function measureWebfontPerfAndFailures() {
if (window.Promise) {
new Promise(function(resolve, reject) {
var loaded = /wf-(in)?active/.exec(document.documentElement.className);
var success = loaded && !loaded[1]; // No "in" in the capture group.
if (loaded) {
success ? resolve() : reject();
}
else {
var originalAciveCallback = WebFontConfig.active;
WebFontConfig.inactive = reject;
WebFontConfig.active = function() {
originalAciveCallback();
resolve();
};
// In case the webfont.js script failed to load.
setTimeout(reject, WebFontConfig.timeout);
}
})
.then(function() {
var fontsActiveTime = measureDuration('fonts:active');
if (fontsActiveTime) {
ga('send', 'timing', 'Fonts', 'active', fontsActiveTime);
}
})
.catch(function() {
ga('send', 'event', 'Fonts', 'error');
});
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* all images are loaded and visible on the page, then sends this measurement
* to Google Analytics via a timing hit.
*/
function measureImagesVisibleTime() {
var imgVisibleTime = measureDuration('img:visible');
if (imgVisibleTime) {
ga('send', 'timing', 'Images', 'visible', imgVisibleTime);
}
}
/**
* Calculates the time duration between the responseEnd timing event and when
* all synchronous JavaScript files are downloaded and executed, then sends
* this measurement to Google Analytics via a timing hit.
*/
function measureJavaSciptExecutionTime() {
var jsExecuteTime = measureDuration('js:execute');
if (jsExecuteTime) {
ga('send', 'timing', 'JavaScript', 'execute', jsExecuteTime);
}
}
/**
* Accepts a mark name and an optional reference point in the navigation timing
* API and returns the time duration between the reference point and the last
* mark (chronologically). The return value is rounded to the nearest whole
* number to be compatible with Google Analytics.
* @param {string} mark The mark name.
* @param {string=} opt_reference An optional reference point from the
* navigation timing API. Defaults to 'responseEnd'.
* @return {?number} The time duration as an integer or undefined if no
* matching marks can be found.
*/
function measureDuration(mark, opt_reference) {
if (window.__perf) {
var reference = opt_reference || 'responseEnd';
var name = reference + ':' + mark;
// Clears any existing measurements with the same name.
performance.clearMeasures(name);
// Creates a new measurement from the reference point to the specified mark.
// If more than one mark with this name exists, the most recent one is used.
performance.measure(name, reference, mark);
// Gets the value of the measurement just created.
var measure = performance.getEntriesByName(name)[0];
// Returns the measure duration.
return Math.round(measure.duration);
}
}Il file index.html finale dovrebbe avere il seguente aspetto:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Performance Analytics Demo</title>
<!-- Start navigation timing feature detect -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End navigation timing feature detect -->
<!-- Start fonts -->
<script>
window.WebFontConfig = {
google: {families: ['Roboto:400,700,400italic']},
timeout: 10000,
active: function() {
__perf && performance.mark('fonts:active');
}
};
</script>
<script async src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
<!-- End fonts -->
<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
body { font-family: Roboto, sans-serif; margin: 1em; }
img { float: left; height: auto; width: 33.33%; }
.gallery { overflow: hidden; }
</style>
<script>__perf && performance.mark('css:unblock');</script>
<!-- End CSS -->
</head>
<body>
<div class="container">
<!-- Start images -->
<div class="gallery">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
<img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>__perf && performance.mark('img:visible')</script>
<!-- End images -->
<h1>Performance Analytics Demo</h1>
<p>Real performance data from real users.</p>
</div>
<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>__perf && performance.mark('js:execute');</script>
<!-- End JavaScript -->
<!-- Start analytics tracking snippet -->
<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>
<!-- End analytics tracking snippet -->
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->
</body>
</html>Se carichi questa pagina e dai un'occhiata alle richieste nel riquadro di rete, vedrai qualcosa di simile a quanto segue:

Questi dati sono utili, ma può essere difficile esaminarli come richiesta codificata in URL. E se per qualsiasi motivo non vedi queste richieste, è davvero difficile capire dove si è verificato l'errore.
Un approccio migliore durante lo sviluppo locale è utilizzare la versione di debug di analytics.js, che registra informazioni di debug utili nella console ogni volta che viene eseguito un comando analytics.js. Se
Se aggiorni l'URL analytics.js in index.html a analytics_debug.js e apri la console del browser, vedrai stampate istruzioni simili a queste:

Ora che hai capito come implementare la misurazione del rendimento per questa pagina demo, puoi provare ad aggiungerla al tuo sito e inviare dati reali degli utenti a Google Analytics.
Generazione di report sui dati raccolti
Dopo aver raccolto i dati sul rendimento per alcuni giorni, potrai generare report su questi dati per ottenere informazioni utili sulla velocità di caricamento effettiva del tuo sito e delle sue risorse per gli utenti reali.
Per accedere ai report User Timing in Google Analytics, fai clic sulla scheda Report in alto e seleziona "Comportamento > Velocità del sito > User Timing" dalla navigazione della barra laterale (o segui le istruzioni per visualizzare il report User Timing dal Centro assistenza).
Quando carichi il report User Timings in Google Analytics, dovresti essere in grado di visualizzare le categorie di timing corrispondenti ai dati che hai inviato. Fai clic su uno di questi per visualizzare visualizzazioni dettagliate dei dati di temporizzazione. L'immagine seguente mostra un esempio dei tempi di caricamento dei caratteri su un sito web reale che utilizza Google Fonts nelle ultime 24 ore.

Complimenti! Hai completato correttamente questo codelab. Se vuoi approfondire, nella sezione successiva troverai alcuni suggerimenti su come utilizzare questo codice per ottenere informazioni ancora più dettagliate.
Le metriche sul rendimento trattate in questo codelab sono fondamentali per misurare il caricamento del tuo sito per gli utenti reali, ma sono solo l'inizio. Se vuoi approfondire l'analisi del rendimento, un passo successivo semplice è monitorare più metriche.
In questo lab di programmazione hai monitorato le metriche relative al momento in cui le risorse erano disponibili per l'utente. Se vuoi, puoi analizzare ulteriormente la maggior parte di questi dati. Ad esempio, anziché misurare solo quando l'esecuzione di JavaScript è terminata, potresti misurare quando è iniziato il caricamento, quando è terminato, quando è iniziata l'esecuzione e infine quando è terminata. Ognuna di queste metriche potrebbe rivelare un problema che una sola metrica non potrebbe indicare.
Oltre a ottenere una maggiore granularità, dovresti anche pensare in modo più olistico alla tua strategia generale di analisi del rendimento. Quali sono gli obiettivi? Che cos'è il successo?
Quando si tratta di analisi, in genere si inizia con una domanda e poi si cerca di capire come utilizzare i dati per rispondere.
Ad esempio, considera il seguente elenco di domande e come utilizzeresti le conoscenze acquisite in questo codelab per utilizzare Analytics per rispondere:
- I valori delle metriche che monitori diminuiscono o aumentano nel tempo?
- In che modo l'utilizzo della memorizzazione nella cache offline tramite service worker o spazio di archiviazione locale influisce sul rendimento complessivo del tuo sito?
- Le risorse vengono caricate in modo ottimale? Ad esempio, c'è un grande divario tra il momento in cui la risorsa viene scaricata e il momento in cui è disponibile per l'uso?
- Esistono correlazioni tra il rendimento e altre metriche che monitori (ad es. tasso di registrazione, tempo sul sito, acquisti e così via)?
Infine, se vuoi saperne di più sul rendimento web o su Google Analytics, ecco alcune risorse utili per iniziare:
- Strumenti e informazioni per aiutarti a creare siti web ad alto rendimento
https://developers.google.com/speed/ - Strumenti e API per gli sviluppatori per sfruttare la piattaforma Google Analytics
https://developers.google.com/analytics/ - Corsi online che insegnano a utilizzare il prodotto Google Analytics (tenuti da persone che lavorano su Google Analytics).
https://analyticsacademy.withgoogle.com/