Mesurer les métriques de performances critiques avec Google Analytics

Dans cet atelier de programmation, vous allez apprendre à utiliser Google Analytics et l'API User Timings afin de mesurer les performances réelles de votre site Web ou de votre application, et de les optimiser afin d'améliorer l'expérience des utilisateurs.

Des outils comme WebPagetest.org sont un bon point de départ pour l'optimisation des performances, mais le véritable test des performances du site sera toujours effectué à partir de données réelles provenant d'utilisateurs réels.

Si vous gérez un site Web, vous utilisez déjà Google Analytics pour mesurer le trafic ainsi que l'utilisation du navigateur et des appareils. Avec un peu plus de code, vous pouvez ajouter des métriques de performances à votre mix.

Points abordés

  • Mesurer avec précision les métriques de performances à l'aide de l'API User Timings
  • Envoyer ces données à Google Analytics pour les intégrer dans vos rapports

Ce dont vous avez besoin

Comment allez-vous utiliser ce tutoriel ?

Je vais le lire uniquement Je vais le lire et effectuer les exercices

Comment évalueriez-vous votre niveau d'expérience en matière de création de sites ou d'applications ?

Débutant Intermédiaire Compétent

Vous pouvez télécharger l'intégralité de l'exemple de code sur votre ordinateur...

Télécharger le fichier ZIP

...ou 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 correspondant à chacune des étapes numérotées de cet atelier de programmation. Vous pouvez l'utiliser pour passer facilement de l'atelier de programmation à l'autre ou vérifier que votre implémentation est correcte.

Si vous avez accès à un programme différent, vous pouvez l'utiliser pour voir exactement ce qui est passé d'une étape à l'autre.

Dans cet atelier de programmation, vous allez utiliser un seul fichier HTML pour charger les éléments suivants:

  • Polices Web
  • Feuilles de style
  • Images
  • JavaScript

Vous allez rédiger un nouveau code qui mesure les métriques de performances clés pour chacun de ces types d'éléments.

Points à prendre en compte pour les performances de l'élément

Si vous avez déjà lu des articles sur l'optimisation des performances, vous savez sans doute que chacun de ces types d'assets présente des particularités différentes et qu'il peut avoir un impact sur les performances globales perçues de différentes manières.

CSS

Par exemple, les feuilles de style bloquent l'affichage de tous les éléments qui les suivent, ce qui signifie que le navigateur doit demander la feuille de style, la télécharger et l'analyser avant de pouvoir afficher le contenu qui en découle. C'est pourquoi il est généralement préférable d'insérer des feuilles de style dans la partie <tête> du document. De plus, en raison du blocage de CSS, il est souvent recommandé de ne placer le code CSS important que dans le <head> et de charger le CSS non critique de manière asynchrone par la suite.

JavaScript

En revanche, JavaScript ne bloque pas le rendu, mais bloque l'analyse et la construction du DOM. Cette opération est nécessaire, car JavaScript peut modifier le DOM. Ainsi, chaque fois que le navigateur verra 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 continuer.

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 l'affichage du document jusqu'à ce qu'il soit disponible. Dans ce cas, il est essentiel de comprendre combien de temps cela prend réellement pour vos utilisateurs. Le chargement d'une police Web peut être rapide, mais très lent pour la plupart des visiteurs de votre site. C'est pourquoi il est si important d'effectuer des mesures et de prendre des décisions sur des données réelles.

Images

Enfin, les images peuvent rendre un site plus vivant, mais elles prennent souvent le plus de temps pour se charger. Pour comprendre comment optimiser les performances, il est essentiel de comprendre ce que cela signifie et de pouvoir identifier les corrélations entre les modèles d'utilisation et les temps de chargement des pages.

La première étape de cet atelier de programmation consiste à voir à quoi ressemble la page de démonstration avant d'ajouter un code de mesure des performances.

Pour afficher la version de démonstration, créez un dossier et ajoutez-y un fichier nommé index.html. Ensuite, copiez le code ci-dessous et collez-le 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 le serveur Web pour Chrome et démarrez un serveur local dans le répertoire que vous venez de créer. Assurez-vous que l'option "afficher automatiquement" le fichier index.html".

