Dans cet atelier de programmation, vous apprendrez à utiliser Google Analytics et l'API User Timings pour mesurer les performances réelles de votre site Web ou de votre application, et les optimiser afin d'améliorer l'expérience de vos utilisateurs.
Les outils tels que WebPagetest.org sont un excellent point de départ pour optimiser les performances, mais le véritable test des performances d'un site sera toujours les données réelles provenant de vrais utilisateurs.
Si vous gérez un site Web, il y a de fortes chances que vous utilisiez déjà Google Analytics pour mesurer le trafic, ainsi que des éléments tels que l'utilisation des appareils et des navigateurs. Avec un peu de code supplémentaire, vous pouvez ajouter des métriques de performances.
Points abordés
- Mesurer précisément et efficacement les métriques de performances à l'aide de l'API User Timings
- Envoyer ces données à Google Analytics pour qu'elles puissent être intégrées à vos rapports
Prérequis
- Un navigateur avec une console pour les développeurs
- Serveur Web pour Chrome ou le serveur Web de votre choix
- L'exemple de code
- Un éditeur de texte
- (Facultatif) un compte Google Analytics
Comment allez-vous utiliser ce tutoriel ?
Comment évalueriez-vous votre expérience de création de sites Web ou d'applications ?
Vous pouvez télécharger l'intégralité de l'exemple de code sur votre ordinateur…
Vous pouvez également cloner le dépôt GitHub à partir de la ligne de commande.
git clone https://github.com/googlecodelabs/performance-analytics.git
L'exemple de code est divisé en sous-répertoires qui correspondent à chacune des étapes numérotées de cet atelier de programmation. Vous pouvez l'utiliser pour parcourir facilement l'atelier de programmation ou vérifier que votre implémentation est correcte.
Si vous avez accès à un programme de comparaison, vous pouvez l'utiliser pour voir exactement ce qui a changé d'une étape à l'autre.
Dans cet atelier de programmation, vous allez prendre un seul fichier HTML qui charge les éléments suivants :
- Polices Web
- Les feuilles de style
- Images
- JavaScript
Vous allez écrire du code qui mesure les métriques de performances clés pour chacun de ces types de composants.
Considérations sur les performances des composants
Si vous avez déjà lu des articles sur l'optimisation des performances, vous savez probablement déjà que chacun de ces types de ressources présente ses propres particularités et peut affecter les performances globales perçues de différentes manières.
CSS
Par exemple, les feuilles de style bloquent le rendu de tous les éléments du DOM qui les suivent. Cela signifie que le navigateur doit envoyer une requête pour la feuille de style, la télécharger et l'analyser avant de pouvoir afficher le contenu du DOM qui la suit. Pour cette raison, il est généralement préférable de placer les feuilles de style dans l'élément <head> du document. En raison de la nature bloquante du CSS, il est également souvent recommandé de ne placer que votre CSS critique dans le <head> et de charger le CSS non critique de manière asynchrone par la suite.
JavaScript
JavaScript, en revanche, ne bloque pas le rendu, mais bloque l'analyse et la construction du DOM. Cela est nécessaire, car JavaScript peut modifier le DOM. Cela signifie que chaque fois que le navigateur voit une balise <script> (à l'exception des scripts asynchrones), il doit exécuter le code avant de passer à la balise suivante. Si la balise <script> fait référence à un fichier JavaScript externe, elle doit télécharger et exécuter le code avant de passer à la suite.
C'est pourquoi il est souvent recommandé de charger votre code JavaScript juste avant la balise de fermeture </body>, afin que la majorité du DOM soit disponible le plus rapidement possible.
Polices Web
Si vous chargez des polices Web, vous pouvez également choisir de bloquer le rendu du document jusqu'à ce que la police soit disponible. Dans ce cas, il est essentiel de comprendre combien de temps cela prend réellement pour vos utilisateurs. Il est possible qu'une typographie Web se charge rapidement pour vous, mais très lentement pour la majorité des personnes qui visitent votre site. C'est pourquoi il est si important de mesurer et de prendre des décisions basées sur des données réelles.
Images
Enfin, les images peuvent vraiment donner vie à un site, mais elles sont souvent les plus longues à charger. Il est essentiel de comprendre ce que cela signifie réellement et d'être capable d'identifier toute corrélation entre les schémas d'utilisation et les temps de chargement des pages pour savoir comment optimiser.
La première étape de cet atelier de programmation consiste à examiner l'apparence de la page de démonstration avant d'ajouter du code de mesure des performances.
Pour afficher la démo, créez un dossier et ajoutez-y un fichier nommé index.html. Ensuite, copiez et collez le code ci-dessous dans le fichier 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>Ensuite, ouvrez Web Server for Chrome et démarrez un serveur local dans le répertoire que vous venez de créer. Assurez-vous que l'option "Afficher automatiquement index.html" est cochée.

