In diesem Codelab erfahren Sie, wie Sie mit Google Analytics und der User Timings API die Leistung Ihrer Website oder Anwendung in der Praxis messen und optimieren können, um die Nutzerfreundlichkeit zu verbessern.
Tools wie WebPagetest.org sind ein guter Ausgangspunkt für Leistungsoptimierungen. Der wahre Test der Websiteleistung sind jedoch immer echte Daten von tatsächlichen Nutzern.
Wenn Sie eine Website betreiben, verwenden Sie wahrscheinlich bereits Google Analytics, um Zugriffe sowie die Nutzung von Geräten und Browsern zu erfassen. Mit nur wenig zusätzlichem Code können Sie auch Leistungsmesswerte einbeziehen.
Lerninhalte
- Leistungsmesswerte mit der User Timings API genau und effektiv messen
- So senden Sie diese Daten an Google Analytics, damit sie in Ihre Berichte aufgenommen werden können
Voraussetzungen
- Ein Browser mit einer Entwicklerkonsole
- Web Server for Chrome oder ein anderer Webserver
- Der Beispielcode
- Ein Texteditor
- (Optional) Google Analytics-Konto
Wie werden Sie diese Anleitung verwenden?
Wie würden Sie Ihre Erfahrung beim Erstellen von Websites oder Anwendungen bewerten?
Sie können den gesamten Beispielcode auf Ihren Computer herunterladen…
… oder klonen Sie das GitHub-Repository über die Befehlszeile.
git clone https://github.com/googlecodelabs/performance-analytics.git
Der Beispielcode ist in Unterverzeichnisse unterteilt, die den einzelnen nummerierten Schritten in diesem Codelab entsprechen. So können Sie im Codelab ganz einfach vor- und zurückspringen oder überprüfen, ob Ihre Implementierung korrekt ist.
Wenn Sie Zugriff auf ein Diff-Programm haben, können Sie damit genau sehen, was sich von Schritt zu Schritt geändert hat.
In diesem Codelab verwenden Sie eine einzelne HTML-Datei, in der die folgenden Assets geladen werden:
- Web fonts
- Stylesheets
- Bilder
- JavaScript
Sie schreiben neuen Code, mit dem die wichtigsten Leistungsmesswerte für die einzelnen Asset-Typen erfasst werden.
Hinweise zur Asset-Leistung
Wenn Sie schon einmal etwas über die Leistungsoptimierung gelesen haben, wissen Sie wahrscheinlich, dass jeder dieser Asset-Typen seine eigenen Besonderheiten hat und die wahrgenommene Gesamtleistung auf unterschiedliche Weise beeinflussen kann.
CSS
Stylesheets blockieren beispielsweise das Rendern aller Elemente im DOM, die nach ihnen kommen. Das bedeutet, dass der Browser eine Anfrage für das Stylesheet stellen, es herunterladen und parsen muss, bevor er Inhalte im DOM rendern kann, die nach dem Stylesheet kommen. Aus diesem Grund ist es in der Regel am besten, Stylesheets im <head> des Dokuments zu platzieren. Da CSS blockiert, wird häufig empfohlen, nur das wichtige CSS im <head> zu platzieren und das nicht wichtige CSS danach asynchron zu laden.
JavaScript
JavaScript blockiert das Rendern nicht, aber das Parsen und Erstellen des DOM. Das ist erforderlich, weil JavaScript das DOM ändern kann. Das bedeutet, dass der Browser jedes Mal, wenn er ein <script>-Tag sieht (mit Ausnahme von asynchronen Scripts), den Code ausführen muss, bevor er zum nächsten Tag übergeht. Wenn das <script>-Tag auf eine externe JavaScript-Datei verweist, muss der Code heruntergeladen und ausgeführt werden, bevor es weitergeht.
Aus diesem Grund wird oft empfohlen, JavaScript direkt vor dem schließenden </body>-Tag zu laden, damit der Großteil des DOM so schnell wie möglich verfügbar ist.
Web fonts
Wenn Sie Webschriftarten laden, können Sie das Rendern des Dokuments blockieren, bis die Schriftart verfügbar ist. In diesem Fall ist es wichtig zu wissen, wie lange das für Ihre Nutzer tatsächlich dauert. Eine Webfont wird bei Ihnen vielleicht schnell geladen, bei den meisten Besuchern Ihrer Website aber sehr langsam. Deshalb sind Analysen und Entscheidungen auf Grundlage echter Daten so wichtig.
Bilder
Bilder können eine Website zum Leben erwecken, aber sie brauchen oft am längsten, um geladen zu werden. Es ist wichtig, zu verstehen, was das genau bedeutet, und Korrelationen zwischen Nutzungsmustern und Seitenladezeiten zu erkennen, um zu wissen, wie Sie die Leistung optimieren können.
Im ersten Schritt dieses Codelabs sehen Sie sich die Demoseite an, bevor Sie Code zur Leistungsmessung hinzufügen.
Wenn Sie die Demo ansehen möchten, erstellen Sie einen neuen Ordner und fügen Sie darin eine Datei mit dem Namen „index.html“ hinzu. Kopieren Sie dann den folgenden Code und fügen Sie ihn in die Datei „index.html“ ein.
<!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>Öffnen Sie als Nächstes Web Server for Chrome und starten Sie einen lokalen Server in dem Verzeichnis, das Sie gerade erstellt haben. Achten Sie darauf, dass die Option „index.html automatisch anzeigen“ aktiviert ist.

Sie sollten jetzt in Ihrem Browser zu http://127.0.0.1:8887/ navigieren und die Demodatei sehen können. Die Ausgabe sollte ungefähr so aussehen:

Sehen Sie sich nach dem Start der Demoseite den Code an und sehen Sie, welche verschiedenen Asset-Typen geladen werden. In den nächsten Schritten fügen Sie Code hinzu, um zu erfassen, wann diese Assets geladen werden und der Nutzer mit ihnen interagieren kann.
Wie bereits im Abschnitt zu Überlegungen zur Asset-Leistung erwähnt, blockiert CSS das Rendern von DOM-Elementen sowie die Ausführung von Skripten, die danach im DOM stehen.
Die gerade erstellte Demodatei enthält das folgende CSS, das auf Bootstrap und einige Inline-Stile verweist.
<!-- 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 -->Da CSS sowohl das Rendern von DOM-Elementen als auch die Ausführung von Skripten blockiert, lässt sich ermitteln, wann die Blockierung durch CSS beendet ist. Dazu fügen Sie unmittelbar nach dem CSS ein <script>-Tag ein, in dem die aktuelle Zeit gespeichert wird.
Sie könnten dazu eine Variable erstellen und ihr new Date() zuweisen. Dank der User Timings API gibt es jedoch eine viel einfachere Methode: performance.mark.
Fügen Sie die folgende Codezeile unmittelbar vor dem schließenden <!-- End CSS -->-Kommentar ein, um zu kennzeichnen, wann das CSS sowohl das Rendern als auch die Skriptausführung blockiert.
<script>performance.mark('css:unblock');</script>Mit der Methode performance.mark wird an diesem genauen Zeitpunkt ein Zeitstempel mit hoher Auflösung erstellt und dem Namen zugeordnet, der an die Methode übergeben wurde. In diesem Fall haben Sie die Markierung „css:unblock“ genannt.
Die performance.mark-Methode geht Hand in Hand mit der performance.measure-Methode, mit der die Zeitdifferenz zwischen zwei Markierungen berechnet wird. Neben den von Ihnen erstellten Markierungen können Sie auch die Markierungen verwenden, die der Browser automatisch für die verschiedenen Punkte in der Navigation Timing API erstellt.
Die folgende Hilfsfunktion misst und gibt die Zeitdauer zwischen einer von Ihnen hinzugefügten Markierung und der Markierung responseEnd zurück, die von der Navigation Timing API erstellt wurde.
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;
}Erstellen Sie zum Verwenden dieser Hilfsfunktion eine neue Datei mit dem Namen perf-analytics.js (im selben Verzeichnis wie die Datei index.html) und kopieren Sie den oben stehenden Code hinein.
Nachdem Sie die Funktion definiert haben, können Sie sie aufrufen und den Markennamen „css:unblock“ übergeben. Damit das Laden anderer Ressourcen nicht beeinträchtigt wird, sollten Sie diese Messungen erst nach dem Auslösen des Ladeereignisses des Fensters ausführen.
Nachdem Sie eine Funktion zum Aufrufen dieses Codes geschrieben haben, sollte Ihre perf-analytics.js-Datei in etwa so aussehen:
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;
}Schließlich müssen Sie das perf-analytics.js-Skript aus index.html laden. Fügen Sie dazu Ihrem Hauptdokument das folgende Script-Tag hinzu. Fügen Sie es zuletzt hinzu, damit das Laden anderer Ressourcen nicht beeinträchtigt wird.
<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->Wenn Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem Code im Verzeichnis 01-css des Code-Lab-Repositorys übereinstimmen.
Wenn Sie die Seite in einem Browser laden und die Entwicklerkonsole öffnen, sollte die Ausgabe etwa so aussehen:

Webschriftarten werden in der Regel über ein externes Stylesheet geladen, wie in der ursprünglichen Demodatei zu sehen ist:
<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->Da es sich um ein <link>-Tag für eine CSS-Datei handelt, könnte es so aussehen, als ob Sie einfach eine Markierung in einem <script>-Tag direkt nach dem <link>-Tag hinzufügen müssten, um festzustellen, wann die Schriftarten geladen und einsatzbereit sind.
Leider ist es nicht so einfach.
Stylesheets blockieren die Ausführung von JavaScript, da der Inhalt von Stylesheets zum Erstellen des CSSOM verwendet wird. Da das geladene JavaScript möglicherweise auf das CSSOM zugreifen muss, muss die Ausführung verzögert werden, bis das CSSOM vollständig erstellt ist.
Der Haken dabei ist, dass der Browser das CSSOM erstellen kann, ohne die Schriftart tatsächlich herunterzuladen. Wenn Sie also dem DOM unmittelbar nach dem <link>-Tag des Stylesheets der Schriftart eine Markierung über ein Inline-Script-Tag hinzufügen, wird die Markierung wahrscheinlich vor dem vollständigen Laden der Schriftart gesetzt.
Bis Schriftart-Ladeereignisse in Browsern verfügbar sind, ist JavaScript erforderlich, um festzustellen, wann eine Schriftart wirklich aktiv und bereit für die Verwendung auf der Seite ist. Glücklicherweise ist das Laden von Schriftarten über JavaScript auch ein Leistungsvorteil, da keine zusätzliche blockierende Anfrage an eine CSS-Datei erforderlich ist.
Die meisten Webschriftarten (einschließlich Google Fonts, Typekit und Font.com) können über das Skript webfont.js geladen werden, das von Google und Typekit gemeinsam entwickelt wurde.
Wenn Sie das Hauptdokument so aktualisieren möchten, dass die Schriftarten mit webfont.js (und nicht mit dem <link>-Tag) geladen werden, ersetzen Sie den Schriftartabschnitt des Codes durch Folgendes:
<!-- 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 -->Im obigen Code gibt es zwei wichtige Dinge zu beachten:
- Dadurch wird im aktiven Callback eine Markierung „fonts:active“ erstellt, sodass Sie später messen können, wie lange das Laden der Schriftarten gedauert hat.
- Das
<script>-Tag, mit dem „webfonts.js“ geladen wird, enthält das Attributasync. Daher wird das Parsen oder Rendern des restlichen Dokuments nicht blockiert. Das gilt nicht für<link>-Tags.
Mit den oben genannten Codes wird zwar eine „fonts:active“-Markierung erstellt, aber das Messen und Protokollieren dieser Markierung in der Konsole ist nicht so einfach wie bei der Markierung „css:unblock“. Der Grund dafür ist, dass das Laden von Schriftarten jetzt asynchron erfolgt. Wenn Sie also versuchen, die Markierung „fonts:active“ im window.onload-Handler zu messen (wie Sie es mit „css:unblock“ getan haben), ist es sehr wahrscheinlich, dass die Schriftart noch nicht geladen wurde.
Um dieses Problem zu beheben, können Sie ein Promise erstellen, das aufgelöst wird, sobald die Schriftart geladen ist. Die folgende Funktion übernimmt diese Aufgabe für Sie. Kopieren Sie den Code und fügen Sie ihn in die Datei „perf-analytics.js“ ein:
/**
* 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')
});
}Aktualisieren Sie auch den window.onload-Handler, um diese neue Funktion aufzurufen.
window.onload = function() {
measureCssUnblockTime();
measureWebfontPerfAndFailures();
};Wenn Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem Code im Verzeichnis 02-fonts des Code-Lab-Repositorys übereinstimmen.
Wenn Sie die Seite in einem Browser laden und die Entwicklerkonsole öffnen, sollte die Ausgabe etwa so aussehen:

Wann ein Bild sichtbar ist, ist nicht so einfach zu beantworten, wie es vielleicht scheint. Aus den vorherigen Schritten wissen Sie, dass Stylesheets und synchrone <script>-Tags das Rendern, Parsen und die Skriptausführung blockieren können. Was Sie vielleicht nicht wissen: Keiner der beiden blockiert den Preload-Scanner des Browsers.
Ein Scanner zum Vorabladen ist in allen modernen Browsern implementiert, um die Leistung zu verbessern, auch auf Websites, die nicht auf Leistung ausgerichtet sind und viele blockierende Assets enthalten. Die Idee ist, dass einige Assets zwar das Parsen, Rendern oder die Ausführung von Skripts blockieren können, aber nicht den Download. Der Browser scannt also die HTML-Datei, bevor er mit dem Erstellen des DOM beginnt, und sucht nach Assets, die er sofort herunterladen kann.
Bei Bildern bedeutet das, dass sie mit hoher Wahrscheinlichkeit bereits heruntergeladen sind, wenn sie dem DOM hinzugefügt werden. Das bedeutet auch, dass der Zeitpunkt, zu dem ein Bild heruntergeladen wird, nicht unbedingt ein guter Leistungsmesswert ist. Der Leistungs-Messwert, der für Sie wichtig ist, ist der Zeitpunkt, zu dem ein Bild für den Nutzer sichtbar ist.
Wenn ein Bild heruntergeladen wird, bevor es dem DOM hinzugefügt wird, ist es erst sichtbar, wenn es sich im DOM befindet. Wenn ein Bild nicht heruntergeladen wird, bevor es dem DOM hinzugefügt wird, wird es erst sichtbar, wenn der onload-Handler ausgelöst wird.
Damit Sie wissen, wann ein Bild sichtbar ist, müssen Sie beide Fälle berücksichtigen.
Dazu können Sie Markierungen im Onload-Handler jedes Bildes sowie in einem Inline-<script>-Tag direkt nach dem letzten Bild im DOM hinzufügen. Die Idee ist, dass die letzte Markierung die Markierung ist, die angibt, wann alle Bilder sichtbar sind.
Wenn Sie Markierungen für das Laden und Rendern der Bilder hinzufügen möchten, aktualisieren Sie den Bildcode in index.html so:
<!-- 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 -->Da bei der performance.measure-Methode für einen bestimmten Markennamen immer die letzte Marke verwendet wird (wenn mehrere Marken mit demselben Namen gefunden werden), kann die Hilfsfunktion measureDuration in der Datei perf-analytics.js ohne zusätzliche Änderungen verwendet werden:
/**
* 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'));
}Fügen Sie die oben genannte Funktion in die Datei perf-analytics.js ein und aktualisieren Sie dann den window.onload-Handler, um sie aufzurufen:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
};Wenn Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem Code im Verzeichnis 03-images des Code-Lab-Repositorys übereinstimmen.
Wenn Sie die Seite in einem Browser laden und die Entwicklerkonsole öffnen, sollte die Ausgabe etwa so aussehen:

Da <script>-Tags ohne das async-Attribut das DOM-Parsing blockieren, bis sie heruntergeladen und ausgeführt wurden, können Sie den Punkt bestimmen, an dem alle Skripts ausgeführt wurden. Fügen Sie dazu eine Markierung in ein Inline-Script-Tag unmittelbar nach dem letzten synchronen <script> im DOM ein.
Die Verwendung von onload-Handlern funktioniert in diesem Fall nicht, da der Browser das Skript erst nach dem Laden ausführen muss und das dauert. Ein Skript, das schnell geladen, aber langsam ausgeführt wird, kann genauso schlecht sein wie ein Skript, das langsam geladen wird.
Wenn Sie erfassen möchten, wann das gesamte JavaScript im Hauptdokument geladen und ausgeführt wird, aktualisieren Sie den JavaScript-Abschnitt in index.html mit dem folgenden Code:
<!-- 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 -->Dadurch wird unmittelbar nach dem Herunterladen und Ausführen der Skripts für die Plugins von jQuery und Bootstrap eine Markierung mit dem Namen „js:execute“ hinzugefügt.
Fügen Sie die folgende Funktion zu perf-analytics.js hinzu, um zu messen, wie lange das dauert:
/**
* 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'));
}Rufen Sie sie dann über den window.onload-Handler auf:
window.onload = function() {
measureCssBlockTime();
measureWebfontPerfAndFailures();
measureImagesVisibleTime();
measureJavaSciptExecutionTime();
};Wenn Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem Code im Verzeichnis 04-javascript des Code-Lab-Repositorys übereinstimmen.
Wenn Sie die Seite in einem Browser laden und die Entwicklerkonsole öffnen, sollte die Ausgabe etwa so aussehen:

Nicht alle Browser unterstützen JavaScript-Promises oder die User Timing APIs. Wenn Sie den bisher geschriebenen Code in einem Browser ausführen, der eine dieser Funktionen nicht unterstützt, erhalten Sie Fehlermeldungen.
Um dieses Problem zu beheben, können Sie die Funktionserkennung verwenden. Fügen Sie den folgenden Code unmittelbar vor dem Schriftartenabschnitt ein. Diese JavaScript-Zeile erkennt die Unterstützung für die performance.mark-Methode. Sie muss also der Seite hinzugefügt werden, bevor diese Methode verwendet wird:
<!-- Start feature detects -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End feature detects -->Fügen Sie dann überall in index.html, wo Sie performance.mark aufrufen, das Feature-Erkennungspräfix voran. Hier ist ein Beispiel, in dem der Code im Bildblock aktualisiert wird. Sie müssen jedoch auch die anderen Abschnitte aktualisieren.
<!-- 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 -->Da die Variable __perf für window festgelegt ist, können Sie sie auch in perf-analytics.js verwenden, um zu verhindern, dass eine Methode aufgerufen wird, die im aktuellen Browser nicht unterstützt wird.
Die Funktion measureDuration muss aktualisiert werden, um die folgende Bedingung hinzuzufügen:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
}
}Da nicht alle Browser JavaScript-Promises unterstützen, muss die measureWebfontPerfAndFailures-Funktion in eine Bedingung eingeschlossen werden:
function measureWebfontPerfAndFailures() {
if (window.Promise) {
// ...
}
}Jetzt sollten Sie Ihren Code problemlos in jedem Browser ausführen können.
Wenn Sie diesen Schritt abgeschlossen haben, sollte Ihr Code mit dem Code im Verzeichnis 05-feature-detects des Code-Lab-Repositorys übereinstimmen.
Im letzten Schritt dieses Codelabs werden die Daten, die in der Konsole protokolliert werden, an Google Analytics gesendet. Bevor Sie Daten an Google Analytics senden können, müssen Sie die analytics.js-Bibliothek und das Standard-Tracking-Snippet auf Ihrer Seite einfügen.
Fügen Sie den folgenden Code in index.html nach dem Haupt-JavaScript-Block, aber vor dem Laden des perf-analytics.js-Scripts ein:
<!-- 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 -->Wenn Sie Google Analytics schon einmal auf einer Website eingefügt haben, wissen Sie, dass Sie den Platzhalter „UA-XXXXX-Y“ durch die Tracking-ID ersetzen müssen, die Sie beim Erstellen einer neuen Property in Google Analytics erhalten haben.
Das analytics.js-Tracking-Snippet hat vier Hauptfunktionen:
- Erstellt ein asynchrones
<script>-Element, mit dem die JavaScript-Bibliothek „analytics.js“ heruntergeladen wird. - Initialisiert eine globale
ga()-Funktion (Befehlswarteschlange ga()), mit der Sie Befehle planen können, die ausgeführt werden, sobald die analytics.js-Bibliothek geladen und einsatzbereit ist. - Fügt der Befehlswarteschlange
ga()einen Befehl hinzu, um ein neues Tracker-Objekt für die über den Parameter „UA-XXXXX-Y“ angegebene Property zu erstellen. - Fügt der Befehlswarteschlange
ga()einen weiteren Befehl hinzu, um einen Seitenaufruf für die aktuelle Seite an Google Analytics zu senden.
Die Daten, die allein durch Seitenaufrufe erfasst werden, sind zwar nützlich, aber sie vermitteln nicht das vollständige Bild. Wenn Sie besser nachvollziehen möchten, wie Nutzer Ihre Website oder App verwenden, müssen Sie zusätzliche Interaktionsdaten an Google Analytics senden.
Google Analytics unterstützt verschiedene Arten von Interaktionsdaten: Seitenaufrufe, Ereignisse, soziale Interaktionen, Ausnahmen und (last but not least) Nutzer-Timings. Wenn Sie Daten zum Nutzer-Timing an Google Analytics senden möchten, können Sie die folgende Befehlssignatur verwenden:
ga('send', 'timing', timingCategory, timingVar, timingValue);Dabei ist timingCategory ein String, mit dem Sie Timing-Treffer in logischen Gruppen organisieren können, timingVar die Variable, die Sie messen, und timingValue die tatsächliche Zeitdauer in Millisekunden.
Um zu sehen, wie das in der Praxis funktioniert, kann die console.log-Anweisung in der measureCssUnblockTime-Funktion so aktualisiert werden:
ga('send', 'timing', 'CSS', 'unblock', measureDuration('css:unblock'));Der oben genannte Code funktioniert zwar in einigen Situationen, es gibt jedoch zwei wichtige Punkte, die Sie beachten sollten:
- Im vorherigen Schritt wurde die Funktion
measureDurationso aktualisiert, dass sie nur ausgeführt wird, wenn der Browser die User Timings API unterstützt. Das bedeutet, dass sie manchmalundefinedzurückgibt. Da es keinen Grund gibt, undefinierte Daten an Google Analytics zu senden (in einigen Fällen könnten dadurch sogar Ihre Berichte beeinträchtigt werden), sollten Sie diesen Timing-Treffer nur senden, wennmeasureDurationeinen Wert zurückgibt. - Wenn
measureDurationeinen Wert zurückgibt, ist es einDOMHighResTimeStampmit einer Genauigkeit von mehr als einer Millisekunde. DatimingValuein Google Analytics eine Ganzzahl sein muss, müssen Sie den vonmeasureDurationzurückgegebenen Wert runden.
Um diese Fallstricke zu berücksichtigen, aktualisieren Sie die Return-Anweisung in der Funktion „measureDuration“, um den Rückgabewert zu runden:
function measureDuration(mark, opt_reference) {
if (window.__perf) {
// ...
return Math.round(measure.duration);
}
}Aktualisieren Sie die Timing-Befehle so, dass sie nur ausgeführt werden, wenn ein Wert für den entsprechenden Messwert vorhanden ist. Die measureCssUnblockTime-Funktion sollte beispielsweise so aktualisiert werden:
function measureCssUnblockTime() {
var cssUnblockTime = measureDuration('css:unblock');
if (cssUnblockTime) {
ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
}
}Sie müssen ähnliche Aktualisierungen für alle anderen Analysefunktionen vornehmen. Nach Abschluss der Konfiguration sollte die endgültige Datei „perf-analytics.js“ so aussehen:
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);
}
}Die endgültige Datei „index.html“ sollte so aussehen:
<!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>Wenn Sie diese Seite laden und sich die Anfragen im Netzwerkbereich ansehen, wird Folgendes angezeigt:

Das ist zwar nützlich, aber es kann mühsam sein, sich diese Daten als URL-codierte Anfrage anzusehen. Wenn Sie diese Anfragen aus irgendeinem Grund nicht sehen, ist es sehr schwierig, den Fehler zu finden.
Eine bessere Methode für die lokale Entwicklung ist die Verwendung der Debugging-Version von analytics.js. Damit werden bei der Ausführung jedes analytics.js-Befehls hilfreiche Debugging-Informationen in der Konsole protokolliert. Im Fall
Wenn Sie die analytics.js-URL in index.html in analytics_debug.js ändern und die Browserkonsole öffnen, werden Anweisungen wie die folgenden ausgegeben:

Nachdem Sie nun wissen, wie Sie die Leistungsmessung für diese Demoseite implementieren, können Sie sie auf Ihrer eigenen Website hinzufügen und echte Nutzerdaten an Google Analytics senden.
Berichte zu den erhobenen Daten erstellen
Nachdem Sie einige Tage lang Leistungsdaten erhoben haben, können Sie Berichte zu diesen Daten erstellen, um umsetzbare Informationen dazu zu erhalten, wie schnell Ihre Website und ihre Ressourcen für echte Nutzer geladen werden.
Wenn Sie in Google Analytics auf die Berichte zur Nutzerzeitmessung zugreifen möchten, klicken Sie oben auf den Tab „Berichte“ und wählen Sie in der Seitenleistennavigation „Verhalten“ > „Websitegeschwindigkeit“ > „Nutzerzeitmessungen“ aus. Alternativ können Sie auch der Anleitung in der Hilfe folgen, um den Bericht Nutzerzeitmessungen aufzurufen.
Wenn Sie den Bericht „Nutzer-Timings“ in Google Analytics aufrufen, sollten Sie die Timing-Kategorien sehen, die den von Ihnen gesendeten Daten entsprechen. Klicken Sie auf eine der Optionen, um detaillierte Visualisierungen Ihrer Zeitmessungsdaten aufzurufen. Das folgende Bild zeigt ein Beispiel für die Ladezeiten von Schriftarten auf einer echten Website, auf der Google Fonts verwendet werden, in den letzten 24 Stunden.

Glückwunsch! Sie haben dieses Codelab erfolgreich abgeschlossen. Wenn Sie noch mehr erfahren möchten, finden Sie im nächsten Abschnitt einige Vorschläge, wie Sie diesen Code erweitern können, um noch mehr Informationen zu erhalten.
Die in diesem Codelab behandelten Leistungsmesswerte sind entscheidend, um zu messen, wie Ihre Website für echte Nutzer geladen wird. Sie sind jedoch nur der Anfang. Wenn Sie die Leistungsanalyse vertiefen möchten, können Sie einfach weitere Messwerte erfassen.
In diesem Codelab haben Sie Messwerte erfasst, die sich darauf beziehen, wann Ressourcen für den Nutzer verfügbar waren. Die meisten dieser Kategorien lassen sich noch weiter unterteilen. Anstatt nur zu messen, wann die Ausführung des JavaScript abgeschlossen ist, könnten Sie beispielsweise messen, wann das Laden begonnen und abgeschlossen wurde, wann die Ausführung begonnen und abgeschlossen wurde. Jeder dieser Messwerte kann ein Problem aufdecken, das mit nur einem Messwert möglicherweise nicht erkannt wird.
Sie sollten nicht nur detailliertere Daten erfassen, sondern auch Ihre allgemeine Strategie zur Leistungsanalyse ganzheitlicher betrachten. Was sind die Ziele? Was ist Erfolg?
Bei der Analyse von Daten sollten Sie in der Regel mit einer Frage beginnen und dann herausfinden, wie Sie Daten verwenden können, um diese Frage zu beantworten.
Sehen Sie sich beispielsweise die folgende Liste mit Fragen an und überlegen Sie, wie Sie das in diesem Codelab erworbene Wissen nutzen würden, um sie mit Analysen zu beantworten:
- Nehmen die Werte der Messwerte, die Sie im Blick behalten, im Laufe der Zeit ab oder zu?
- Wie würde sich die Verwendung von Offline-Caching über Service Worker oder lokalen Speicher auf die Gesamtleistung Ihrer Website auswirken?
- Werden Ihre Ressourcen optimal geladen? Gibt es eine große Lücke zwischen dem Herunterladen der Ressource und dem Zeitpunkt, an dem sie verwendet werden kann?
- Gibt es Korrelationen zwischen der Leistung und anderen Messwerten, die Sie erfassen (z. B. Registrierungsrate, Zeit auf der Website, Käufe usw.)?
Wenn Sie mehr über Web-Leistung oder Google Analytics erfahren möchten, finden Sie hier einige nützliche Ressourcen:
- Tools und Informationen zum Erstellen leistungsstarker Websites
https://developers.google.com/speed/ - Tools und APIs für Entwickler zur Nutzung der Google Analytics-Plattform
https://developers.google.com/analytics/ - Onlinekurse, in denen Sie lernen, wie Sie das Google Analytics-Produkt verwenden (die Kurse werden von Personen gehalten, die an Google Analytics arbeiten).
https://analyticsacademy.withgoogle.com/