Capture d&#39;écran 2016-05-11 à 1.03.43 PM.png

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

Capture d&#39;écran 2016-05-11 à 10.59.03 AM.png

Une fois que la page de démonstration est en cours d'exécution, examinez le code et observez les différents types d'éléments en cours de chargement. Lors des prochaines étapes, vous allez ajouter du code pour mesurer le chargement de ces éléments et les interactions avec l'utilisateur.

Comme indiqué dans la section sur les considérations liées aux performances des éléments plus tôt, le CSS bloque l'affichage des éléments DOM ainsi que l'exécution des scripts qui en suivent.

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 code CSS bloque à la fois l'affichage des éléments DOM et l'exécution des scripts, il est possible de déterminer quand le code CSS est bloqué en ajoutant une balise <script> immédiatement après le code CSS qui stocke l'heure actuelle.

Pour ce faire, créez une variable et attribuez-lui new Date(), mais grâce à l'API User Timings, la méthode performance.mark est beaucoup plus simple.

Pour indiquer quand le code CSS a fini de bloquer le rendu et l'exécution du script, ajoutez la ligne de code suivante juste avant le commentaire <!-- End CSS --> fermant.

<script>performance.mark('css:unblock');</script>

La méthode performance.mark crée un horodatage haute résolution à ce moment précis et l'associe au nom qui lui a été transmis. Dans ce cas, vous avez nommé la marque &cst:unblock".

La méthode performance.mark va de pair avec la méthode performance.measure, qui permet de calculer le décalage entre deux marques : en plus des marques que vous créez, vous pouvez utiliser les marques automatiquement créées par le navigateur pour les différents points dans l'API Navigation Timing.

La fonction utilitaire suivante mesure et renvoie la durée entre un repère que vous avez ajouté et le repère responseEnd créé 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) et copiez-collez le code ci-dessus dans celui-ci.

Maintenant que cette fonction est définie, vous pouvez l'appeler et transmettre le nom &css:unblock" Pour éviter toute interférence avec une autre charge de ressources, vous devez reporter l'exécution de ces mesures jusqu'au déclenchement de l'événement de chargement de la fenêtre.

Une fois que vous avez écrit une fonction pour appeler ce code, votre fichier perf-analytics.js doit 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 devez charger le script perf-analytics.js à partir de index.html. Pour ce faire, ajoutez la balise de script suivante à votre document principal. Ajoutez-la en dernier afin 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 à ce qui figure dans le 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, vous devriez obtenir le résultat suivant:

Capture d&#39;écran 17/05/2016 à 11/13/02

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

Étant donné qu'il s'agit d'une balise <link> dans un fichier CSS, il peut sembler simple de déterminer quand les polices sont chargées et prêtes à être utilisées. Il suffit de l'ajouter 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 créer le CSSOM. Comme il est possible que le chargement du code JavaScript soit nécessaire pour accéder au CSSOM, l'exécution doit être retardée jusqu'à ce que le CSSOM soit entièrement créé.

En principe, le navigateur peut créer le CSSOM sans télécharger la police. Cela signifie que si vous ajoutez une marque via un tag de script intégré au DOM immédiatement après la balise de style &la;feuille <lien>, la marque risque d'apparaître avant le chargement complet de la police.

Jusqu'à ce que les événements de chargement de police soient disponibles dans les navigateurs, JavaScript est nécessaire pour déterminer si 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 cette opération ne nécessite pas de demande de blocage supplémentaire pour un fichier CSS.

La plupart des polices Web (y compris les polices Google Fonts, typekit et font.com) peuvent être chargées via le script webfont.js, codéveloppé par Google et Typekit.

Pour mettre à jour le document principal afin d'utiliser webfont.js afin de charger les polices (plutôt que le tag <link>), remplacez la section des polices dans le code comme 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 -->

