Измерение критических показателей производительности с помощью Google Analytics

В этой лабораторной работе вы узнаете, как использовать Google Analytics и User Timings API для измерения реальной производительности вашего веб-сайта или приложения и оптимизации их для повышения удобства работы ваших пользователей.

Такие инструменты, как WebPagetest.org , — отличное начало для оптимизации производительности, но настоящей проверкой производительности сайта всегда будут реальные данные от реальных пользователей.

Если вы запускаете веб-сайт, есть большая вероятность, что вы уже используете Google Analytics для измерения трафика, а также таких вещей, как использование устройства и браузера. С помощью небольшого дополнительного кода вы можете добавить показатели производительности.

Что вы узнаете

  • Как точно и эффективно измерять показатели производительности с помощью User Timings API
  • Как отправить эти данные в Google Analytics, чтобы их можно было включить в ваши отчеты

Что вам понадобится

  • Браузер с консолью разработчика
  • Веб-сервер для Chrome или используйте собственный веб-сервер по выбору.
  • Пример кода
  • Текстовый редактор
  • (Необязательно) учетная запись Google Analytics

Как вы будете использовать этот учебник?

Прочитайте только это Прочтите его и выполните упражнения

Как бы вы оценили свой опыт создания веб-сайтов или приложений?

Новичок Средний Опытный

Вы можете загрузить весь пример кода на свой компьютер...

Скачать ZIP

...или клонируйте репозиторий GitHub из командной строки.

git clone https://github.com/googlecodelabs/performance-analytics.git

Образец кода разделен на подкаталоги, соответствующие каждому из пронумерованных шагов в этой лаборатории кода. Вы можете использовать это, чтобы легко пропустить лабораторию кода или убедиться, что ваша реализация верна.

Если у вас есть доступ к программе сравнения, вы можете использовать ее, чтобы увидеть, что именно изменилось от шага к шагу.

В этой лаборатории кода вы возьмете один файл HTML, который загружает следующие ресурсы:

  • Веб-шрифты
  • Таблицы стилей
  • Картинки
  • JavaScript

И вы собираетесь написать новый код, который измеряет ключевые показатели производительности для каждого из этих типов активов.

Соображения по эффективности активов

Если вы когда-либо читали что-нибудь об оптимизации производительности, вы, вероятно, уже знаете, что каждый из этих типов ресурсов имеет свои особенности и может по-разному влиять на общую воспринимаемую производительность.

CSS

Например, таблицы стилей блокируют отрисовку всех элементов в DOM, которые идут после них, что означает, что браузер должен сделать запрос на таблицу стилей, загрузить ее и проанализировать, прежде чем он сможет отобразить любой контент в DOM, который приходит. после этого. По этой причине обычно лучше размещать таблицы стилей в <head> документа. И из-за блокирующего характера CSS также часто рекомендуется размещать критические CSS только в <head> и после этого асинхронно загружать некритические CSS.

JavaScript

JavaScript, с другой стороны, не блокирует рендеринг, но блокирует синтаксический анализ и построение DOM. Это необходимо, потому что JavaScript может изменять DOM, а это означает, что каждый раз, когда браузер видит тег <script> (за исключением асинхронных скриптов), он должен выполнить код, прежде чем перейти к следующему тегу. Если тег <script> ссылается на внешний файл JavaScript, он должен загрузить и выполнить код, прежде чем двигаться дальше.

По этой причине часто рекомендуется загружать JavaScript прямо перед закрывающим тегом </body>, чтобы большая часть DOM была доступна как можно быстрее.

Веб-шрифты

Если вы загружаете веб-шрифты, вы также можете заблокировать отображение документа до тех пор, пока шрифт не будет доступен для использования. В этом случае очень важно понять, сколько времени это на самом деле занимает у ваших пользователей. Веб-шрифт может загружаться быстро для вас, но очень медленно для большинства людей, посещающих ваш сайт. Вот почему измерения и принятие решений на основе реальных данных так важны.

Картинки

