Start · Sprachen · JavaScript · Referenz · VisibilityStateEntry

VisibilityStateEntry

Schnittstelle

Ein Performance-Eintrag, der festhält, wann eine Seite in den Zustand <code>visible</code> oder <code>hidden</code> gewechselt ist.

seit JavaScript Experimentell: Chrome/Edge 115+, nicht in Firefox Kategorie: webapi

Signatur

interface VisibilityStateEntry extends PerformanceEntry

Beschreibung

VisibilityStateEntry ist ein Eintrag der Performance-Zeitleiste mit dem entryType "visibility-state". Der Browser legt einen solchen Eintrag bei jedem Wechsel des Sichtbarkeitszustands eines Dokuments an, zum Beispiel wenn der Tab gewechselt, das Fenster minimiert oder die Seite im Hintergrund geladen wird. Außerdem gibt es einen ersten Eintrag bei startTime 0, der den Anfangszustand festhält.

Die wichtigsten Eigenschaften sind name (der neue Zustand, also "visible" oder "hidden") und startTime (der Zeitpunkt des Wechsels als DOMHighResTimeStamp relativ zu performance.timeOrigin). duration ist immer 0, weil der Wechsel als einzelner Zeitpunkt erfasst wird.

Nützlich ist das Interface vor allem für Real User Monitoring (RUM): Metriken wie LCP oder FCP sind verfälscht, wenn die Seite beim Laden im Hintergrund war. Mit VisibilityStateEntry lässt sich im Nachhinein prüfen, ob und wann die Seite versteckt war. Man muss dafür nicht selbst früh einen visibilitychange-Listener registrieren.

Ausgelesen werden die Einträge mit einem PerformanceObserver (Typ "visibility-state", am besten mit buffered: true) oder mit performance.getEntriesByType("visibility-state"). Einen eigenen Konstruktor gibt es nicht, die Einträge erzeugt ausschließlich der Browser.

Parameter

Name Typ Default Beschreibung
$name Pflicht string Eigenschaft (schreibgeschützt): der neue Sichtbarkeitszustand, "visible" oder "hidden".
$entryType Pflicht string "visibility-state" Eigenschaft (schreibgeschützt): immer "visibility-state".
$startTime Pflicht DOMHighResTimeStamp Eigenschaft (schreibgeschützt): Zeitpunkt des Zustandswechsels in Millisekunden seit performance.timeOrigin. Der Anfangszustand hat 0.
$duration Pflicht number 0 Eigenschaft (schreibgeschützt): immer 0.
$toJSON() function Geerbte Methode: gibt eine JSON-Darstellung des Eintrags zurück, praktisch zum Versenden an einen Analytics-Endpunkt.

Rückgabewert

Typ
VisibilityStateEntry
Beschreibung
Die Einträge liefern PerformanceObserver-Callbacks oder performance.getEntriesByType("visibility-state"). Es gibt keinen öffentlichen Konstruktor.

Beispiele

Sichtbarkeitswechsel mit PerformanceObserver beobachten

if (PerformanceObserver.supportedEntryTypes?.includes('visibility-state')) {
  const observer = new PerformanceObserver((list) => {
    for (const entry of list.getEntries()) {
      console.log(`${entry.name} ab ${entry.startTime.toFixed(0)} ms`);
    }
  });
  // buffered: true liefert auch die Einträge, die vor der Registrierung entstanden sind
  observer.observe({ type: 'visibility-state', buffered: true });
} else {
  console.log('visibility-state wird nicht unterstützt');
}
visible ab 0 ms hidden ab 5321 ms visible ab 9870 ms

Prüfen, ob die Seite vor dem LCP versteckt war

const wasHiddenBefore = (timestamp) =>
  performance
    .getEntriesByType('visibility-state')
    .some((e) => e.name === 'hidden' && e.startTime < timestamp);

new PerformanceObserver((list) => {
  const entries = list.getEntries();
  const lcp = entries[entries.length - 1];
  if (wasHiddenBefore(lcp.startTime)) {
    console.log('LCP verworfen: Seite war zwischendurch im Hintergrund');
  } else {
    console.log('LCP:', Math.round(lcp.startTime), 'ms');
  }
}).observe({ type: 'largest-contentful-paint', buffered: true });
LCP: 1240 ms

Gesamte Sichtbarkeitsdauer berechnen und senden

const visibleTime = () => {
  const entries = performance.getEntriesByType('visibility-state');
  let total = 0;
  let visibleSince = null;
  for (const e of entries) {
    if (e.name === 'visible' && visibleSince === null) visibleSince = e.startTime;
    if (e.name === 'hidden' && visibleSince !== null) {
      total += e.startTime - visibleSince;
      visibleSince = null;
    }
  }
  if (visibleSince !== null) total += performance.now() - visibleSince;
  return Math.round(total);
};

document.addEventListener('visibilitychange', () => {
  if (document.visibilityState === 'hidden') {
    navigator.sendBeacon('/analytics', JSON.stringify({ visibleMs: visibleTime() }));
  }
});

// Wichtig · Fallstricke

Experimentell: Derzeit unterstützen nur Chromium-Browser das Interface (Chrome und Edge ab 115). Firefox und Safari unterstützen es nicht. Prüfen Sie die Unterstützung deshalb immer vorher mit PerformanceObserver.supportedEntryTypes.includes('visibility-state'). Als Rückfallebene können Sie document.visibilityState und das Ereignis visibilitychange verwenden.

  • Ohne buffered: true fehlen dem Observer alle Einträge, die vor seiner Registrierung entstanden sind, einschließlich des Anfangszustands bei startTime 0.
  • duration ist immer 0. Wie lange ein Zustand gedauert hat, müssen Sie selbst aus der Differenz aufeinanderfolgender startTime-Werte berechnen.
  • Wenn die Seite aus dem Back/Forward-Cache (bfcache) wiederhergestellt wird, beginnt keine neue Zeitleiste. Für solche Fälle sollten Sie zusätzlich auf pageshow mit event.persisted achten.
  • Der Zustand "prerender" aus der Page Visibility API erscheint hier nicht als Eintrag.