Voici deux points importants à noter concernant le code ci-dessus:

  • Un repère &fonts:active&quot est créé dans le rappel actif pour que vous puissiez mesurer la durée de chargement des polices.
  • La balise <script> qui charge webfonts.js contient l'attribut async. Elle ne bloque donc pas l'analyse ni le rendu du reste du document (ce qui n'est pas vrai pour les balises <link>).

Même si les codes ci-dessus créent une marque ("fonts:active"), mesurer cette marque et la consigner dans la console n'est pas aussi simple que pour la marque &css:unblock" En effet, le chargement de la police est désormais asynchrone. Par conséquent, si vous essayez de mesurer les valeurs de police (actives) dans le gestionnaire window.onload (comme vous l'avez fait avec &cst:unblock"), il est très probable que la police ne soit pas encore chargée.

Pour résoudre ce problème, vous pouvez créer une promesse qui sera résolue une fois la police chargée. La fonction suivante s'en charge. 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 à ce qui figure dans le 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, vous devriez obtenir le résultat suivant:

Capture d&#39;écran 17/05/2016 à 11/13/22

Il n'est pas aussi facile de savoir quand une image est visible que c'est le cas. À l'étape précédente, vous savez que les feuilles de style et les balises <script> synchrones peuvent bloquer l'affichage, l'analyse et l'exécution du script. Vous ne savez peut-être pas qu'aucune de ces options ne bloque le scanner de préchargement du navigateur.

Un scanner de préchargement est un élément que tous les navigateurs récents implémentent parmi les nombreuses tentatives d'amélioration des performances, même sur des sites qui ne proposent pas de solution proposant de nombreux éléments bloquants. Même si certains éléments peuvent bloquer l'analyse, l'affichage ou l'exécution des scripts, ils n'ont pas besoin de bloquer les téléchargements. Le navigateur analyse le fichier HTML avant de commencer à créer le DOM et recherche les éléments qu'il peut commencer à télécharger immédiatement.

En ce qui concerne les images, il est probable qu'elles aient déjà été téléchargées au moment où elles sont ajoutées au DOM. Cela signifie également que le point de téléchargement d'une image n'est pas nécessairement une bonne métrique de performances. La métrique de performance à laquelle vous devez vous intéresser est le point à partir duquel une image est visible par l'utilisateur.

Lorsqu'une image est téléchargée avant d'être ajoutée au DOM, c'est à ce moment-là qu'elle devient visible. En revanche, si une image n'est pas téléchargée avant son ajout au DOM, son point de vue est le moment où son gestionnaire onload se déclenche.

Pour savoir quand une image est visible, vous devez gérer les deux cas.

Pour ce faire, ajoutez des marques dans chaque gestionnaire d'événements image et dans un tag <script> intégré juste après la dernière image du DOM. L'idée est que la marque qui apparaît en dernier sera la marque lorsque toutes les images seront visibles.

Pour ajouter des marques à la fois lors du chargement des images et lors de leur rendu, mettez à jour le code des images dans index.html:

<!-- 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 d'un nom de marque particulier utilise toujours le dernier repère (si elle trouve plusieurs marques portant le même nom), la fonction utilitaire measureDuration peut être utilisée dans le fichier perf-analytics.js sans 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 à ce qui figure dans le 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, vous devriez obtenir le résultat suivant:

Capture d&#39;écran 17/05/2016 à 11/13/39

Étant donné que les balises <script> sans l'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 point d'exécution de tous les scripts en ajoutant une marque dans une balise de script intégré immédiatement après la dernière <script> synchrone dans le DOM.

Notez que l'utilisation des gestionnaires onload ne fonctionne pas dans ce cas, car le navigateur doit exécuter le script après l'avoir chargé, ce qui prend du temps. L'exécution d'un script qui se charge rapidement, mais qui est lente peut aussi être médiocre.

Pour savoir quand tout JavaScript est chargé et exécuté dans le document principal, mettez à jour la section JavaScript de 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 -->

Cette opération entraîne l'ajout d'une marque ""js:execute&quot" immédiatement après que les scripts des plug-ins jQuery et Bootstrap's ont été téléchargés et terminés de s'exécuter.

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 du gestionnaire window.onload:

window.onload = function() {
  measureCssBlockTime();
  measureWebfontPerfAndFailures();
  measureImagesVisibleTime();
  measureJavaSciptExecutionTime();
};

Une fois cette étape terminée, votre code doit correspondre à ce qui figure dans le 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, vous devriez obtenir le résultat suivant:

Capture d&#39;écran 17/05/2016 à 11/14/03

Tous les navigateurs ne sont pas compatibles avec les promesses JavaScript ou les API User Timing, et si vous exécutez le code que vous avez écrit jusqu'à présent dans un navigateur sans prendre en charge l'une de ces fonctionnalités, vous obtiendrez des erreurs.

Pour résoudre ce problème, vous pouvez utiliser la détection de fonctionnalités. Ajoutez le code suivant juste avant la section des polices. Cette ligne de JavaScript détecte la compatibilité avec la méthode performance.mark. Vous devez donc l'ajouter à 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, n'importe où dans index.html où vous appelez performance.mark, ajoutez le préfixe avec la fonctionnalité de détection de caractéristiques. Voici un exemple de mise à jour du code dans le bloc d'images, mais vous devez aussi mettre à jour les autres sections.

<!-- 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 que vous n'appelez pas une méthode non compatible avec 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 les navigateurs ne sont pas compatibles avec les promesses JavaScript, la fonction measureWebfontPerfAndFailures doit aussi être encapsulée dans une condition:

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 à ce qui figure dans le répertoire 05-feature-detects du dépôt de l'atelier de programmation.

La dernière étape de cet atelier de programmation consiste à consigner les données dans la console afin de 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&quot" par l'ID de suivi que vous avez reçu lors de la création d'une propriété dans Google Analytics.

L'extrait de code de suivi analytics.js effectue quatre opérations principales:

  • Il 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 de commande ga()) qui vous permet de programmer l'exécution des commandes une fois la bibliothèque analytics.js 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 commande à la file d'attente de commandes ga() pour envoyer une page vue à Google Analytics pour la page active.