Наконец, изображения действительно могут оживить сайт, но зачастую они загружаются дольше всего. Понимание того, что это на самом деле означает, и способность определять любые корреляции между шаблонами использования и временем загрузки страницы имеют решающее значение для понимания того, как оптимизировать.

Первый шаг в этой лаборатории кода — посмотреть, как выглядит демонстрационная страница, прежде чем добавлять какой-либо код измерения производительности.

Чтобы просмотреть демонстрацию, создайте новую папку и добавьте в нее файл с именем index.html. Затем скопируйте и вставьте приведенный ниже код в файл 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>

Затем откройте веб-сервер для Chrome и запустите локальный сервер в только что созданном каталоге. Убедитесь, что установлен флажок «Автоматически показывать index.html».

Снимок экрана 11 мая 2016 г., 13.03.43.png

Теперь вы сможете перейти по адресу http://127.0.0.1:8887/ в своем браузере и просмотреть демонстрационный файл. Это должно выглядеть примерно так:

Снимок экрана 11 мая 2016 г., 10.59.03.png

После запуска демо-страницы уделите время просмотру кода и просмотру всех загружаемых типов ресурсов. В следующих нескольких шагах вы добавите код для измерения того, когда эти активы загружены и могут взаимодействовать с пользователем.

Как упоминалось ранее в разделе, посвященном вопросам производительности ресурсов, CSS блокирует отрисовку элементов DOM, а также выполнение скриптов, следующих за ним в DOM.

Демонстрационный файл, который вы только что создали, содержит следующий CSS, который ссылается на Bootstrap и несколько встроенных стилей.

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

Поскольку CSS блокирует как отрисовку элементов DOM, так и выполнение скриптов, можно определить, когда CSS завершает блокировку, добавив <script> сразу после CSS, в котором хранится текущее время.

Вы можете сделать это, создав переменную и присвоив ей new Date() , но благодаря User Timings API есть гораздо более простой способ: метод performance.mark .

Чтобы пометить, когда CSS заблокирует и рендеринг, и выполнение скрипта, добавьте следующую строку кода непосредственно перед закрывающим комментарием <!-- End CSS --> .

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

Метод performance.mark создает отметку времени с высоким разрешением в этот точный момент времени и связывает ее с любым именем, которое было передано методу. В этом случае вы назвали метку «css: разблокировать».

Метод performance.mark идет рука об руку с методом performance.measure , который используется для расчета разницы во времени между двумя отметками (в дополнение к отметкам, которые вы делаете, вы также можете использовать отметки, которые браузер автоматически делает для различных точек). в API времени навигации ).

Следующая служебная функция измеряет и возвращает продолжительность времени между добавленной меткой и меткой responseEnd , созданной API синхронизации навигации.

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

Чтобы начать использовать эту служебную функцию, создайте новый файл с именем perf-analytics.js (в том же каталоге, что и файл index.html ), скопируйте и вставьте в него приведенный выше код.

Теперь, когда эта функция определена, вы можете вызвать ее и передать имя метки «css:unblock». Чтобы не мешать загрузке каких-либо других ресурсов, следует отложить выполнение этих измерений до тех пор, пока не сработает событие загрузки окна.

После того, как вы написали функцию для вызова этого кода, ваш файл perf-analytics.js должен выглядеть примерно так:

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

Наконец, вам нужно загрузить скрипт perf-analytics.js из index.html . Для этого добавьте следующий тег сценария в основной документ. Не забудьте добавить его последним, чтобы он не мешал загрузке других ресурсов.

<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->

После того, как вы выполните этот шаг, ваш код должен соответствовать тому, что находится в каталоге 01-css репозитория лаборатории кода.

Если вы загрузите страницу в браузере и откроете консоль разработчика, вы увидите что-то вроде следующего:

Снимок экрана 17 мая 2016 г., 13.11.02.png

Веб-шрифты обычно загружаются через внешнюю таблицу стилей, как показано в исходном демонстрационном файле:

<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->

Поскольку это <link> для файла CSS, может показаться, что определить, когда шрифты загружены и готовы к использованию, так же просто, как добавить отметку внутри <script> сразу после <link> , как в шаг 1.

