Debuguj wydajność w terenie

Dowiedz się, jak przypisywać dane o wydajności do informacji debugowania, aby łatwiej identyfikować i rozwiązywać problemy z użytkownikami rzeczywistymi za pomocą funkcji analitycznych

Google udostępnia 2 kategorie narzędzi do pomiaru i debugowania skuteczności:

  • Narzędzia w Laboratorium: narzędzia takie jak Lighthouse, w których strona wczytuje się w symulowanym środowisku, które może naśladować różne warunki (np. wolną sieć czy słabsze urządzenie mobilne).
  • Narzędzia terenowe: narzędzia takie jak Raport na temat użytkowania Chrome (CrUX), który opiera się na zbiorczych danych rzeczywistych użytkowników z Chrome. Pamiętaj, że dane z pomiarów zgłaszane przez narzędzia takie jak PageSpeed Insights i Search Console pochodzą z danych raportu na temat użytkowania Chrome.

Narzędzia terenowe zapewniają dokładniejsze dane, które odzwierciedlają wrażenia prawdziwych użytkowników, ale narzędzia laboratoryjne często lepiej pomagają w identyfikowaniu i rozwiązywaniu problemów.

Dane raportu na temat użytkowania Chrome są bardziej reprezentatywne dla rzeczywistej skuteczności strony, ale poznanie jego wyników raczej nie pomoże w ustaleniu, jak poprawić wydajność.

Z kolei narzędzie Lighthouse wykryje problemy i zasugeruje sposoby ich ulepszenia. ale tylko w przypadku problemów z wydajnością wykrytych podczas wczytywania strony. Nie wykrywa problemów, które występują tylko w wyniku interakcji użytkownika, takich jak przewijanie lub klikanie przycisków na stronie.

W związku z tym pojawia się ważne pytanie: jak możesz rejestrować informacje debugowania dotyczące podstawowych wskaźników internetowych lub innych danych o wydajności, które pochodzą od rzeczywistych użytkowników?

W tym poście szczegółowo omawiamy interfejsy API, za pomocą których można zbierać dodatkowe informacje debugowania dotyczące każdego z bieżących wskaźników podstawowych wskaźników internetowych, oraz podsuwamy pomysły na to, jak rejestrować te dane w dotychczasowym narzędziu analitycznym.

Interfejsy API do atrybucji i debugowania

Skumulowane przesunięcie układu (CLS)

Spośród wszystkich podstawowych wskaźników internetowych to CLS jest chyba najważniejszym elementem, w przypadku którego zbieranie w tej dziedzinie informacji o debugowaniu jest najważniejsze. CLS jest mierzony przez cały okres istnienia strony, więc sposób interakcji użytkownika ze stroną – odległość przewijania, klikanie elementów itd. – może mieć znaczny wpływ na to, czy występują przesunięcia układu, a które elementy się przenoszą.

Zobacz następujący raport z PageSpeed Insights:

Raport PageSpeed Insights z różnymi wartościami CLS
W przypadku dostępności danych terenowych i laboratoryjnych narzędzie PageSpeed Insights wyświetla oba typy danych, które mogą się różnić

Wartość CLS z modułu (Lighthouse) w porównaniu z CLS z pola (dane CrUX) znacznie się różni. Warto to rozważyć, jeśli uważasz, że strona może zawierać dużo treści interaktywnych, które nie są używane podczas testowania w Lighthouse.

Ale nawet jeśli rozumiesz, że interakcje użytkownika wpływają na dane w polach, nadal musisz wiedzieć, które elementy na stronie się zmieniają, aby uzyskać wynik 0,28 w 75 centylu. Umożliwia to interfejs LayoutShiftAttribution.

Atrybucja przesunięcia układu

Interfejs LayoutShiftAttribution jest widoczny przy każdym wpisie layout-shift wysyłanym przez interfejs Layout Instability API.

Szczegółowe omówienie obu tych interfejsów znajdziesz w artykule Debugowanie przesunięć układu. Na potrzeby tego posta przede wszystkim musisz wiedzieć, że jako programista możesz obserwować każde przesunięcie układu zachodzące na stronie oraz ustalić, które elementy się przesuwają.

Oto przykładowy kod, który rejestruje każde przesunięcie układu oraz elementy, które przesunęły się:

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

Prawdopodobnie nie jest praktyczne mierzenie i przesyłanie danych do narzędzia analitycznego w przypadku każdego wystąpienia zmiany układu. Jednak dzięki monitorowaniu wszystkich zmian możesz śledzić najgorsze zmiany i wysyłać tylko informacje o nich.

Celem nie jest identyfikowanie i naprawianie każdego przesunięcia układu, które występuje u każdego użytkownika, lecz identyfikowanie przesunięć, które wpływają na największą liczbę użytkowników i tym samym w największym stopniu wpływają na CLS strony w 75. percentylu.