Même si les données collectées à partir des pages vues seules sont utiles, elles n'indiquent pas l'intégralité de l'histoire. Pour mieux comprendre la façon dont les internautes utilisent votre site ou votre application, vous devez envoyer des données d'interaction supplémentaires à Google Analytics.

Google Analytics accepte plusieurs types de données d'interaction: les pages vues, les événements, les interactions sur les réseaux sociaux, les exceptions et, enfin, les temps de navigation. Pour envoyer des données de temps utilisateur à Google Analytics, vous pouvez utiliser la signature de commande suivante:

ga('send', 'timing', timingCategory, timingVar, timingValue);

timingCategory est une chaîne qui vous permet d'organiser les appels temporels 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, vous pouvez mettre à jour l'instruction console.log de la fonction measureCssUnblockTime comme suit:

ga('send', 'timing', 'CSS', 'unblock', measureDuration('css:unblock'));

Le code ci-dessus peut fonctionner dans certaines situations, mais vous devez tenir compte de deux points importants:

  • À l'étape précédente, la fonction measureDuration a été mise à jour pour s'exécuter uniquement si le navigateur est compatible avec l'API User Timings, ce qui signifie qu'elle renvoie parfois undefined. Étant donné qu'il n'y a aucune raison d'envoyer des données non définies à Google Analytics (dans certains cas, cela risque de commettre des erreurs dans vos rapports), vous ne devez envoyer cet appel de durée que si measureDuration affiche une valeur.
  • Lorsque measureDuration renvoie une valeur, il s'agit d'un élément DOMHighResTimeStamp dont la précision est supérieure à la milliseconde. timingValue dans Google Analytics doit être un entier. Vous devez donc arrondir la valeur renvoyée par measureDuration.

Pour tenir compte de ces erreurs, mettez à jour l'instruction de retour dans la fonction measureDuration afin d'arrondir la valeur renvoyée:

function measureDuration(mark, opt_reference) {
  if (window.__perf) {
    // ...
    return Math.round(measure.duration);
  }
}

De plus, mettez à jour les commandes de synchronisation 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 les mêmes modifications à toutes les autres fonctions de mesure. Une fois le processus terminé, le fichier final perf-analytics.js doit ressembler à ceci:

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 observez les requêtes dans le panneau "Network", vous verrez ce qui suit:

