Z tego modułu dowiesz się, jak za pomocą Google Analytics oraz User Timings API mierzyć rzeczywistą szybkość działania swojej witryny lub aplikacji i optymalizować ją pod kątem wygody użytkowników.
Narzędzia takie jak WebPagetest.org świetnie nadają się do optymalizacji skuteczności, ale prawdziwy test skuteczności witryn zawsze przedstawia rzeczywiste dane od użytkowników.
Jeśli prowadzisz witrynę, prawdopodobnie używasz już Google Analytics do pomiaru ruchu, a także urządzeń i przeglądarek. Niewielki fragment kodu pozwala zróżnicować dane skuteczności.
Czego się nauczysz
- Jak dokładnie i skutecznie mierzyć dane o skuteczności za pomocą interfejsu User Timings API
- Jak wysyłać te dane do Google Analytics, aby mogły zostać uwzględnione w raportach
Czego potrzebujesz
- Przeglądarka z konsolą programisty
- Serwer WWW dla Chrome lub własny serwer WWW
- Przykładowy kod
- Edytor tekstu
- (opcjonalnie) konto Google Analytics;
Jak będziesz korzystać z tego samouczka?
Jak oceniasz tworzenie witryn lub aplikacji?
Możesz też pobrać cały przykładowy kod na komputer...
...lub skopiuj repozytorium GitHub z wiersza poleceń.
git clone https://github.com/googlecodelabs/performance-analytics.git
Przykładowy kod jest podzielony na podkatalogi odpowiadające poszczególnym numerom kroków w tym module. Dzięki temu możesz łatwo pominąć je w laboratorium lub sprawdzić, czy implementacja jest prawidłowa.
Jeśli masz dostęp do innego programu, możesz za jego pomocą sprawdzić, co dokładnie zostało zmienione.
W tym module kodu weźmiesz udział w pojedynczym pliku HTML, który wczytuje te zasoby:
- Czcionki internetowe
- Arkusze stylów
- Obrazy
- JavaScript
Będziesz pisać nowy kod, który będzie mierzyć kluczowe dane o skuteczności każdego z tych typów zasobów.
Uwagi dotyczące skuteczności zasobów
Jeśli czytasz o optymalizacji skuteczności, prawdopodobnie wiesz już, że każdy z tych typów zasobów ma swoje własne cechy i może wpływać na ogólne postrzeganie skuteczności.
Usługa porównywania cen
Na przykład arkusze stylów blokują renderowanie wszystkich elementów w DOM, co oznacza, że przeglądarka musi wysłać żądanie arkusza stylów, pobrać go i przeanalizować, zanim będzie mógł wyrenderować dowolną treść znajdującą się za nim DOM. Z tego powodu najlepiej jest umieszczać arkusze stylów w sekcji &head. Ze względu na zablokowany charakter usługi porównywania cen zalecamy też, aby umieścić kluczowy kod CSS tylko w sekcji &head, a następnie ładować niekrytyczny kod CSS później.
JavaScript
Z kolei JavaScript nie blokuje renderowania, ale blokuje analizowanie i tworzenie modelu DOM. Jest to konieczne, ponieważ JavaScript może modyfikować DOM, czyli gdy przeglądarka widzi tag <script> (oprócz skryptów asynchronicznych), musi wykonać kod, zanim przejdziesz do następnego tagu. Jeśli <script> odwołuje się do zewnętrznego pliku JavaScript, musi pobrać i wykonać kod, zanim przejdziesz dalej.
Dlatego często zalecamy wczytanie kodu JavaScript tuż przed tagiem zamykającym </body>, tak aby większość elementów DOM była dostępna tak szybko, jak to możliwe.
Czcionki internetowe
Jeśli wczytujesz czcionki internetowe, możesz też zablokować renderowanie dokumentu, dopóki czcionka nie będzie dostępna. W takim przypadku musisz wiedzieć, ile czasu zajmuje to Twoim użytkownikom. Czcionka internetowa jest szybko wczytywana, ale działa bardzo wolno w przypadku większości użytkowników witryny. Dlatego pomiar i podejmowanie decyzji dotyczących rzeczywistych danych jest takie ważne.
Obrazy
Obrazy mogą też stać się aktywne, ale często wczytują się najdłużej. Zrozumienie tego, co to znaczy, i znanie zależności między wzorcami użytkowania a czasem wczytywania strony jest niezbędne do przeprowadzenia optymalizacji.
Pierwszym krokiem w tym module kodu jest sprawdzenie wyglądu strony demonstracyjnej przed dodaniem kodu pomiaru skuteczności.
Aby wyświetlić prezentację, utwórz nowy folder i dodaj do niego plik o nazwie index.html. Następnie skopiuj poniższy kod i wklej go w pliku 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>
Następnie otwórz serwer WWW dla Chrome i uruchom serwer lokalny w nowo utworzonym katalogu. Upewnij się, że &&tt;automatycznie pokazuj indeks.html"
Teraz w przeglądarce możesz otworzyć stronę http://127.0.0.1:8887/ i wyświetlić plik demonstracyjny. Powinna wyglądać mniej więcej tak:
Po uruchomieniu strony demonstracyjnej poświęć chwilę na przyjrzenie się kodowi i zobaczenie, które typy zasobów się wczytują. W kolejnych krokach dodasz kod, który umożliwi pomiar czasu wczytywania tych zasobów i interakcję użytkownika.
Jak wspomnieliśmy wcześniej w sekcji o skuteczności zasobów, CSS blokuje renderowanie elementów DOM, a także wykonywanie skryptów występujących w ten sposób.
Właśnie utworzony przez Ciebie plik demonstracyjny zawiera ten kod CSS, który odwołuje się do Bootstrap i kilku stylów wbudowanych.
<!-- 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 blokuje zarówno renderowanie elementów DOM, jak i uruchamianie skryptów, więc możesz określić, kiedy usługa CSS zakończy blokowanie. Aby to zrobić, dodaj tag <script>
bezpośrednio po kodzie CSS, który przechowuje bieżącą godzinę.
Możesz to zrobić, tworząc zmienną i przypisując do niej element new Date()
, ale korzystając z User Timings API, można to zrobić znacznie prościej: metoda performance.mark
.
Aby oznaczyć, że usługa porównywania cen zakończyła zarówno renderowanie, jak i wykonywanie skryptu, dodaj ten wiersz kodu tuż przed zamykającym komentarzem <!-- End CSS -->
.
<script>performance.mark('css:unblock');</script>
Metoda performance.mark
tworzy sygnaturę czasową w wysokiej rozdzielczości w tym punkcie w czasie i kojarzy ją z dowolną nazwą przekazaną do metody. W tym przypadku nadano mu nazwę "css:unblock".
Metoda performance.mark
jest połączona z metodą performance.measure
, która służy do obliczania różnicy czasu między 2 znakami (oprócz oznaczeń użytych w dokumencie), a oprócz tego możesz używać znaczników, które przeglądarka automatycznie tworzy w przypadku różnych punktów w interfejsie Nawigacja Timing API).
Poniższa funkcja narzędzia mierzy i zwraca czas między dodanym znakiem a znakiem responseEnd utworzonym przez API Timing interfejsu 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;
}
Aby zacząć korzystać z tej funkcji, utwórz nowy plik o nazwie perf-analytics.js
(w tym samym katalogu co plik index.html
), a następnie skopiuj powyższy kod i wklej go w nim.
Po zdefiniowaniu tej funkcji możesz ją wywołać i przekazać w nazwie znaku &"css:unblock". Aby nie zakłócać działania innych zasobów, należy opóźnić wykonywanie tych pomiarów do czasu uruchomienia zdarzenia wczytywania okna.
Gdy napiszesz funkcję wywołującą ten kod, plik perf-analytics.js
powinien wyglądać mniej więcej tak:
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;
}
Na koniec musisz załadować skrypt perf-analytics.js
z aplikacji index.html
. Aby to zrobić, dodaj ten tag skryptu do głównego dokumentu. Dodaj go na końcu, aby nie zakłócał wczytywania innych zasobów.
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->
Gdy ukończysz ten krok, Twój kod powinien być zgodny z tym w katalogu 01-css
repozytorium kodu.
Jeśli wczytasz stronę w przeglądarce i otworzysz konsolę programisty, powinien wyświetlić się następujący wynik:
Czcionki internetowe są zwykle ładowane za pomocą zewnętrznego arkusza stylów, jak widać w początkowym pliku demonstracyjnym:
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->
To jest tag <link>
do pliku CSS, więc może Ci się wydawać, że czcionki są wczytywane i gotowe do użycia, więc wystarczy dodać znacznik w tagu <script>
bezpośrednio po <link>
, tak jak w kroku 1.
Niestety, to nie jest takie proste.
Arkusze stylów blokują wykonywanie JavaScriptu, ponieważ zawartość arkuszy stylów jest używana do stworzenia CSSOM. Ponieważ może się zdarzyć, że wczytany kod JavaScript będzie musiał uzyskać dostęp do CSSOM, wykonanie może być opóźnione, dopóki nie zostanie w pełni utworzony.
Należy jednak pamiętać, że przeglądarka może utworzyć CSSOM bez pobierania czcionki, co oznacza, że jeśli dodasz znacznik wbudowany tag skryptu do elementu DOM bezpośrednio po tagu fontanny, możliwe, że problem pojawi się przed całkowitym wczytaniem czcionki.
Zanim zdarzenia wczytywania czcionek staną się dostępne w przeglądarkach, JavaScript jest potrzebny do określenia, czy czcionka jest rzeczywiście aktywna i gotowa do użycia na stronie. Na szczęście ładowanie czcionek za pomocą JavaScriptu również prowadzi do wzrostu skuteczności, bo nie wymaga dodatkowego żądania blokowania do pliku CSS.
Większość czcionek internetowych (w tym czcionek Google, typekit i font.com) można wczytywać za pomocą skryptu webfont.js, który został opracowany wspólnie przez Google i Typekit.
Aby zaktualizować główny dokument za pomocą tagu webfont.js do ładowania czcionek (zamiast tagu <link>), zastąp sekcję czcionek kodem:
<!-- 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 -->
Pamiętaj o 2 ważnych kwestiach dotyczących tego kodu:
- Tworzy on znacznik ":active" w aktywnym odwołaniu, dzięki czemu możesz później zmierzyć czas wczytywania czcionek.
- Tag
<script>
, który wczytuje plik webfonts.js, zawiera atrybutasync
, więc nie będzie analizować ani renderować reszty dokumentu (co nie dotyczy zasady<link>
).
Powyższy kod pozwala utworzyć znak "fonts:active" pomiar tego znaku i rejestrowanie go w konsoli nie jest tak łatwy jak w przypadku znaku "css:unblock". Przyczyną jest to, że ładowanie czcionki odbywa się asynchronicznie, więc jeśli spróbujesz zmierzyć znak &"fonts:active" w module obsługi window.onload
(jak w przypadku parametru „"css:unblock"”), to czcionka może nie zostać jeszcze wczytana.
Aby rozwiązać ten problem, możesz stworzyć obietnicę rozwiązaną po wczytaniu czcionki. Poniższa funkcja robi to za Ciebie. Skopiuj go i wklej do pliku 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')
});
}
Zaktualizuj też moduł obsługi window.onload
, by wywoływał tę nową funkcję
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
};
Gdy ukończysz ten krok, Twój kod powinien być zgodny z tym w katalogu 02-fonts
repozytorium kodu.
Jeśli wczytasz stronę w przeglądarce i otworzysz konsolę programisty, powinien wyświetlić się następujący wynik:
Zorientowanie się, kiedy obraz jest widoczny, nie jest tak proste, jak mogłoby się wydawać. Jak wiesz z poprzednich etapów, synchroniczne arkusze stylów i tagi <script>
mogą blokować renderowanie, analizowanie i uruchamianie skryptów. Możesz także nie wiedzieć, że żadna z nich nie blokuje skanera wstępnego wczytywania przeglądarki.
Skaner wstępnego wczytywania to jedna z nowoczesnych przeglądarek, które poprawiają wydajność. Jest to nawet sytuacja, w której witryna zawiera dużo zasobów blokujących. Chodzi o to, że chociaż niektóre zasoby mogą blokować analizowanie lub renderowanie bądź wykonywanie skryptów, nie muszą one blokować pobierania. Przeglądarka skanuje plik HTML, zanim rozpocznie tworzenie modelu DOM, i poszukuje zasobów, które może natychmiast pobrać.
Jeśli chodzi o obrazy, oznacza to, że prawdopodobnie zostały już pobrane przed dodaniem ich do DOM. Oznacza to też, że punkt pobierania obrazu nie musi być dobrej jakości. Wskaźnik wydajności, na który należy zwrócić uwagę, to moment, w którym obraz jest widoczny dla użytkownika.
Jeśli przed dodaniem obrazu do DOM pobierany jest obraz, punkt, w którym się on pojawia, to punkt, w którym się on znajduje w DOM. Z drugiej strony, jeśli obraz nie zostanie pobrany przed dodaniem go do modelu DOM, punkt, w którym stanie się widoczny, zostanie uruchomiony przy użyciu modułu onload
.
Jeśli więc chcesz sprawdzić, czy obraz jest widoczny, musisz obsługiwać oba te przypadki.
W tym celu dodaj znaczniki w obrębie każdego modułu obsługi ładowania oraz do wbudowanego tagu <script> bezpośrednio po ostatnim obrazie w DOM. Chodzi o to, że znak, który pojawia się jako ostatni, będzie znakiem reprezentującym wszystkie obrazy.
Aby dodać znaczniki zarówno do wczytywania obrazów, jak i ich wyrenderowania, zaktualizuj kod obrazów w index.html
w następujący sposób:
<!-- 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 -->
Metoda performance.measure
dla określonego znaku zawsze używa ostatniego znaku (jeśli znajdzie wiele znaków o tej samej nazwie), można użyć w tym celu funkcji narzędzia measureDuration
w pliku perf-analytics.js
bez żadnych dodatkowych modyfikacji:
/**
* 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'));
}
Dodaj powyższą funkcję do pliku perf-analytics.js
, a następnie zaktualizuj element window.onload
, by ją wywoływać:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
};
Gdy ukończysz ten krok, Twój kod powinien być zgodny z tym w katalogu 03-images
repozytorium kodu.
Jeśli wczytasz stronę w przeglądarce i otworzysz konsolę programisty, powinien wyświetlić się następujący wynik:
Tagi <script>
bez atrybutu DOM analizują DOM, dopóki nie zostaną pobrane i wykonane, więc możesz wskazać punkt, w którym wszystkie skrypty zostały zakończone, dodając oznaczenie w tagu wbudowanego tuż po ostatniej synchronicznej ścieżce <script>
w DOM.
Pamiętaj, że w tym przypadku moduły obsługi onload
nie działają, ponieważ przeglądarka musi wykonać skrypt po jego wczytaniu, co zajmuje trochę czasu. Skrypt, który szybko się wczytuje, ale wolno wykonuje, może być tak samo zły jak skrypt wczytujący się powoli.
Aby śledzić ładowanie i wykonywanie całego kodu JavaScript w dokumencie głównym, zaktualizuj sekcję JavaScriptu w index.html
o następujący kod:
<!-- 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 -->
Spowoduje to dodanie znaku o nazwie "js:execute" zaraz po pobraniu i zakończeniu wykonywania skryptów dla wtyczek jQuery i Boststrap'.
Aby zmierzyć, ile czasu to zajmie, dodaj do perf-analytics.js
tę funkcję:
/**
* 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'));
}
A następnie wywołaj ją z modułu obsługi window.onload
:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};
Gdy ukończysz ten krok, Twój kod powinien być zgodny z tym w katalogu 04-javascript
repozytorium kodu.
Jeśli wczytasz stronę w przeglądarce i otworzysz konsolę programisty, powinien wyświetlić się następujący wynik:
Nie wszystkie przeglądarki obsługują obietnice JavaScriptu lub interfejsy API User Timing. Jeśli uruchomisz kod napisany w przeglądarce bez obsługi jednej z tych funkcji, pojawią się błędy.
Aby rozwiązać ten problem, możesz użyć funkcji wykrywania cech. Dodaj poniższy fragment kodu bezpośrednio przed sekcją czcionek. Ten wiersz kodu JavaScript wykrywa obsługę metody performance.mark
, więc musi zostać dodana do strony, zanim zostanie użyta:
<!-- Start feature detects -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End feature detects -->
Następnie w dowolnym miejscu w miejscu index.html
, gdzie wywołujesz funkcję performance.mark
, poprzedź ją prefiksem wykrywania funkcji. Oto przykład, który aktualizuje kod w bloku obrazu, ale musisz też zaktualizować pozostałe sekcje.
<!-- 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 -->
Teraz po ustawieniu zmiennej __perf
w window
możesz jej używać także w perf-analytics.js
, aby mieć pewność, że nie wywołujesz metody, która nie jest obsługiwana w bieżącej przeglądarce.
Funkcja measureDuration
musi zostać zaktualizowana, aby dodać ten warunek:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
}
}
Ponieważ nie wszystkie przeglądarki obsługują obietnice w języku JavaScript, funkcja measureWebfontPerfAndFailures
musi być też opakowana warunkowo:
function measureWebfontPerfAndFailures() {
if (window.Promise) {
// ...
}
}
Teraz powinno być możliwe uruchomienie kodu w dowolnej przeglądarce.
Gdy ukończysz ten krok, Twój kod powinien być zgodny z tym w katalogu 05-feature-detects
repozytorium kodu.
Ostatnim krokiem w tym ćwiczeniu jest zebranie danych, które są rejestrowane w konsoli, i wysłanie ich do Google Analytics. Zanim będzie można wysyłać dane do Google Analytics, musisz dodać do strony bibliotekę analytics.js i domyślny fragment kodu śledzenia.
Dodaj ten kod do tagu index.html
po głównym bloku JavaScript, ale przed wczytaniem skryptu 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 -->
Jeśli masz już wcześniej dodaną witrynę Google Analytics, oznacza to, że musisz zastąpić obiekt zastępczy „UA-XXXXX-Y"” identyfikatorem śledzenia otrzymanym podczas tworzenia nowej usługi w Google Analytics.
Fragment kodu śledzenia analytics.js ma cztery główne zadania:
- Tworzy asynchroniczny element
<script>
, który pobiera bibliotekę JavaScript analytics.js. - Inicjuje globalną funkcję
ga()
(zwaną kolejką poleceń ga()), która pozwala zaplanować uruchamianie poleceń po wczytaniu biblioteki analytics.js i przygotowaniu jej do działania. - Dodaje polecenie do kolejki poleceń
ga()
, aby utworzyć nowy obiekt skryptu śledzenia dla właściwości określonej za pomocą parametru'UA-XXXXX-Y'. - Dodaje kolejne polecenie do kolejki poleceń
ga()
, aby wysłać odsłonę do Google Analytics dla bieżącej strony.
Dane zebrane na podstawie samych odsłon są przydatne, ale nie obrazują całej historii. Aby uzyskać lepszy obraz sposobu, w jaki użytkownicy korzystają z Twojej witryny lub aplikacji, musisz wysyłać do Google Analytics dodatkowe dane o interakcjach.
Google Analytics obsługuje kilka rodzajów danych o interakcjach: odsłony stron, zdarzenia, interakcje społecznościowe, wyjątki oraz (ostatnie) między innymi czas działań użytkownika. Aby wysyłać do Google Analytics dane o czasie użytkowników, możesz użyć tego podpisu polecenia:
ga('send', 'timing', timingCategory, timingVar, timingValue);
Gdzie timingCategory
to ciąg znaków, który pozwala uporządkować działania związane z czasem w grupę logiczną, timingVar
to zmienna, którą mierzysz, a timingValue
to rzeczywisty czas trwania w milisekundach.
Aby zobaczyć, jak to działa, instrukcję console.log
w funkcji measureCssUnblockTime
można zaktualizować w ten sposób:
ga('send', 'timing', 'CSS', 'unblock', measureDuration('css:unblock'));
Powyższy kod zadziała w niektórych sytuacjach, ale musisz pamiętać o 2 ważnych kwestiach:
- Poprzedni krok spowodował uruchomienie funkcji
measureDuration
tylko wtedy, gdy przeglądarka obsługuje interfejs User Timings API, co oznacza, że niekiedy będzie zwracałundefined
. Nie ma powodu, aby wysyłać do Google Analytics niezdefiniowane dane (w niektórych przypadkach może to nawet zaburzyć raportowanie), dlatego to działanie związane z czasem powinno być wysyłane tylko wtedy, gdymeasureDuration
zwraca wartość. - Zwrócona wartość
measureDuration
toDOMHighResTimeStamp
, którego dokładność jest większa niż kilka milisekund. PonieważtimingValue
w Google Analytics musi być liczbą całkowitą, musisz zaokrąglić wartość zwracaną przezmeasureDuration
.
Aby to zrobić, zaktualizuj instrukcję zwrotną w funkcji measurementDuration, by zaokrąglić wartość zwrotną:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
return Math.round(measure.duration);
}
}
Zaktualizuj polecenia synchronizacji, tak aby uruchamiały się tylko wtedy, gdy istnieje wartość danych, których dotyczy problem. Funkcja measureCssUnblockTime
powinna być na przykład podobna do tej:
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}
Musisz dokonać podobnych aktualizacji wszystkich pozostałych funkcji pomiarowych. Gdy to zrobisz, końcowy plik perf-analytics.js powinien wyglądać tak:
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);
}
}
Ostateczny plik index.html powinien wyglądać tak:
<!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>
Jeśli załadujesz tę stronę i przyjrzysz się żądaniom w panelu sieci, zobaczysz coś takiego:
To przydatne, ale dla danych może być uciążliwe. Jeśli z jakichś powodów nie widzisz takich żądań, bardzo trudno jest wskazać, gdzie wystąpiła awaria.
Podczas programowania lokalnego lepiej jest korzystać z wersji debugowania analytics.js, która rejestruje cenne dane debugowania w konsoli, gdy jest uruchamiane każde polecenie.
Zaktualizuj adres URL analytics.js w wersji index.html
na analytics_debug.js
i otwórz konsolę przeglądarki. Zobaczysz wydrukowane instrukcje, które wyglądają tak:
Gdy już wiesz, jak wdrożyć pomiar skuteczności tej strony demonstracyjnej, możesz dodać go do swojej witryny, wysyłając rzeczywiste dane użytkowników do Google Analytics.
Raporty o danych, które zbierasz
Po kilku dniach zbieramy dane o skuteczności, więc możesz wygenerować raporty z tymi danymi, by dowiedzieć się, jak szybko witryna i jej zasoby rzeczywiście wczytują się w przypadku prawdziwych użytkowników.
Aby przejść do raportów Czas działań użytkownika w Google Analytics, kliknij u góry kartę Raportowanie i wybierz na pasku bocznym „&&t;Zachowanie >Szybkość witryny> Czas użytkownika” (lub wykonaj instrukcje, aby wyświetlić raport Czas użytkownika w Centrum pomocy).
Po załadowaniu raportu Czas działań użytkownika w Google Analytics powinny być widoczne kategorie czasu odpowiadające przesłanym przez Ciebie danym. Kliknij dowolną z nich, aby zobaczyć szczegółowe wizualizacje danych o czasie. Ten obraz przedstawia przykład czasu wczytywania czcionek w rzeczywistej witrynie korzystającej z Google Fonts w ciągu ostatnich 24 godzin.
Gratulacje! Udało Ci się ukończyć ten moduł. Jeśli chcesz dowiedzieć się więcej, w następnej sekcji znajdziesz kilka sugestii, jak wykorzystać ten kod i uzyskać jeszcze więcej informacji.
Dane o skuteczności omówione w tym module kodu mają kluczowe znaczenie dla pomiaru rzeczywistej liczby użytkowników witryny, ale to dopiero początek. Jeśli chcesz bardziej zagłębić się w statystyki skuteczności, wystarczy tylko śledzić więcej danych.
W tym module kodu monitorowałeś wskaźniki powiązane z udostępnieniem zasobów użytkownikowi. Jeśli chcesz, możesz podzielić nawet większą część tych elementów. Na przykład zamiast liczyć czas wykonania kodu JavaScript, możesz zmierzyć, kiedy rozpoczęło się jego wczytywanie, kiedy się zakończyło, kiedy zostało ono wykonane, a na koniec zostało wykonane. Każdy z tych rodzajów danych może wykryć problem, którego tylko niektóre z nich mogą nie wykazać.
Oprócz bardziej szczegółowej analizy zastanów się też nad całościową strategią analizy skuteczności. Jakie są cele? Co to jest sukces?
Gdy chodzi o jakiegoś rodzaju statystyki, użytkownik powinien zacząć od pytania, a następnie dowiedzieć się, jak używać danych, by na nie odpowiedzieć.
Przyjrzyjmy się przykładowej liście i sposobowi wykorzystania zdobytej w tym module wiedzy na potrzeby analityki, aby odpowiedzieć na te pytania:
- Czy wartości danych, które śledzisz, rosną lub maleją?
- Jak wykorzystanie pamięci podręcznej w trybie offline przez skrypt service worker lub pamięć lokalna może wpłynąć na ogólną wydajność witryny?
- Czy zasoby są prawidłowo wczytywane? Innymi słowy, czy występuje przerwa między pobraniem zasobu a dostępnością go?
- Czy jakieś wskaźniki związane ze skutecznością i innymi danymi, które śledzisz (np.współczynnik rejestracji, czas spędzony w witrynie, zakupy itp.), są powiązane?
Jeśli chcesz dowiedzieć się więcej o wydajności witryn lub Google Analytics, zapoznaj się z tymi materiałami:
- Narzędzia i informacje ułatwiające tworzenie skutecznych witryn internetowych
https://developers.google.com/speed/ - Narzędzia i interfejsy API dla programistów korzystających z platformy Google Analytics
https://developers.google.com/analytics/ - Kursy online uczące korzystania z samej usługi Google Analytics (udane przez osoby pracujące w Google Analytics).
https://analyticsacademy.withgoogle.com/