К сожалению, это не так просто.

Таблицы стилей блокируют выполнение JavaScript, поскольку содержимое таблиц стилей используется для построения CSSOM , и поскольку возможно, что загружаемому JavaScript потребуется доступ к CSSOM, выполнение должно быть отложено до полного создания CSSOM.

Загвоздка в том, что браузер может создать CSSOM без фактической загрузки шрифта, а это означает, что если вы добавите метку с помощью встроенного тега скрипта в DOM сразу после тега <link> таблицы стилей шрифта, скорее всего, метка появится до того, как шрифт полностью загружен.

Пока события загрузки шрифта не станут доступны в браузерах, JavaScript необходим, чтобы определить, когда шрифт действительно активен и готов к использованию на странице. К счастью, загрузка шрифтов через JavaScript также обеспечивает выигрыш в производительности, поскольку не требует дополнительного запроса блокировки к файлу CSS.

Большинство веб-шрифтов (включая шрифты Google, typekit и font.com) можно загрузить с помощью сценария webfont.js , который был совместно разработан Google и Typekit.

Чтобы обновить основной документ для использования webfont.js для загрузки шрифтов (а не тега <link>), замените раздел шрифтов кода следующим:

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

В приведенном выше коде следует обратить внимание на две важные вещи:

  • Он создает метку «fonts:active» в обратном вызове active, поэтому позже вы можете измерить, сколько времени потребовалось для загрузки шрифтов.
  • Тег <script> , который загружает webfonts.js, содержит атрибут async , поэтому он не будет блокировать синтаксический анализ или рендеринг остальной части документа (что неверно для тегов <link> ).

Хотя приведенные выше коды действительно создают метку «fonts:active», измерить эту метку и зарегистрировать ее в консоли не так просто, как для метки «css:unblock». Причина в том, что загрузка шрифта теперь происходит асинхронно, поэтому, если вы попытаетесь измерить отметку «fonts:active» в обработчике window.onload (как вы сделали с «css:unblock»), вполне возможно, что шрифт не будет быть загружены еще.

Чтобы решить эту проблему, вы можете создать обещание, которое разрешается после загрузки шрифта. Следующая функция делает это за вас. Скопируйте и вставьте его в файл 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')
  });
}

Также обновите обработчик window.onload для вызова этой новой функции.

window.onload = function() {
  measureCssUnblockTime();
  measureWebfontPerfAndFailures();
};

После того, как вы выполните этот шаг, ваш код должен соответствовать тому, что находится в каталоге 02-fonts репозитория лаборатории кода.

Если вы загрузите страницу в браузере и откроете консоль разработчика, вы увидите что-то вроде следующего:

Скриншот 2016-05-17 в 11.13.22.png

Узнать, когда изображение видно, не так просто, как может показаться. Из предыдущих шагов вы знаете, что таблицы стилей и синхронные теги <script> могут блокировать рендеринг, синтаксический анализ и выполнение скрипта. Возможно, вы не знаете, что ни один из них не блокирует сканер предварительной загрузки браузера.

Сканер предварительной загрузки — это то, что реализовано во всех современных браузерах как одна из многих попыток повысить производительность даже на сайтах, не ориентированных на производительность, которые содержат много блокирующих ресурсов. Идея состоит в том, что хотя некоторые ресурсы могут блокировать синтаксический анализ, рендеринг или выполнение скриптов, они не должны блокировать загрузку. Таким образом, браузер сканирует HTML-файл, прежде чем он начнет создавать DOM, и ищет активы, которые он может начать загружать немедленно.

Что касается изображений, это означает, что есть неплохая вероятность того, что ваши изображения уже могут быть загружены к тому времени, когда они будут добавлены в DOM. Это также означает, что точка загрузки изображения не обязательно является хорошей метрикой производительности . Метрика производительности, о которой вы должны заботиться, — это точка, в которой изображение видно пользователю.

Когда изображение загружается до добавления в DOM, точка, в которой оно становится видимым, — это точка, в которой оно находится в DOM. С другой стороны, если изображение не загружено до добавления в DOM, точка, в которой оно становится видимым, onload при срабатывании его обработчика загрузки.