Capture d&#39;écran 2016-05-10 à 18:57.23 PM.png

C'est utile, mais il peut être fastidieux de considérer ces données comme une requête encodée en URL. Si, pour une raison ou pour une autre, ces demandes ne s'affichent pas, il vous sera très difficile de savoir où l'échec s'est produit.

Lors du développement en local, il est préférable d'utiliser la version de débogage d'analytics.js, qui enregistre les informations de débogage utiles dans la console lors de l'exécution de chaque commande analytics.js.

Mettez à jour l'URL analytics.js dans index.html pour ouvrir analytics_debug.js, puis ouvrez la console de votre navigateur. Les instructions se présentent comme suit:

Capture d&#39;écran 2016-05-10 à 18:54.13 PM.png

Maintenant que vous savez comment mettre en œuvre 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.

Créer des rapports sur les données que vous collectez

Une fois que vous aurez collecté des données sur les performances pendant quelques jours, vous pourrez générer des rapports sur ces données afin d'obtenir des informations exploitables concernant la vitesse à laquelle votre site et ses ressources se chargent pour les utilisateurs réels.

Pour accéder aux rapports sur le temps utilisateur dans Google Analytics, cliquez sur l'onglet "Création de rapports" en haut, puis sélectionnez "Comportement &gt", "Vitesse du site &gt" et "Temps utilisateur" dans la barre de navigation latérale (ou suivez les instructions pour afficher le rapport Temps utilisateur dans le centre d'aide).

Lorsque vous chargez ce rapport dans Google Analytics, vous devriez pouvoir consulter les catégories de temps correspondantes, Cliquez sur l'une de ces options pour afficher des visualisations détaillées de vos données temporelles. L'image ci-dessous illustre un exemple de temps de chargement de police utilisé sur un site Web avec Google Fonts au cours des dernières 24 heures.

Capture d&#39;écran 2016-05-10 à 19:16.07 PM.png

Félicitations ! Vous avez terminé cet atelier de programmation. Si vous souhaitez approfondir le sujet, la section suivante vous donnera quelques suggestions pour développer ce code afin d'obtenir encore plus d'informations.

Les métriques de performances abordées dans cet atelier de programmation sont essentielles pour mesurer la vitesse de chargement de votre site aux utilisateurs réels. Toutefois, elles ne sont qu'un début. Si vous souhaitez approfondir l'analyse des performances, il vous suffit de suivre davantage de métriques.

Dans cet atelier de programmation, vous avez suivi des métriques sur la disponibilité des ressources pour l'utilisateur. Si vous le souhaitez, vous pouvez encore détailler la plupart de ces aspects. Par exemple, au lieu de déterminer l'heure à laquelle le code JavaScript a fini de s'exécuter, vous pouvez mesurer le début et la fin du chargement, puis l'heure du chargement. Chacune de ces métriques peut révéler un problème que seul un seul d'entre eux ne connaît pas.

En plus d'affiner votre stratégie d'analyse des performances, vous devez adopter une approche plus globale. Quels sont les objectifs ? Qu'est-ce que le succès ?

Pour ce qui est de l'analyse, vous devez d'abord poser des questions, puis déterminer comment utiliser les données pour répondre à cette question.

Prenons la liste suivante, et la façon dont vous allez utiliser les connaissances acquises dans cet atelier de programmation pour répondre à ces questions:

  • Les valeurs des statistiques suivies diminuent-elles ou augmentent-elles au fil du temps ?
  • Comment l'utilisation de la mise en cache hors connexion via un service worker ou le stockage local affecte-t-elle les performances globales de votre site ?
  • Vos ressources se chargent-elles de manière optimale ? Autrement dit, il existe un grand écart entre le moment où la ressource est téléchargée et celui où elle est disponible ?
  • Existe-t-il des corrélations entre les performances et d'autres métriques que vous suivez (taux d'inscription, temps passé sur le site, achats, etc.) ?

Enfin, si vous souhaitez en savoir plus sur les performances Web ou Google Analytics, voici quelques ressources utiles pour vous lancer: