Leistungsdaten mit Informationen zur Fehlerbehebung zuordnen, um echte Nutzerprobleme in Analytics zu erkennen und zu beheben
Google stellt zwei Kategorien von Tools zur Messung und Fehlerbehebung zur Verfügung:
- Lab-Tools:Tools wie Lighthouse. Hier wird Ihre Seite in einer simulierten Umgebung geladen, die verschiedene Bedingungen imitieren kann (z. B. ein langsames Netzwerk und ein Low-End-Mobilgerät).
- Field Tools:Tools wie der Chrome User Experience Report (CrUX), der auf aggregierten, echten Nutzerdaten aus Chrome basiert. Die von Tools wie PageSpeed Insights und der Search Console gemeldeten Felddaten stammen aus CrUX-Daten.
Während Tools für die Praxis genauere Daten liefern – also Daten, die die tatsächliche Erfahrung der Nutzer widerspiegeln – sind Lab-Tools oft besser bei der Identifizierung und Behebung von Problemen.
CrUX-Daten sind repräsentativer für die tatsächliche Leistung Ihrer Seite. Es ist jedoch unwahrscheinlich, dass Sie anhand der CrUX-Daten herausfinden können, wie Sie die Leistung verbessern können.
Lighthouse hingegen erkennt Probleme und macht konkrete Verbesserungsvorschläge. Lighthouse macht jedoch nur Vorschläge für Leistungsprobleme, die beim Seitenaufbau erkannt werden. Es werden keine Probleme erkannt, die sich nur als Folge von Nutzerinteraktionen wie Scrollen oder Klicken auf Schaltflächen auf der Seite äußern.
Das wirft eine wichtige Frage auf: Wie können Sie Debug-Informationen für Core Web Vitals oder andere Leistungsmesswerte von echten Nutzern erfassen?
In diesem Beitrag wird ausführlich erläutert, mit welchen APIs Sie zusätzliche Debugging-Informationen für jeden der aktuellen Core Web Vitals-Messwerte erfassen können. Außerdem erhalten Sie Ideen, wie Sie diese Daten in Ihrem vorhandenen Analysetool erfassen können.
APIs für Attribution und Fehlerbehebung
CLS
Von allen Core Web Vitals-Messwerten ist wahrscheinlich das Erfassen von Informationen zur Fehlerbehebung im Feld CLS am wichtigsten. Der CLS-Wert wird über die gesamte Lebensdauer der Seite hinweg gemessen. Die Art und Weise, wie ein Nutzer mit der Seite interagiert, also wie weit er scrollt, was er anklickt usw., kann einen wesentlichen Einfluss darauf haben, ob Layoutverschiebungen vorhanden sind und welche Elemente verschoben werden.
Betrachten Sie den folgenden Bericht von PageSpeed Insights:
Der aus dem Lab (Lighthouse) gemeldete CLS-Wert ist im Vergleich zum CLS-Wert aus dem Feld (CrUX-Daten) sehr unterschiedlich. Dies ist sinnvoll, wenn Sie bedenken, dass die Seite möglicherweise viele interaktive Inhalte enthält, die beim Testen in Lighthouse nicht verwendet werden.
Aber selbst wenn Sie wissen, dass sich die Nutzerinteraktion auf Felddaten auswirkt, müssen Sie wissen, welche Elemente auf der Seite sich ändern, um einen Wert von 0,3 beim 75.Perzentil zu erzielen.
Mit der Schnittstelle LayoutShiftAttribution ist dies möglich.
Layout Shift-Zuordnung abrufen
Die Schnittstelle LayoutShiftAttribution wird bei jedem layout-shift
-Eintrag angezeigt, den die Layout Instability API ausgibt.
Eine ausführliche Erläuterung dieser beiden Oberflächen finden Sie unter Fehler bei Layoutverschiebungen beheben. Für diesen Beitrag sollten Sie vor allem wissen, dass Sie als Entwickler jede Layoutverschiebung auf der Seite beobachten können und welche Elemente sich dabei ändern.
Hier sehen Sie Beispielcode, in dem jeder Layout Shift sowie die verschobenen Elemente protokolliert werden:
new PerformanceObserver((list) => {
for (const {value, startTime, sources} of list.getEntries()) {
// Log the shift amount and other entry info.
console.log('Layout shift:', {value, startTime});
if (sources) {
for (const {node, curRect, prevRect} of sources) {
// Log the elements that shifted.
console.log(' Shift source:', node, {curRect, prevRect});
}
}
}
}).observe({type: 'layout-shift', buffered: true});
Es ist wahrscheinlich nicht praktikabel, für jede einzelne Layoutverschiebung Daten zu messen und an Ihr Analysetool zu senden. Durch das Überwachen aller Schichten können Sie jedoch die schlimmsten Schichten verfolgen und nur Informationen zu diesen Schichten melden.
Das Ziel besteht nicht darin, jede einzelne Layoutverschiebung zu ermitteln und zu beheben, sondern diejenigen, die die größte Anzahl von Nutzern betreffen und somit den größten Beitrag zur CLS Ihrer Seite beim 75. Perzentil leisten.
Außerdem müssen Sie nicht bei jeder Verschiebung das größte Quellelement berechnen, sondern nur dann, wenn Sie bereit sind, den CLS-Wert an Ihr Analysetool zu senden.
Der folgende Code verwendet eine Liste von layout-shift
-Einträgen, die zu CLS beigetragen haben, und gibt das größte Quellelement der größten Verschiebung zurück:
function getCLSDebugTarget(entries) {
const largestEntry = entries.reduce((a, b) => {
return a && a.value > b.value ? a : b;
});
if (largestEntry && largestEntry.sources && largestEntry.sources.length) {
const largestSource = largestEntry.sources.reduce((a, b) => {
return a.node && a.previousRect.width * a.previousRect.height >
b.previousRect.width * b.previousRect.height ? a : b;
});
if (largestSource) {
return largestSource.node;
}
}
}
Sobald Sie das größte Element identifiziert haben, das zur größten Veränderung beigetragen hat, können Sie dies an Ihr Analysetool melden.
Das Element, das für eine bestimmte Seite am stärksten zur CLS beiträgt, variiert wahrscheinlich von Nutzer zu Nutzer. Wenn Sie diese Elemente jedoch für alle Nutzer zusammenfassen, können Sie eine Liste mit sich verändernden Elementen generieren, die sich auf die meisten Nutzer auswirken.
Nachdem Sie die Ursache der Verschiebungen für diese Elemente ermittelt und behoben haben, meldet Ihr Analysecode kleinere Verschiebungen als die "schlimmsten" Verschiebungen für Ihre Seiten. Letztendlich sind alle gemeldeten Veränderungen so klein, dass Ihre Seiten den Grenzwert für „gut“ von 0,1 einhalten.
Weitere nützliche Metadaten, die zusammen mit dem größten Shift-Quellelement erfasst werden können:
- Der Zeitpunkt der größten Änderung
- Der URL-Pfad zum Zeitpunkt der größten Verschiebung (für Websites, die die URL dynamisch aktualisieren, z. B. Single-Page-Anwendungen).
LCP
Für die Fehlerbehebung von LCP vor Ort benötigen Sie hauptsächlich, welches Element das größte Element (das LCP-Kandidatenelement) für den jeweiligen Seitenaufbau war.
Es ist durchaus möglich, dass sich das LCP-Kandidatenelement von Nutzer zu Nutzer unterscheidet, sogar für dieselbe Seite. Es ist sogar durchaus üblich.
Dafür kann es verschiedene Gründe geben:
- Nutzergeräte haben unterschiedliche Bildschirmauflösungen. Das führt zu unterschiedlichen Seitenlayouts und damit auch zu unterschiedlichen Elementen im Darstellungsbereich.
- Nutzer laden nicht immer Seiten, die ganz nach oben gescrollt werden. Häufig enthalten Links Fragmentkennungen oder sogar Textfragmente. Ihre Seiten können also geladen und an jeder Scrollposition auf der Seite angezeigt werden.
- Inhalte können für den aktuellen Nutzer personalisiert sein, sodass das LCP-Kandidatenelement von Nutzer zu Nutzer stark variieren kann.
Das bedeutet, dass Sie nicht davon ausgehen können, welches Element oder welche Gruppe von Elementen das am häufigsten vorkommende LCP-Kandidatenelement für eine bestimmte Seite ist. Sie müssen es anhand des Verhaltens der realen Nutzer messen.
LCP-Kandidatenelement identifizieren
Um das LCP-Kandidatenelement in JavaScript zu ermitteln, können Sie die Largest Contentful Paint API verwenden, dieselbe API, mit der Sie den LCP-Zeitwert bestimmen.
Bei der Beobachtung von largest-contentful-paint
-Einträgen können Sie das aktuelle LCP-Kandidatenelement anhand des element
-Attributs des letzten Eintrags ermitteln:
new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP element:', lastEntry.element);
}).observe({type: 'largest-contentful-paint', buffered: true});
Sobald Sie das LCP-Kandidatenelement kennen, können Sie es zusammen mit dem Messwert an Ihr Analysetool senden. Wie bei CLS können Sie auf diese Weise ermitteln, welche Elemente zuerst optimiert werden müssen.
Neben dem LCP-Kandidatenelement kann es auch nützlich sein, die LCP-Unterzeitzeiten zu messen. So lässt sich ermitteln, welche spezifischen Optimierungsschritte für Ihre Website relevant sind.
FID
Für die Fehlerbehebung von FID vor Ort sollten Sie bedenken, dass FID nur den Verzögerungsteil der gesamten Latenz des ersten Eingabeereignisses misst. Das bedeutet, dass die Interaktionen des Nutzers nicht so wichtig sind wie das, was während der Interaktion im Hauptthread passiert ist.
Viele JavaScript-Anwendungen, die serverseitiges Rendering (SSR) unterstützen, liefern beispielsweise statischen HTML-Code, der auf dem Bildschirm gerendert werden kann, bevor er für die Nutzereingabe interaktiv wird, d. h. bevor der für die Interaktion erforderliche JavaScript-Code vollständig geladen ist.
Für diese Arten von Anwendungen kann es sehr wichtig sein zu wissen, ob die erste Eingabe vor oder nach der Hydration erfolgte. Wenn sich herausstellt, dass viele Nutzer versuchen, vor Abschluss der Hydration mit der Seite zu interagieren, solltest du deine Seiten deaktiviert oder geladen und nicht in einem interaktiven Zustand rendern.
Wenn Ihr Anwendungs-Framework den Hydrationszeitstempel anzeigt, können Sie ihn mit dem Zeitstempel des Eintrags first-input
vergleichen, um festzustellen, ob die erste Eingabe vor oder nach der Hydration erfolgte. Wenn Ihr Framework diesen Zeitstempel nicht offenlegt oder überhaupt keine Hydration verwendet, könnte ein weiteres nützliches Signal sein, ob die Eingabe vor oder nach dem Abschluss des Ladens von JavaScript erfolgt ist.
Das DOMContentLoaded
-Ereignis wird ausgelöst, nachdem der HTML-Code der Seite vollständig geladen und geparst wurde. Dazu gehört das Warten auf das Laden aller synchronen, verzögerten oder Modulskripts (einschließlich aller statisch importierten Module). Sie können also die Zeitangabe dieses Ereignisses verwenden und mit dem Zeitpunkt des FID-Werts vergleichen.
Der folgende Code beobachtet first-input
-Einträge und protokolliert, ob die erste Eingabe vor dem Ende des DOMContentLoaded
-Ereignisses erfolgte oder nicht:
new PerformanceObserver((list) => {
const fidEntry = list.getEntries()[0];
const navEntry = performance.getEntriesByType('navigation')[0];
const wasFIDBeforeDCL =
fidEntry.startTime < navEntry.domContentLoadedEventStart;
console.log('FID occurred before DOMContentLoaded:', wasFIDBeforeDCL);
}).observe({type: 'first-input', buffered: true});
FID-Zielelement und Ereignistyp identifizieren
Weitere potenziell nützliche Signale zur Fehlerbehebung sind das Element, mit dem interagiert wurde, sowie die Art der Interaktion (z. B. mousedown
, keydown
, pointerdown
). Auch wenn die Interaktion mit dem Element selbst nicht zur FID beiträgt (die FID ist nur der Verzögerungsbereich der gesamten Ereignislatenz). Es kann jedoch hilfreich sein, zu wissen, mit welchen Elementen Ihre Nutzer interagieren, um herauszufinden, wie FID am besten verbessert werden kann.
Wenn beispielsweise die überwiegende Mehrheit der ersten Interaktionen eines Nutzers mit einem bestimmten Element erfolgt, sollten Sie den JavaScript-Code, der für dieses Element erforderlich ist, im HTML-Code einfügen und den Rest per Lazy Loading laden.
Wenn Sie den Interaktionstyp und das Element abrufen möchten, die dem ersten Eingabeereignis zugeordnet sind, können Sie auf die Attribute target
und name
des first-input
-Eintrags verweisen:
new PerformanceObserver((list) => {
const fidEntry = list.getEntries()[0];
console.log('FID target element:', fidEntry.target);
console.log('FID interaction type:', fidEntry.name);
}).observe({type: 'first-input', buffered: true});
INP
INP ist FID insofern ähnlich, als die nützlichsten Informationen, die vor Ort erfasst werden sollten:
- Mit welchem Element interagiert wurde
- Warum Interaktionstyp
- Wann diese Interaktion stattgefunden hat
Wie FID ist eine Hauptursache für langsame Interaktionen ein blockierter Hauptthread, der häufig beim Laden von JavaScript auftreten kann. Wenn Sie wissen, ob die meisten langsamen Interaktionen beim Seitenaufbau auftreten, können Sie herausfinden, welche Maßnahmen zur Behebung des Problems erforderlich sind.
Anders als bei FID berücksichtigt der INP-Messwert die volle Latenz einer Interaktion, einschließlich der Zeit, die für die Ausführung von registrierten Ereignis-Listenern benötigt wird, sowie die Zeit, die für das Darstellen des nächsten Frames benötigt wird, nachdem alle Ereignis-Listener ausgeführt wurden. Daher ist es für INP noch nützlicher zu wissen, welche Zielelemente zu langsamen Interaktionen führen und welche Arten von Interaktionen das sind.
INP und FID basieren beide auf der Event Timing API. Die Art und Weise, wie diese Informationen in JavaScript ermittelt werden, ist dem vorherigen Beispiel sehr ähnlich. Mit dem folgenden Code werden das Zielelement und die Zeit (relativ zu DOMContentLoaded
) des INP-Eintrags protokolliert.
function logINPDebugInfo(inpEntry) {
console.log('INP target element:', inpEntry.target);
console.log('INP interaction type:', inpEntry.name);
const navEntry = performance.getEntriesByType('navigation')[0];
const wasINPBeforeDCL =
inpEntry.startTime < navEntry.domContentLoadedEventStart;
console.log('INP occurred before DCL:', wasINPBeforeDCL);
}
Dieser Code zeigt nicht, wie ermittelt wird, welcher event
-Eintrag der INP-Eintrag ist, da diese Logik komplexer ist. Im folgenden Abschnitt wird jedoch erläutert, wie Sie diese Informationen über die JavaScript-Bibliothek web-vitals erhalten.
Verwendung mit der JavaScript-Bibliothek „web-vitals“
Die obigen Abschnitte enthalten einige allgemeine Vorschläge und Codebeispiele zum Erfassen von Informationen zur Fehlerbehebung, die in die Daten aufgenommen werden, die Sie an Ihr Analysetool senden.
Seit Version 3 enthält die JavaScript-Bibliothek web-vitals einen Attributions-Build, der alle diese Informationen sowie einige zusätzliche Signale enthält.
Das folgende Codebeispiel zeigt, wie Sie einen zusätzlichen Ereignisparameter (oder eine zusätzliche benutzerdefinierte Dimension) festlegen können, der einen Debug-String enthält, um die Ursache von Leistungsproblemen besser zu ermitteln.
import {onCLS, onFID, onINP, onLCP} from 'web-vitals/attribution';
function sendToGoogleAnalytics({name, value, id, attribution}) {
const eventParams = {
metric_value: value,
metric_id: id,
}
switch (name) {
case 'CLS':
eventParams.debug_target = attribution.largestShiftTarget;
break;
case 'LCP':
eventParams.debug_target = attribution.element;
break;
case 'FID':
case 'INP':
eventParams.debug_target = attribution.eventTarget;
break;
}
// Assumes the global `gtag()` function exists, see:
// https://developers.google.com/analytics/devguides/collection/ga4
gtag('event', name, eventParams);
}
onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);
Dieser Code ist spezifisch für Google Analytics, im Grunde sollte sich das Konzept jedoch auch auf andere Analysetools übertragen lassen.
Dieser Code zeigt auch, wie Berichte zu einem einzelnen Debug-Signal erstellt werden. Es kann jedoch nützlich sein, wenn Sie mehrere verschiedene Signale pro Messwert erfassen und Berichte dazu erstellen können. Um beispielsweise INP-Fehler zu beheben, können Sie den Interaktionstyp, die Zeit und auch das Element erfassen, mit dem interagiert wird. Der Attributions-Build web-vitals
stellt alle diese Informationen bereit, wie im folgenden Beispiel gezeigt:
import {onCLS, onFID, onINP, onLCP} from 'web-vitals/attribution';
function sendToGoogleAnalytics({name, value, id, attribution}) {
const eventParams = {
metric_value: value,
metric_id: id,
}
switch (name) {
case 'INP':
eventParams.debug_target = attribution.eventTarget;
eventParams.debug_type = attribution.eventType;
eventParams.debug_time = attribution.eventTime;
eventParams.debug_load_state = attribution.loadState;
break;
// Additional metric logic...
}
// Assumes the global `gtag()` function exists, see:
// https://developers.google.com/analytics/devguides/collection/ga4
gtag('event', name, eventParams);
}
onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onFID(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);
Eine vollständige Liste der erkannten Signale zur Fehlerbehebung findest du in der Dokumentation zur Attribution von Web-Vitals.
Berichte erstellen und Daten visualisieren
Nachdem Sie mit dem Erfassen von Debug-Informationen zusammen mit den Messwerten begonnen haben, besteht der nächste Schritt darin, die Daten aller Nutzer zu aggregieren, um nach Mustern und Trends zu suchen.
Wie bereits erwähnt, musst du nicht unbedingt jedes einzelne Problem beheben, sondern vor allem zuerst die Probleme, die die größte Anzahl von Nutzern betreffen. Das sollten auch die Probleme sein, die die größten negativen Auswirkungen auf deine Core Web Vitals-Werte haben.
Informationen zu GA4 finden Sie im entsprechenden Artikel zur Abfrage und Visualisierung der Daten mit BigQuery.
Zusammenfassung
Wir hoffen, dass du in diesem Beitrag konkrete Möglichkeiten aufgezeigt hast, wie du die vorhandenen Performance-APIs und die web-vitals
-Bibliothek nutzen kannst, um Debug-Informationen zu erhalten, die dir bei der Leistungsdiagnose anhand echter Nutzerbesuche helfen können. Der Schwerpunkt dieses Leitfadens liegt auf den Core Web Vitals. Die Konzepte gelten aber auch für die Fehlerbehebung bei allen Leistungsmesswerten, die in JavaScript gemessen werden können.
Der Web Vitals-Bericht ist ein guter Ausgangspunkt, wenn Sie die Leistung erst zum ersten Mal analysieren und Google Analytics bereits nutzen. Es unterstützt bereits Berichte mit Informationen zur Fehlerbehebung für die Core Web Vitals-Messwerte.
Wenn Sie als Analyseanbieter Ihre Produkte verbessern und Ihren Nutzern mehr Informationen zur Fehlerbehebung bereitstellen möchten, sollten Sie einige der hier beschriebenen Techniken in Betracht ziehen. Sie sollten sich jedoch nicht nur auf die hier vorgestellten Ideen beschränken. Dieser Beitrag bezieht sich allgemein auf alle Analysetools. Einzelne Analysetools können und sollten jedoch wahrscheinlich noch mehr Debug-Informationen erfassen und melden.
Wenn Sie der Meinung sind, dass die Fehlerbehebung für diese Messwerte unzureichend ist, weil Funktionen oder Informationen in den APIs selbst fehlen, senden Sie uns Ihr Feedback an web-vitals-feedback@googlegroups.com.