Leistung vor Ort beheben

Hier erfahren Sie, wie Sie Leistungsdaten mit Informationen zur Fehlerbehebung zuordnen, um echte Nutzerprobleme mit Analysen zu erkennen und zu beheben.

Google bietet zwei Kategorien von Tools zur Messung und Fehlerbehebung:

  • Lab-Tools:Tools wie Lighthouse. Hier wird Ihre Seite in einer simulierten Umgebung geladen, die verschiedene Bedingungen nachahmen kann (z. B. ein langsames Netzwerk und ein Low-End-Mobilgerät).
  • Feldtools: Tools wie der Bericht zur Nutzererfahrung in Chrome (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.

Feldtools bieten zwar genauere Daten – also Daten, die auch die Erfahrungen echter Nutzer widerspiegeln. Mit Lab-Tools lassen sich Probleme oft besser erkennen und beheben.

Die 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 kann jedoch nur Vorschläge für Leistungsprobleme machen, die beim Laden der Seite erkannt werden. Es werden keine Probleme erkannt, die sich nur als Ergebnis von Nutzerinteraktionen wie Scrollen oder Klicken auf Schaltflächen auf der Seite ergeben.

Das wirft eine wichtige Frage auf: Wie kann ich Informationen zur Fehlerbehebung für Core Web Vitals oder andere Leistungsmesswerte von echten Nutzern erfassen?

In diesem Beitrag wird ausführlich erläutert, welche APIs Sie verwenden können, um zusätzliche Debugging-Informationen für jeden der aktuellen Core Web Vitals-Messwerte zu erfassen. Außerdem erhalten Sie Ideen, wie Sie diese Daten in Ihrem bestehenden Analysetool erfassen können.

APIs für Attribution und Fehlerbehebung

CLS

Von allen Core Web Vitals-Messwerten ist wahrscheinlich der CLS der wichtigste Faktor, der Informationen zur Fehlerbehebung im Feld erfasst. 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 durchgeführt werden und welche Elemente sich verschieben.

Sehen Sie sich den folgenden Bericht von PageSpeed Insights an:

PageSpeed Insights-Bericht mit verschiedenen CLS-Werten

Der aus dem Lab (Lighthouse) gemeldete Wert für den CLS-Wert aus dem Feld (CrUX-Daten) ist sehr unterschiedlich. Dies ist sinnvoll, wenn Sie bedenken, dass die Seite 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 dennoch wissen, welche Elemente auf der Seite sich verändern, damit beim 75.Perzentil ein Wert von 0,3 erreicht wird.

Mit der Schnittstelle LayoutShiftAttribution ist dies möglich.

Layout Shift-Zuordnung abrufen

Die Schnittstelle LayoutShiftAttribution wird für jeden layout-shift-Eintrag verfügbar gemacht, den die Layout Instability API ausgibt.

Eine ausführliche Erläuterung dieser beiden Oberflächen finden Sie unter Probleme mit Layoutverschiebungen beheben. Für diesen Beitrag müssen Sie vor allem wissen, dass Sie als Entwickler jede Layoutverschiebung auf der Seite beobachten können und welche Elemente sich verschieben.

Hier sehen Sie Beispielcode, in dem jede Layoutverschiebung 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 Layoutänderung Daten zu messen und an Ihr Analysetool zu senden. Wenn Sie jedoch alle Schichten überwachen, können Sie die schlimmsten Schichten verfolgen und nur Informationen zu diesen Schichten melden.

Das Ziel besteht nicht darin, jede einzelne Layoutverschiebung zu identifizieren und zu korrigieren, die für jeden Nutzer auftritt. Es geht vielmehr darum, die Verschiebungen zu identifizieren, die die größte Anzahl von Nutzern betreffen und somit am stärksten zur CLS Ihrer Seite beim 75. Perzentil beitragen.

Außerdem müssen Sie nicht bei jeder Verschiebung das größte Quellelement berechnen, sondern nur, 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 aus 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 meisten zur CLS beiträgt, ist wahrscheinlich von Nutzer zu Nutzer unterschiedlich. Wenn Sie diese Elemente jedoch für alle Nutzer zusammenfassen, können Sie eine Liste mit sich verändernden Elementen erstellen, die die meisten Nutzer betreffen.

Nachdem Sie die Ursache der Verschiebungen für diese Elemente ermittelt und behoben haben, werden im Analysecode kleinere Veränderungen als die „schlimmsten“ Verschiebungen für Ihre Seiten gemeldet. Schließlich sind alle gemeldeten Veränderungen so gering, dass Ihre Seiten innerhalb des Grenzwerts „Gut“ von 0,1 liegen.

Hier einige weitere Metadaten, die zusammen mit dem größten Shift-Quellelement erfasst werden können:

  • Zeitpunkt der größten Änderung
  • Der URL-Pfad zum Zeitpunkt der größten Änderung (für Websites, die die URL dynamisch aktualisieren, z. B. Single-Page-Anwendungen).

LCP

Für die LCP-Fehlerbehebung vor Ort benötigen Sie als primäre Information, welches Element das größte (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 genau dieselbe Seite. Es kommt sogar sehr häufig vor.

Dafür kann es verschiedene Gründe geben:

  • Nutzergeräte haben unterschiedliche Bildschirmauflösungen, was dazu führt, dass unterschiedliche Seitenlayouts und somit unterschiedliche Elemente im Darstellungsbereich sichtbar sind.
  • Nutzer laden nicht immer Seiten, die ganz nach oben gescrollt werden. Häufig enthalten Links Fragmentbezeichner oder sogar Textfragmente. Ihre Seiten können also geladen und an jeder Scrollposition 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 keine Annahmen darüber treffen können, welches Element oder welcher Satz von Elementen das am häufigsten verwendete LCP-Kandidatenelement für eine bestimmte Seite ist. Sie müssen sie am tatsächlichen Nutzerverhalten messen.

LCP-Kandidatenelement bestimmen

Um das LCP-Kandidatenelement in JavaScript zu ermitteln, können Sie die Largest Contentful Paint API verwenden. Das ist dieselbe API, mit der Sie den LCP-Zeitwert bestimmen.

Beim Beobachten von largest-contentful-paint-Einträgen können Sie das aktuelle LCP-Kandidatenelement anhand des Attributs element 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-Teilzeiten zu messen. Dadurch lässt sich ermitteln, welche spezifischen Optimierungsschritte für Ihre Website relevant sind.

FID

Für das Debuggen von FID im Feld ist es wichtig, dass Sie daran denken, dass FID nur den Verzögerungsanteil der gesamten Latenz des ersten Eingabeereignisses misst. Das bedeutet, dass das, mit dem der Nutzer interagiert hat, nicht so wichtig ist wie das, was sonst im Hauptthread passiert ist.

Viele JavaScript-Anwendungen, die serverseitiges Rendering (SSR) unterstützen, stellen beispielsweise statischen HTML-Code bereit, der auf dem Bildschirm gerendert werden kann, bevor er für die Nutzereingabe interaktiv wird, d. h. bevor das für die Interaktivität erforderliche JavaScript geladen wurde.

Bei dieser Art 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, sollten Sie Ihre Seiten deaktiviert oder geladen und nicht interaktiv darstellen.

Wenn Ihr Anwendungs-Framework den Hydrationszeitstempel verfügbar macht, können Sie ihn mit dem Zeitstempel des first-input-Eintrags vergleichen, um festzustellen, ob die erste Eingabe vor oder nach der Hydration erfolgt ist. Wenn Ihr Framework diesen Zeitstempel nicht offenlegt oder keine Hydration verwendet, könnte ein weiteres nützliches Signal sein, ob die Eingabe vor oder nach dem Abschluss des Ladevorgangs 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 von synchronen, zurückgestellten oder Modulskripts (einschließlich aller statisch importierten Module). Sie können also das Timing 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). Die Interaktion mit dem Element selbst hat keinen Einfluss auf FID (Denken Sie daran, dass die FID nur der Verzögerungsanteil der gesamten Ereignislatenz ist). Wenn Sie wissen, mit welchen Elementen Ihre Nutzer interagieren, lässt sich FID am besten verbessern.

Wenn beispielsweise die überwiegende Mehrheit der ersten Interaktionen eines Nutzers mit einem bestimmten Element erfolgt, sollten Sie den für dieses Element erforderlichen JavaScript-Code im HTML-Code inline einfügen und den Rest mithilfe von 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 sehr ähnlich, als die nützlichsten Informationen, die vor Ort erfasst werden müssen:

  1. Mit welchem Element interagiert wurde
  2. Warum der Interaktionstyp war
  3. Wann diese Interaktion stattgefunden hat

Wie FID ist eine Hauptursache für langsame Interaktionen ein blockierter Hauptthread, was häufig beim Laden von JavaScript auftreten kann. Wenn Sie wissen, ob die meisten langsamen Interaktionen beim Seitenaufbau auftreten, können Sie ermitteln, wie sich das Problem beheben lässt.

Im Gegensatz zu FID berücksichtigt der INP-Messwert die volle Latenz einer Interaktion, einschließlich der Zeit, die zum Ausführen von registrierten Ereignis-Listenern benötigt wird, sowie der Zeit, die für die Darstellung des nächsten Frames benötigt wird, nachdem alle Ereignis-Listener ausgeführt wurden. Für INP ist es also 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 Sie diese Informationen in JavaScript ermitteln, 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 bestimmt wird, welcher event-Eintrag der INP-Eintrag ist, da diese Logik komplexer ist. Im folgenden Abschnitt wird jedoch erläutert, wie du diese Informationen mithilfe der JavaScript-Bibliothek web-vitals abrufst.

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 und auch einige zusätzliche Signale enthält.

Das folgende Codebeispiel zeigt, wie Sie einen zusätzlichen Ereignisparameter (oder eine zusätzliche benutzerdefinierte Dimension) mit einem Debug-String festlegen können, mit dem sich die Ursache von Leistungsproblemen leichter ermitteln lässt.

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, sollte jedoch auch für andere Analysetools übertragen werden.

Dieser Code zeigt auch nur, wie Berichte zu einem einzelnen Debug-Signal erstellt werden. Es kann jedoch nützlich sein, mehrere unterschiedliche Signale pro Messwert zu erfassen und Berichte dazu zu erstellen. Für das Debuggen von INP können Sie beispielsweise 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 verfügbaren Fehlerbehebungssignale findest du in der Dokumentation zur Attribution von Web-Vitals.

Berichte erstellen und Daten visualisieren

Nachdem Sie mit dem Erfassen von Informationen zur Fehlerbehebung zusammen mit den Messwerten begonnen haben, aggregieren Sie im nächsten Schritt die Daten aller Nutzer, um nach Mustern und Trends zu suchen.

Wie bereits erwähnt, müssen Sie nicht unbedingt jedes einzelne Problem beheben, das Ihre Nutzer haben. Sie sollten – insbesondere zuerst – die Probleme angehen, die die größte Anzahl von Nutzern betreffen. Das sollten auch die Probleme sein, die die größten negativen Auswirkungen auf Ihre Core Web Vitals-Werte haben.

Für GA4 finden Sie im entsprechenden Artikel den Artikel Daten mit BigQuery abfragen und visualisieren.

Zusammenfassung

Wir hoffen, dass in diesem Beitrag konkrete Möglichkeiten aufgezeigt wurden, wie Sie die vorhandenen Performance APIs und die web-vitals-Bibliothek nutzen können, um Informationen zur Fehlerbehebung zu erhalten und die Leistung anhand echter Nutzerbesuche zu ermitteln. 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.

Wenn Sie gerade erst mit der Leistungsmessung beginnen und Google Analytics nutzen, ist das Tool „Web Vitals-Bericht“ ein guter Ausgangspunkt, da es bereits Berichte zur Fehlerbehebung für die Core Web Vitals-Messwerte unterstützt.

Wenn Sie ein Analyseanbieter sind und Ihre Produkte verbessern und Ihren Nutzern weitere Informationen zur Fehlerbehebung bereitstellen möchten, sollten Sie einige der hier beschriebenen Techniken in Betracht ziehen. Beschränken Sie sich jedoch nicht auf nur die hier vorgestellten Ideen. Dieser Beitrag bezieht sich auf alle Analysetools. Einzelne Analysetools können und sollten jedoch wahrscheinlich noch mehr Debug-Informationen erfassen und melden.

Wenn Sie der Meinung sind, dass Sie in diesen Messwerten keine Fehler beheben können, weil Funktionen oder Informationen in den APIs selbst fehlen, senden Sie Ihr Feedback an web-vitals-feedback@googlegroups.com.