Nie musisz też obliczać największego elementu źródłowego przy każdej zmianie. Jest to konieczne tylko wtedy, gdy chcesz wysłać wartość CLS do swojego narzędzia analitycznego.

Ten kod pobiera listę wpisów layout-shift, które zostały uwzględnione w CLS, i zwraca największy element źródłowy po wystąpieniu największego przesunięcia:

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

Po zidentyfikowaniu największego elementu wpływającego na największą zmianę możesz zgłosić to w narzędziu analitycznym.

Element, który ma największy wpływ na CLS w przypadku danej strony, będzie się różnić w zależności od użytkownika, ale jeśli pogrupujesz te elementy wśród wszystkich użytkowników, będziesz w stanie wygenerować listę zmieniających się elementów, które wpływają na największą liczbę użytkowników.

Gdy znajdziesz i usuniesz główną przyczynę zmian tych elementów, kod Analytics zacznie raportować mniejsze zmiany jako „największe” zmiany na stronach. Ostatecznie wszystkie zgłoszone przesunięcia będą na tyle małe, że Twoje strony będą się mieścić w dopuszczalnym progu 0,1.

Inne metadane, które przydają się do przechwytywania wraz z największym elementem źródłowym shift, to:

  • Czas największej zmiany
  • Ścieżka adresu URL w momencie największej zmiany (w przypadku witryn, które dynamicznie aktualizują adres URL, np. aplikacji na jednej stronie).

Największe wyrenderowanie treści (LCP)

Aby debugować LCP w polu, musisz znać element, który był największym elementem (elementem kandydującym do LCP) podczas wczytywania danej strony.

Pamiętaj, że jest całkiem możliwe – w rzeczywistości jest to dość powszechne – że kandydujący element LCP będzie się różnić w zależności od użytkownika, nawet w przypadku dokładnie tej samej strony.

Dzieje się tak z kilku powodów:

  • Urządzenia użytkowników mają różne rozdzielczości ekranu, co powoduje różne układy stron, a w konsekwencji różne elementy widoczne w widocznym obszarze.
  • Użytkownicy nie zawsze wczytują strony, które znajdują się na samej górze. Linki często zawierają identyfikatory fragmentów, a nawet fragmenty tekstu, co oznacza, że strony mogą się ładować i wyświetlać w dowolnym miejscu przewijania.
  • Treści mogą być spersonalizowane pod kątem bieżącego użytkownika, więc kandydujący element LCP może się znacznie różnić w zależności od użytkownika.

Oznacza to, że nie możesz zakładać, który element lub zestaw elementów będzie najczęściej wybieranym elementem kandydującym do LCP na danej stronie. Musisz je mierzyć na podstawie zachowań rzeczywistych użytkowników.

Określanie elementu kandydującego do LCP

Aby określić kandydujący element LCP w języku JavaScript, możesz użyć interfejsu Largest Contentful Paint API – tego samego interfejsu API, którego używasz do określania wartości czasu LCP.

Obserwując wpisy largest-contentful-paint, możesz określić aktualny element kandydujący do LCP, sprawdzając właściwość element ostatniego wpisu:

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

Gdy już poznasz element kandydujący do LCP, możesz go wysłać do narzędzia analitycznego wraz z wartością danych. Podobnie jak w przypadku CLS, pomoże Ci to określić, które elementy należy zoptymalizować w pierwszej kolejności.

Oprócz kandydującego elementu LCP przydaje się też pomiar podczasów podpunktów LCP, ponieważ pomaga określić, jakie konkretne kroki optymalizacji są odpowiednie w przypadku Twojej witryny.

Interakcja do kolejnego wyrenderowania (INP)

Najważniejsze informacje, które należy podać w polu dotyczącym INP:

  1. Element, z którym nastąpiła interakcja
  2. Dlaczego rodzaj interakcji
  3. Kiedy doszło do interakcji

Główną przyczyną powolnego działania interakcji jest zablokowany wątek główny, co może być częstym zjawiskiem podczas wczytywania kodu JavaScript. Wiedza o tym, czy większość wolnych interakcji występuje podczas wczytywania strony, pomaga określić, co należy zrobić, aby rozwiązać problem.

Wskaźnik INP uwzględnia pełne opóźnienie interakcji, w tym czas potrzebny na uruchomienie zarejestrowanych detektorów zdarzeń, a także czas potrzebny na wyrenderowanie następnej klatki po uruchomieniu wszystkich detektorów zdarzeń. Oznacza to, że w przypadku INP przydatne jest poznanie, które elementy docelowe powodują zwykle wolne interakcje i jakie są to interakcje.

Poniższy kod rejestruje element docelowy i czas wpisu INP.

function logINPDebugInfo(inpEntry) {
  console.log('INP target element:', inpEntry.target);
  console.log('INP interaction type:', inpEntry.name);
  console.log('INP time:', inpEntry.startTime);
}