Vous devriez maintenant pouvoir accéder à http://127.0.0.1:8887/ dans votre navigateur et voir le fichier de démonstration. Voici un exemple :

Une fois la page de démonstration exécutée, prenez le temps d'examiner le code et de voir tous les types d'assets chargés. Au cours des prochaines étapes, vous ajouterez du code pour mesurer le moment où ces éléments sont chargés et peuvent être utilisés par l'utilisateur.
Comme indiqué précédemment dans la section sur les considérations relatives aux performances des composants, le CSS bloque le rendu des éléments DOM ainsi que l'exécution des scripts qui le suivent dans le DOM.
Le fichier de démonstration que vous venez de créer contient le code CSS suivant, qui fait référence à Bootstrap et à quelques styles intégrés.
<!-- 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 -->Étant donné que le CSS bloque à la fois le rendu des éléments DOM et l'exécution des scripts, il est possible de déterminer quand le CSS a fini de bloquer en ajoutant une balise <script> immédiatement après le CSS qui stocke l'heure actuelle.
Vous pouvez le faire en créant une variable et en lui attribuant new Date(), mais grâce à l'API User Timings, il existe un moyen beaucoup plus simple : la méthode performance.mark.
Pour indiquer quand le CSS a fini de bloquer le rendu et l'exécution du script, ajoutez la ligne de code suivante immédiatement avant le commentaire de fermeture <!-- End CSS -->.
<script>performance.mark('css:unblock');</script>La méthode performance.mark crée un code temporel haute résolution à ce moment précis et l'associe au nom transmis à la méthode. Dans ce cas, vous avez nommé le repère "css:unblock".
La méthode performance.mark va de pair avec la méthode performance.measure, qui est utilisée pour calculer la différence de temps entre deux repères (en plus des repères que vous créez, vous pouvez également utiliser ceux que le navigateur crée automatiquement pour les différents points de l'API Navigation Timing).
La fonction utilitaire suivante mesure et renvoie la durée entre une marque que vous avez ajoutée et la marque responseEnd créée par l'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;
}Pour commencer à utiliser cette fonction utilitaire, créez un fichier nommé perf-analytics.js (dans le même répertoire que le fichier index.html), puis copiez-y le code ci-dessus.
Maintenant que cette fonction est définie, vous pouvez l'appeler et transmettre le nom de repère "css:unblock". Pour ne pas interférer avec le chargement d'autres ressources, vous devez différer l'exécution de ces mesures jusqu'à ce que l'événement de chargement de la fenêtre se déclenche.
Une fois que vous avez écrit une fonction pour appeler ce code, votre fichier perf-analytics.js devrait se présenter comme suit :
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;
}Enfin, vous devrez charger le script perf-analytics.js à partir de index.html. Pour ce faire, ajoutez la balise de script suivante à votre document principal. Veillez à l'ajouter en dernier pour qu'il n'interfère pas avec le chargement d'autres ressources.
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->Une fois cette étape terminée, votre code doit correspondre à celui du répertoire 01-css du dépôt de l'atelier de programmation.
Si vous chargez la page dans un navigateur et ouvrez la console de développement, un résultat semblable à celui-ci devrait s'afficher :