Итак, чтобы узнать, когда изображение видно, вы должны обрабатывать оба случая.

Вы можете сделать это, добавив метки в обработчик загрузки каждого изображения, а также во встроенный тег <script> сразу после последнего изображения в DOM. Идея состоит в том, что метка, которая появляется последней, будет меткой, обозначающей, когда все изображения видны.

Чтобы добавить метки как при загрузке изображений, так и при их отображении, обновите код изображений в 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 -->

Поскольку метод performance.measure для определенного имени метки всегда будет использовать последнюю метку (если он находит несколько меток с одинаковым именем), для этого можно использовать служебную функцию measureDuration в файле perf-analytics.js без каких-либо дополнительных модификаций. :

/**
 * 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'));
}

Добавьте указанную выше функцию в файл perf-analytics.js , а затем обновите обработчик window.onload , чтобы он вызывал ее:

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

После того, как вы выполните этот шаг, ваш код должен соответствовать тому, что находится в каталоге 03-images репозитория лаборатории кода.

Если вы загрузите страницу в браузере и откроете консоль разработчика, вы увидите что-то вроде следующего:

Снимок экрана 2016-05-17 в 11.13.39.png

Поскольку теги <script> без async атрибута блокируют синтаксический анализ DOM до тех пор, пока они не будут загружены и выполнены, вы можете определить точку, в которой все скрипты закончили выполнение, добавив метку во встроенный тег скрипта сразу после последнего синхронного <script> в ДОМ.

Обратите внимание, что использование onload загрузки в этом случае не сработает, так как браузер должен выполнить скрипт после его загрузки, а это требует времени. Сценарий, который быстро загружается, но медленно выполняется, может быть таким же плохим, как и медленно загружаемый сценарий.

Чтобы отслеживать, когда весь JavaScript загружается и выполняется в основном документе, обновите раздел JavaScript в index.html , добавив следующий код:

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

Это добавит отметку с именем «js:execute» сразу после того, как скрипты для плагинов jQuery и Bootstrap будут загружены и завершены.

Чтобы измерить, сколько времени это займет, добавьте в 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'));
}

А затем вызвать его из обработчика window.onload :

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

После того, как вы выполните этот шаг, ваш код должен соответствовать тому, что находится в каталоге 04-javascript репозитория лаборатории кода.

Если вы загрузите страницу в браузере и откроете консоль разработчика, вы увидите что-то вроде следующего:

Снимок экрана 17 мая 2016 г., 14.11.03.png

Не все браузеры поддерживают обещания JavaScript или API-интерфейсы User Timing, и если вы запустите код, который вы написали до сих пор, в браузере без поддержки одной из этих функций, вы получите ошибки.

Чтобы справиться с этим, вы можете использовать функцию обнаружения. Добавьте следующий фрагмент кода непосредственно перед разделом шрифтов. Эта строка кода JavaScript определяет поддержку метода performance.mark , поэтому ее необходимо добавить на страницу до того, как этот метод будет использован:

<!-- Start feature detects -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End feature detects -->

Затем в любом месте index.html , где вы вызываете performance.mark , добавьте к нему префикс обнаружения функции. Вот пример, который обновляет код в блоке изображения, но вы также должны обновить и другие разделы.

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

Теперь, когда для window установлена ​​переменная __perf , вы также можете использовать ее в perf-analytics.js , чтобы убедиться, что вы не вызываете метод, который не поддерживается в текущем браузере.

Функция measureDuration должна быть обновлена, чтобы добавить следующее условие:

function measureDuration(mark, opt_reference) {
  if (window.__perf) {
    // ...
  }
}

Наконец, поскольку не все браузеры поддерживают промисы JavaScript, функция measureWebfontPerfAndFailures также должна быть заключена в условие:

function measureWebfontPerfAndFailures() {
  if (window.Promise) {
    // ...
  }
}

Теперь вы сможете без проблем запускать свой код в любом браузере.

После того, как вы выполните этот шаг, ваш код должен соответствовать тому, что находится в каталоге 05-feature-detects репозитория лаборатории кода.

Последний шаг в этой лаборатории кода — взять данные, которые записываются в консоль, и вместо этого отправить их в Google Analytics. И прежде чем вы сможете отправлять данные в Google Analytics, вы должны добавить на свою страницу библиотеку analytics.js и фрагмент отслеживания по умолчанию .

Добавьте следующий код в index.html после основного блока JavaScript, но до загрузки скрипта 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 -->

Если вы ранее добавляли Google Analytics на веб-сайт, вы знаете, что вам нужно заменить заполнитель «UA-XXXXX-Y» идентификатором отслеживания, который вы получили при создании нового свойства в Google Analytics.

Фрагмент отслеживания analytics.js выполняет четыре основные функции:

  • Создает асинхронный элемент <script> , загружающий библиотеку JavaScript analytics.js.
  • Инициализирует глобальную функцию ga() (называемую очередью команд ga() ), которая позволяет запланировать запуск команд после загрузки и готовности к работе библиотеки analytics.js.
  • Добавляет команду в очередь команд ga() для создания нового объекта отслеживания для свойства, указанного в параметре UA-XXXXX-Y.
  • Добавляет еще одну команду в очередь команд ga() для отправки просмотра страницы в Google Analytics для текущей страницы.

Хотя данные, собранные только из просмотров страниц, полезны, они не рассказывают всей истории. Чтобы получить более полное представление о том, как пользователи взаимодействуют с вашим сайтом или приложением, вам необходимо отправить дополнительные данные о взаимодействии в Google Analytics.

Google Analytics поддерживает несколько типов данных о взаимодействии: просмотры страниц , события , социальные взаимодействия , исключения и (не в последнюю очередь) время пользователя . Чтобы отправить данные о времени пользователя в Google Analytics, вы можете использовать следующую сигнатуру команды:

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

Где timingCategory — это строка, позволяющая организовать совпадения по времени в логическую группу, timingVar — измеряемая переменная, а timingValue — фактическая продолжительность времени в миллисекундах.

Чтобы увидеть, как это работает на практике, оператор console.log в функции measureCssUnblockTime можно обновить следующим образом:

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

Хотя приведенный выше код будет работать в некоторых ситуациях, есть две важные ошибки, о которых следует знать:

  • На предыдущем шаге функция measureDuration была обновлена, чтобы она выполнялась только в том случае, если браузер поддерживает API User Timings, что означает, что иногда она будет возвращать undefined . Поскольку нет причин отправлять неопределенные данные в Google Analytics (в некоторых случаях это может даже испортить ваши отчеты), вы должны отправлять это совпадение по времени только в том случае, если measureDuration возвращает значение.
  • Когда measureDuration возвращает значение, это DOMHighResTimeStamp , точность которого превышает миллисекунды. Поскольку timingValue в Google Analytics должен быть целым числом, вы должны округлить значение, возвращаемое measureDuration .

Чтобы учесть эти ошибки, обновите оператор return в функции MeasureDuration, чтобы округлить возвращаемое значение:

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

И обновите команды синхронизации, чтобы они выполнялись только в том случае, если для рассматриваемой метрики существует значение. Например, функция measureCssUnblockTime должна быть обновлена ​​примерно так:

function measureCssUnblockTime() {
  var cssUnblockTime = measureDuration('css:unblock');
  if (cssUnblockTime) {
    ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
  }
}

Вам нужно будет сделать аналогичные обновления для всех других функций измерения. После завершения окончательный файл perf-analytics.js должен выглядеть следующим образом:

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

И окончательный файл 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 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>

Если вы загрузите эту страницу и посмотрите на запросы в сетевой панели, вы увидите что-то вроде следующего:

Снимок экрана 10 мая 2016 г., 18.57.23.png

Это полезно, но просмотр этих данных как запроса в кодировке URL может быть громоздким. И если по какой-либо причине вы не видите эти запросы, очень сложно отследить, где произошел сбой.

Лучшим подходом при локальной разработке является использование отладочной версии analytics.js , которая будет записывать полезную отладочную информацию в консоль при выполнении каждой команды analytics.js. если ты

обновите URL-адрес analytics.js в index.html на analytics_debug.js и откройте консоль браузера, вы увидите распечатанные утверждения, которые выглядят следующим образом:

Снимок экрана 10 мая 2016 г., 18:54:13.png

Теперь, когда вы понимаете, как реализовать измерение производительности для этой демонстрационной страницы, вы можете попробовать добавить ее на свой собственный сайт, отправляя реальные пользовательские данные в Google Analytics.

Отчетность по собранным вами данным

После сбора данных о производительности в течение нескольких дней вы сможете составить отчет по этим данным, чтобы получить полезную информацию о том, насколько быстро ваш сайт и его ресурсы загружаются для реальных пользователей.

Чтобы перейти к отчетам о пользовательском времени в Google Analytics, щелкните вкладку «Отчетность» вверху и выберите «Поведение > Скорость сайта > Пользовательское время» на боковой панели навигации (или следуйте инструкциям, чтобы просмотреть отчет о пользовательском времени в Справочном центре). .

Когда вы загружаете отчет User Timings в Google Analytics, вы должны видеть категории времени, соответствующие отправленным вами данным. Нажмите на любой из них, чтобы увидеть подробные визуализации ваших временных данных. На следующем изображении показан пример времени загрузки шрифта на реальном веб-сайте с использованием Google Fonts за последние 24 часа.

Снимок экрана 10 мая 2016 г., 16.16.07.png

Поздравляем! Вы успешно завершили эту лабораторную работу с кодом. Если вы хотите углубиться, в следующем разделе вы найдете несколько советов о том, как строить на основе этого кода, чтобы получить еще больше информации.

Показатели производительности, рассматриваемые в этой лаборатории кода, имеют решающее значение для измерения того, как ваш сайт загружается для реальных пользователей, но это только начало. Если вы хотите углубиться в аналитику производительности, проще всего будет просто отслеживать дополнительные показатели.

В этой лаборатории кода вы отслеживали метрики, связанные с тем, когда ресурсы были доступны пользователю. Если бы вы хотели, вы могли бы разбить большинство из них еще дальше. Например, вместо того, чтобы просто измерять, когда JavaScript закончил выполнение, вы можете измерить, когда он начал загрузку, когда он закончил загрузку, когда он начал выполняться и, наконец, когда он закончил выполнение. Каждая из этих метрик может выявить проблему, о которой может не сказать только одна из них.

В дополнение к большей детализации вам также следует более комплексно продумать свою общую стратегию аналитики производительности. Каковы цели? Что такое успех?

Когда дело доходит до любого вида аналитики, вы обычно хотите начать с какого-то вопроса, а затем выяснить, как использовать данные для ответа на этот вопрос.

Например, рассмотрите следующий список вопросов и то, как вы использовали бы знания, полученные в этой лаборатории кода, чтобы использовать аналитику для ответа на них:

  • Уменьшаются или увеличиваются значения показателей, которые вы отслеживаете, со временем?
  • Как использование автономного кэширования через сервис-воркер или локальное хранилище повлияет на общую производительность вашего сайта?
  • Ваши ресурсы загружены оптимально? Т.е. есть ли большой разрыв между моментом загрузки ресурса и моментом, когда он доступен для использования?
  • Есть ли корреляция между производительностью и другими показателями, которые вы отслеживаете (например, число регистраций, время на сайте, покупки и т. д.)?

Наконец, если вы хотите узнать больше о веб-производительности или Google Analytics, вот несколько отличных ресурсов, которые помогут вам начать работу:

  • Инструменты и информация, которые помогут вам создавать высокопроизводительные веб-сайты
    https://developers.google.com/скорость/
  • Инструменты и API для разработчиков, позволяющие использовать платформу Google Analytics.
    https://developers.google.com/analytics/
  • Онлайн-курсы, которые научат вас, как использовать сам продукт Google Analytics (преподаются людьми, которые работают с самой Google Analytics.
    https://analyticsacademy.withgoogle.com/