Ten kod nie pokazuje, jak określić, który wpis event należy do wartości INP, ponieważ ta logika jest bardziej skomplikowana. Jednak w tej sekcji wyjaśniamy, jak uzyskać te informacje za pomocą biblioteki JavaScript web-vitals.

Używanie z biblioteką JavaScript web-vitals

W poprzednich sekcjach znajdziesz ogólne wskazówki i przykłady kodu, które pomogą Ci rejestrować informacje debugowania, aby uwzględniać je w danych przesyłanych do narzędzia analitycznego.

Od wersji 3 biblioteka JavaScript web-vitals zawiera kompilację atrybucji, która zawiera wszystkie te informacje, a także kilka dodatkowych sygnałów.

Poniższy przykładowy kod pokazuje, jak ustawić dodatkowy parametr zdarzenia (lub wymiar niestandardowy) zawierający ciąg debugowania, który pomaga w znalezieniu głównej przyczyny problemów z wydajnością.

import {onCLS, 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 'INP':
      eventParams.debug_target = attribution.interactionTarget;
      break;
  }

  // Assumes the global `gtag()` function exists, see:
  // https://developers.google.com/analytics/devguides/collection/ga4
  gtag('event', name, eventParams);
}

onCLS(sendToGoogleAnalytics);
onLCP(sendToGoogleAnalytics);
onINP(sendToGoogleAnalytics);

Kod ten dotyczy tylko Google Analytics, ale ogólna zasada powinna się też przełożyć na inne narzędzia analityczne.

Ten kod pokazuje też, jak tworzyć raporty na podstawie jednego sygnału debugowania, ale przydatne jest zbieranie i raportowanie wielu różnych sygnałów na podstawie jednej metryki.

Na przykład do debugowania wartości INP możesz potrzebować m.in. zbierania danych o elemencie, z którym nastąpiła interakcja, o typie interakcji, czasie, parametrze loadState, fazach interakcji i innych (takich jak dane ramki długiej animacji).

Kompilacja atrybucji web-vitals udostępnia dodatkowe informacje o atrybucji, tak jak w tym przykładzie dla INP:

import {onCLS, 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.interactionTarget;
      eventParams.debug_type = attribution.interactionType;
      eventParams.debug_time = attribution.interactionTime;
      eventParams.debug_load_state = attribution.loadState;
      eventParams.debug_interaction_delay = Math.round(attribution.inputDelay);
      eventParams.debug_processing_duration = Math.round(attribution.processingDuration);
      eventParams.debug_presentation_delay =  Math.round(attribution.presentationDelay);
      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);
onINP(sendToGoogleAnalytics);

Pełną listę ujawnionych sygnałów debugowania znajdziesz w dokumentacji atrybucji Web Vitals.

Raportowanie i wizualizacja danych

Po rozpoczęciu zbierania informacji debugowania wraz z wartościami danych następnym krokiem jest zgrupowanie danych dotyczących wszystkich użytkowników, aby można było zacząć szukać wzorców i trendów.

Jak wspomnieliśmy wcześniej, nie musisz rozwiązywać wszystkich problemów napotykanych przez użytkowników. Dotyczy to – zwłaszcza na początku – problemów, które dotykają największej liczby użytkowników, co powinno być także najbardziej negatywnym wpływem na Twoje Podstawowe wskaźniki internetowe.

W przypadku GA4 przeczytaj specjalny artykuł o tworzeniu zapytań i wizualizacji danych za pomocą BigQuery.

Podsumowanie

Mamy nadzieję, że w tym poście omówiliśmy konkretne sposoby wykorzystania obecnych interfejsów API wydajności i biblioteki web-vitals do uzyskiwania informacji na potrzeby debugowania, które pomogą diagnozować wydajność na podstawie wizyt rzeczywistych użytkowników w terenie. Chociaż ten przewodnik skupia się na podstawowych wskaźnikach internetowych, pojęcia te mają też zastosowanie do debugowania wszelkich danych dotyczących wydajności, które można zmierzyć w języku JavaScript.

Jeśli dopiero zaczynasz mierzyć skuteczność i korzystasz już z Google Analytics, dobrym punktem wyjścia może być narzędzie Raport podstawowych wskaźników internetowych, które obsługuje już raportowanie informacji debugowania dotyczących podstawowych wskaźników internetowych.

Jeśli jesteś dostawcą usług analitycznych i chcesz ulepszyć swoje usługi i zapewnić użytkownikom więcej informacji na temat debugowania, rozważ zastosowanie niektórych z opisanych tu technik, ale nie ograniczaj się tylko do przedstawionych tu pomysłów. Ten post ma zastosowanie do wszystkich narzędzi analitycznych, ale poszczególne narzędzia analityczne mogą (i powinny) rejestrować i przekazywać jeszcze więcej informacji debugujących.

Jeśli uważasz, że możesz debugować te dane z powodu braku funkcji lub informacji w samych interfejsach API, prześlij swoją opinię na adres web-vitals-feedback@googlegroups.com.