Les polices Web sont généralement chargées via une feuille de style externe, comme indiqué dans le fichier de démonstration initial :
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->Comme il s'agit d'une balise <link> vers un fichier CSS, il peut sembler que déterminer quand les polices sont chargées et prêtes à l'emploi est aussi simple que d'ajouter une marque dans une balise <script> immédiatement après la balise <link>, comme à l'étape 1.
Malheureusement, ce n'est pas aussi simple.
Les feuilles de style bloquent l'exécution de JavaScript, car leur contenu est utilisé pour construire le CSSOM. Comme il est possible que le code JavaScript en cours de chargement doive accéder au CSSOM, l'exécution doit être retardée jusqu'à ce que le CSSOM soit entièrement construit.
Le problème est que le navigateur peut construire le CSSOM sans télécharger la police. Cela signifie que si vous ajoutez une marque au DOM via une balise de script intégrée immédiatement après la balise <link> de la feuille de style de la police, il y a de fortes chances que la marque soit ajoutée avant le chargement complet de la police.
Tant que les événements de chargement de police ne sont pas disponibles dans les navigateurs, JavaScript est nécessaire pour déterminer quand une police est réellement active et prête à être utilisée sur la page. Heureusement, le chargement des polices via JavaScript permet également d'améliorer les performances, car il ne nécessite pas de requête de blocage supplémentaire vers un fichier CSS.
La plupart des polices Web (y compris les polices Google Fonts, Typekit et font.com) peuvent être chargées à l'aide du script webfont.js, qui a été développé conjointement par Google et Typekit.
Pour mettre à jour le document principal afin qu'il utilise webfont.js pour charger les polices (plutôt que la balise <link>), remplacez la section des polices du code par ce qui suit :
<!-- 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 -->Il y a deux choses importantes à noter concernant le code ci-dessus :
- Il crée une marque "fonts:active" dans le rappel actif, ce qui vous permet de mesurer ultérieurement le temps nécessaire au chargement des polices.
- La balise
<script>qui charge webfonts.js contient l'attributasync. Elle ne bloque donc pas l'analyse ni le rendu du reste du document (ce qui n'est pas le cas pour les balises<link>).
Bien que les codes ci-dessus créent une marque "fonts:active", la mesure de cette marque et sa consignation dans la console ne sont pas aussi simples que pour la marque "css:unblock". En effet, le chargement des polices se fait désormais de manière asynchrone. Par conséquent, si vous essayez de mesurer la marque "fonts:active" dans le gestionnaire window.onload (comme vous l'avez fait avec "css:unblock"), il est fort probable que la police ne soit pas encore chargée.
Pour résoudre ce problème, vous pouvez créer une promesse qui est résolue une fois la police chargée. La fonction suivante effectue cette opération pour vous. Copiez-le et collez-le dans le fichier 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')
});
}Mettez également à jour le gestionnaire window.onload pour appeler cette nouvelle fonction.
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
};Une fois cette étape terminée, votre code doit correspondre à celui du répertoire 02-fonts du dépôt de l'atelier de programmation.
Si vous chargez la page dans un navigateur et ouvrez la console de développement, un résultat semblable à celui-ci devrait s'afficher :

Savoir quand une image est visible n'est pas aussi simple qu'il n'y paraît. Vous savez, grâce aux étapes précédentes, que les feuilles de style et les balises <script> synchrones peuvent bloquer l'affichage, l'analyse et l'exécution de scripts. Ce que vous ignorez peut-être, c'est qu'aucun d'eux ne bloque le scanner de préchargement du navigateur.
Un scanner de préchargement est implémenté par tous les navigateurs modernes dans le but d'améliorer les performances, même sur les sites qui ne sont pas axés sur les performances et qui contiennent de nombreux éléments bloquants. L'idée est que, même si certains éléments peuvent bloquer l'analyse, le rendu ou l'exécution de scripts, ils ne doivent pas bloquer les téléchargements. Le navigateur analyse donc le fichier HTML avant de commencer à construire le DOM et recherche les éléments qu'il peut commencer à télécharger immédiatement.
En ce qui concerne les images, cela signifie qu'il y a de fortes chances qu'elles soient déjà téléchargées au moment où elles sont ajoutées au DOM. Cela signifie également que le moment où une image est téléchargée n'est pas forcément une bonne métrique de performances. La métrique de performances qui vous intéresse est le moment où une image est visible par l'utilisateur.
Lorsqu'une image est téléchargée avant d'être ajoutée au DOM, le moment où elle devient visible correspond au moment où elle se trouve dans le DOM. En revanche, si une image n'est pas téléchargée avant d'être ajoutée au DOM, elle devient visible lorsque son gestionnaire onload se déclenche.
Par conséquent, pour savoir quand une image est visible, vous devez gérer les deux cas.
Pour ce faire, vous pouvez ajouter des repères dans le gestionnaire onload de chaque image, ainsi que dans une balise <script> intégrée immédiatement après la dernière image du DOM. L'idée est que le repère qui se produit en dernier sera celui qui représente le moment où toutes les images sont visibles.
Pour ajouter des repères lorsque les images sont chargées et lorsqu'elles sont affichées, mettez à jour le code des images dans index.html comme suit :
<!-- 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 -->Étant donné que la méthode performance.measure pour un nom de repère particulier utilisera toujours le dernier repère (si elle trouve plusieurs repères portant le même nom), la fonction utilitaire measureDuration du fichier perf-analytics.js peut être utilisée à cet effet sans aucune modification supplémentaire :
/**
* 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'));
}Ajoutez la fonction ci-dessus au fichier perf-analytics.js, puis mettez à jour le gestionnaire window.onload pour l'appeler :
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
};Une fois cette étape terminée, votre code doit correspondre à celui du répertoire 03-images du dépôt de l'atelier de programmation.
Si vous chargez la page dans un navigateur et ouvrez la console de développement, un résultat semblable à celui-ci devrait s'afficher :

Étant donné que les balises <script> sans attribut async bloquent l'analyse DOM jusqu'à ce qu'elles aient été téléchargées et exécutées, vous pouvez déterminer le moment où tous les scripts ont fini de s'exécuter en ajoutant un repère dans une balise de script intégré immédiatement après le dernier <script> synchrone dans le DOM.
Notez que l'utilisation de gestionnaires onload ne fonctionnera pas dans ce cas, car le navigateur doit exécuter le script après l'avoir chargé, ce qui prend du temps. Un script qui se charge rapidement, mais qui s'exécute lentement peut être tout aussi problématique qu'un script qui se charge lentement.
Pour suivre le moment où tout le code JavaScript est chargé et exécuté dans le document principal, mettez à jour la section JavaScript dans index.html avec le code suivant :
<!-- 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 -->Une marque nommée "js:execute" sera ajoutée immédiatement après le téléchargement et l'exécution des scripts pour les plug-ins jQuery et Bootstrap.
Pour mesurer la durée de cette opération, ajoutez la fonction suivante à 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'));
}Appelez-le ensuite à partir du gestionnaire window.onload :
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};Une fois cette étape terminée, votre code doit correspondre à celui du répertoire 04-javascript du dépôt de l'atelier de programmation.
Si vous chargez la page dans un navigateur et ouvrez la console de développement, un résultat semblable à celui-ci devrait s'afficher :

Tous les navigateurs ne sont pas compatibles avec les promesses JavaScript ni avec les API User Timing. Si vous exécutez le code que vous avez écrit jusqu'à présent dans un navigateur qui n'est pas compatible avec l'une de ces fonctionnalités, des erreurs s'affichent.
Pour y remédier, vous pouvez utiliser la détection de fonctionnalités. Ajoutez l'extrait de code suivant immédiatement avant la section des polices. Cette ligne de code JavaScript détecte la compatibilité avec la méthode performance.mark. Elle doit donc être ajoutée à la page avant que cette méthode ne soit utilisée :
<!-- Start feature detects -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End feature detects -->Ensuite, partout dans index.html où vous appelez performance.mark, préfixez-le avec la détection de fonctionnalité. Voici un exemple qui met à jour le code dans le bloc d'image. Veillez à mettre à jour les autres sections également.
<!-- 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 -->Maintenant que la variable __perf est définie sur window, vous pouvez également l'utiliser dans perf-analytics.js pour vous assurer de ne pas appeler une méthode qui n'est pas prise en charge dans le navigateur actuel.
La fonction measureDuration doit être mise à jour pour ajouter la condition suivante :
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
}
}Enfin, comme tous les navigateurs ne sont pas compatibles avec les promesses JavaScript, la fonction measureWebfontPerfAndFailures doit également être encapsulée dans une conditionnelle :
function measureWebfontPerfAndFailures() {
if (window.Promise) {
// ...
}
}Vous devriez maintenant pouvoir exécuter votre code dans n'importe quel navigateur sans problème.
Une fois cette étape terminée, votre code doit correspondre à celui du répertoire 05-feature-detects du dépôt de l'atelier de programmation.
La dernière étape de cet atelier de programmation consiste à prendre les données qui sont enregistrées dans la console et à les envoyer à Google Analytics. Avant de pouvoir envoyer des données à Google Analytics, vous devez ajouter la bibliothèque analytics.js et l'extrait de code de suivi par défaut à votre page.
Ajoutez le code suivant à index.html après le bloc JavaScript principal, mais avant le chargement du 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 -->Si vous avez déjà ajouté Google Analytics à un site Web, vous savez que vous devez remplacer l'espace réservé "UA-XXXXX-Y " par l'ID de suivi que vous avez reçu lorsque vous avez créé une propriété dans Google Analytics.
L'extrait de code de suivi analytics.js remplit quatre fonctions principales :
- Crée un élément
<script>asynchrone qui télécharge la bibliothèque JavaScript analytics.js. - Initialise une fonction
ga()globale (appelée file d'attente des commandes ga()) qui vous permet de planifier l'exécution des commandes une fois que la bibliothèque analytics.js est chargée et prête à l'emploi. - Ajoute une commande à la file d'attente de commandes
ga()pour créer un objet de suivi pour la propriété spécifiée via le paramètre "UA-XXXXX-Y". - Ajoute une autre commande à la file d'attente de commandes
ga()pour envoyer une page vue à Google Analytics pour la page actuelle.
Bien que les données collectées à partir des vues de page seules soient utiles, elles ne donnent pas une image complète. Pour mieux comprendre l'expérience des utilisateurs sur votre site ou dans votre application, vous devez envoyer des données d'interaction supplémentaires à Google Analytics.
Google Analytics accepte plusieurs types de données d'interaction : pages vues, événements, interactions sociales, exceptions et, enfin, temps utilisateur. Pour envoyer des données de temps utilisateur à Google Analytics, vous pouvez utiliser la signature de commande suivante :
ga('send', 'timing', timingCategory, timingVar, timingValue);Où timingCategory est une chaîne qui vous permet d'organiser les hits de timing dans un groupe logique, timingVar est la variable que vous mesurez et timingValue est la durée réelle en millisecondes.
Pour voir comment cela fonctionne en pratique, l'instruction console.log dans la fonction measureCssUnblockTime peut être mise à jour comme suit :
ga('send', 'timing', 'CSS', 'unblock', measureDuration('css:unblock'));Bien que le code ci-dessus fonctionne dans certaines situations, il existe deux pièges importants à connaître :
- L'étape précédente a mis à jour la fonction
measureDurationpour qu'elle ne s'exécute que si le navigateur est compatible avec l'API User Timings, ce qui signifie qu'elle renverra parfoisundefined. Étant donné qu'il n'y a aucune raison d'envoyer des données non définies à Google Analytics (dans certains cas, cela pourrait même fausser vos rapports), vous ne devez envoyer ce hit de timing que simeasureDurationrenvoie une valeur. - Lorsque
measureDurationrenvoie une valeur, il s'agit d'unDOMHighResTimeStamp, qui aura une précision supérieure à la milliseconde. Étant donné quetimingValuedans Google Analytics doit être un nombre entier, vous devez arrondir la valeur renvoyée parmeasureDuration.
Pour tenir compte de ces pièges, mettez à jour l'instruction return dans la fonction measureDuration afin d'arrondir la valeur renvoyée :
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
return Math.round(measure.duration);
}
}Mettez à jour les commandes de timing pour qu'elles ne s'exécutent que si une valeur existe pour la métrique en question. Par exemple, la fonction measureCssUnblockTime doit être mise à jour comme suit :
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}Vous devrez apporter des modifications similaires à toutes les autres fonctions de mesure. Une fois terminé, le fichier perf-analytics.js final doit se présenter comme suit :
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);
}
}Le fichier index.html final doit se présenter comme suit :
<!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>Si vous chargez cette page et examinez les requêtes dans le panneau réseau, vous verrez quelque chose comme ceci :

C'est utile, mais il peut être fastidieux d'examiner ces données sous forme de requête encodée en URL. Et si, pour une raison quelconque, vous ne voyez pas ces requêtes, il est très difficile de déterminer où l'échec s'est produit.
Lorsque vous développez en local, il est préférable d'utiliser la version de débogage d'analytics.js. Celle-ci enregistre des informations de débogage utiles dans la console à chaque fois qu'une commande analytics.js est exécutée. Si vous
Si vous remplacez l'URL analytics.js dans index.html par analytics_debug.js et que vous ouvrez la console de votre navigateur, vous verrez des instructions semblables à celles-ci :

Maintenant que vous savez comment implémenter la mesure des performances pour cette page de démonstration, vous pouvez essayer de l'ajouter à votre propre site et d'envoyer des données utilisateur réelles à Google Analytics.
Générer des rapports sur les données que vous avez collectées
Après avoir collecté des données sur les performances pendant quelques jours, vous pourrez générer des rapports sur ces données pour obtenir des insights exploitables sur la vitesse de chargement réelle de votre site et de ses ressources pour les utilisateurs.
Pour accéder aux rapports "Timing utilisateur" dans Google Analytics, cliquez sur l'onglet "Rapports" en haut de la page, puis sélectionnez "Comportement > Vitesse du site > Timing utilisateur" dans la barre de navigation latérale (ou suivez les instructions pour afficher le rapport Timing utilisateur dans le centre d'aide).
Lorsque vous chargez le rapport "Timing utilisateur" dans Google Analytics, vous devriez voir les catégories de timing qui correspondent aux données que vous avez envoyées. Cliquez sur l'un d'eux pour afficher des visualisations détaillées de vos données de timing. L'image ci-dessous montre un exemple de temps de chargement des polices sur un site Web réel utilisant Google Fonts au cours des dernières 24 heures.

Félicitations ! Vous avez terminé cet atelier de programmation. Si vous souhaitez aller plus loin, la section suivante vous proposera quelques suggestions pour développer ce code et obtenir encore plus d'informations.
Les métriques de performances abordées dans cet atelier de programmation sont essentielles pour mesurer la façon dont votre site se charge pour les utilisateurs réels, mais elles ne sont qu'un début. Si vous souhaitez approfondir l'analyse des performances, vous pouvez simplement suivre davantage de métriques.
Dans cet atelier de programmation, vous avez suivi les métriques liées à la disponibilité des ressources pour l'utilisateur. Si vous le souhaitez, vous pouvez subdiviser la plupart de ces catégories. Par exemple, au lieu de simplement mesurer quand le code JavaScript a fini de s'exécuter, vous pouvez mesurer quand il a commencé à se charger, quand il a fini de se charger, quand il a commencé à s'exécuter et, enfin, quand il a fini de s'exécuter. Chacune de ces métriques peut révéler un problème que les autres ne permettent pas d'identifier.
En plus d'être plus précis, vous devez également réfléchir de manière plus globale à votre stratégie générale d'analyse des performances. Quels sont les objectifs ? Qu'est-ce que le succès ?
Pour toute analyse, vous devez généralement commencer par poser une question, puis trouver comment utiliser les données pour y répondre.
Par exemple, examinez la liste de questions suivante et réfléchissez à la façon dont vous utiliseriez les connaissances acquises dans cet atelier de programmation pour y répondre à l'aide des données analytiques :
- Les valeurs des métriques que vous suivez diminuent-elles ou augmentent-elles au fil du temps ?
- Comment l'utilisation de la mise en cache hors connexion via un service worker ou un stockage local affecterait-elle les performances globales de votre site ?
- Vos ressources sont-elles chargées de manière optimale ? Autrement dit, y a-t-il un grand écart entre le moment où la ressource est téléchargée et celui où elle est disponible pour être utilisée ?
- Existe-t-il des corrélations entre les performances et les autres métriques que vous suivez (par exemple, le taux d'inscription, le temps passé sur le site, les achats, etc.) ?
Enfin, si vous souhaitez en savoir plus sur les performances Web ou Google Analytics, voici quelques ressources utiles pour vous aider à démarrer :
- Outils et informations pour vous aider à créer des sites Web performants
https://developers.google.com/speed/ - Outils et API permettant aux développeurs d'exploiter la plate-forme Google Analytics
https://developers.google.com/analytics/ - Cours en ligne qui vous apprennent à utiliser le produit Google Analytics lui-même (dispensés par des personnes qui travaillent sur Google Analytics).
https://analyticsacademy.withgoogle.com/