Hintergrunddaten mit der Beacon API senden

Die Seitennavigation sollte nicht von Analytics-Anfragen als Geisel genommen werden. Wenn Benutzer auf einen Link klicken oder einen Tab schließen, können traditionelle HTTP-Anfragen blockieren oder vollständig fehlschlagen, was zu unvollständigen Daten und frustrierten Benutzern führt. Die Beacon API-Lösung ändert dies, indem sie Anfragen im Hintergrund in die Warteschlange einreiht und sicherstellt, dass Ihre Daten den Server erreichen, ohne die Performance zu beeinträchtigen.
Dieser Artikel zeigt, wie Sie navigator.sendBeacon()
für zuverlässige Hintergrunddatenübertragung implementieren. Sie lernen praktische Anwendungen wie Analytics-Tracking und Fehlerberichterstattung kennen, verstehen, warum es fetch()
während Seitenübergängen übertrifft, und sehen eine vollständige Implementierung mit modernem JavaScript.
Wichtige Erkenntnisse
- Die Beacon API reiht Anfragen im Hintergrund in die Warteschlange ein, ohne die Seitennavigation zu blockieren
- Verwenden Sie
navigator.sendBeacon()
für Analytics, Fehlerberichterstattung und Benutzeraktions-Tracking - Beacons sind zuverlässiger als
fetch()
während Page-Unload-Events - Halten Sie Payloads klein und bündeln Sie mehrere Events für optimale Performance
- Implementieren Sie Fallbacks für ältere Browser, die die Beacon API nicht unterstützen
- Die API gibt einen Boolean zurück, der eine erfolgreiche Einreihung in die Warteschlange anzeigt, nicht die Zustellungsbestätigung
Was die Beacon API anders macht
Der Beacon API-Ansatz löst ein grundlegendes Problem: traditionelle HTTP-Anfragen blockieren die Seitennavigation. Wenn Sie fetch()
oder XMLHttpRequest
während Unload-Events verwenden, muss der Browser warten, bis die Anfrage abgeschlossen ist, bevor die Navigation fortgesetzt werden kann. Dies führt zu einer schlechten Benutzererfahrung und unzuverlässiger Datenübertragung.
Die Beacon API funktioniert anders. Sie reiht Anfragen asynchron in die Warteschlange ein und übernimmt die Übertragung im Hintergrund, sogar nachdem die Seite geschlossen wurde. Der Browser verwaltet den gesamten Prozess, ohne die Navigation zu blockieren oder zu erfordern, dass Ihr JavaScript aktiv bleibt.
Warum traditionelle Methoden während Seitenübergängen versagen
Betrachten Sie dieses häufige Szenario mit fetch()
:
window.addEventListener('beforeunload', () => {
// Dies kann fehlschlagen oder die Navigation blockieren
fetch('/analytics', {
method: 'POST',
body: JSON.stringify({ event: 'page_exit' })
})
})
Dieser Ansatz hat mehrere Probleme:
- Die Anfrage kann abgebrochen werden, wenn die Seite entladen wird
- Die Navigation wird blockiert, bis die Anfrage abgeschlossen ist
- Keine Garantie, dass die Daten den Server erreichen
- Schlechte Benutzererfahrung mit verzögerten Seitenübergängen
Wie navigator.sendBeacon() funktioniert
Die navigator.sendBeacon()
-Methode akzeptiert zwei Parameter: einen URL-Endpunkt und optionale Daten. Sie gibt einen Boolean zurück, der anzeigt, ob die Anfrage erfolgreich in die Warteschlange eingereiht wurde (nicht, ob sie den Server erreicht hat).
const success = navigator.sendBeacon(url, data)
Der Browser übernimmt die tatsächliche Übertragung und optimiert für Netzwerkbedingungen und Systemressourcen. Dieser Fire-and-Forget-Ansatz ist perfekt für Analytics, Logging und Diagnosedaten, bei denen Sie keine Antwort benötigen.
Praktische Implementierungsbeispiele
Grundlegendes Analytics-Tracking
Hier ist eine minimale Implementierung für das Tracking von Benutzersitzungen:
// Session-Daten tracken
const sessionData = {
userId: 'user123',
sessionDuration: Date.now() - sessionStart,
pageViews: pageViewCount,
timestamp: new Date().toISOString()
}
// Daten senden, wenn die Seite ausgeblendet wird oder der Benutzer wegnavigiert
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
const payload = JSON.stringify(sessionData)
navigator.sendBeacon('/log', payload)
}
})
window.addEventListener('beforeunload', () => {
const payload = JSON.stringify(sessionData)
navigator.sendBeacon('/log', payload)
})
Fehlerberichterstattungssystem
Die Beacon API eignet sich hervorragend zum Erfassen und Melden von JavaScript-Fehlern:
window.addEventListener('error', (event) => {
const errorData = {
message: event.message,
filename: event.filename,
line: event.lineno,
column: event.colno,
stack: event.error?.stack,
userAgent: navigator.userAgent,
timestamp: Date.now()
}
if (navigator.sendBeacon) {
navigator.sendBeacon('/log', JSON.stringify(errorData))
}
})
Benutzeraktions-Tracking
Verfolgen Sie spezifische Benutzerinteraktionen, ohne die Benutzeroberfläche zu blockieren:
function trackUserAction(action, details) {
const actionData = {
action,
details,
timestamp: Date.now(),
url: window.location.href
}
if (navigator.sendBeacon) {
navigator.sendBeacon('/log', JSON.stringify(actionData))
}
}
// Verwendungsbeispiele
document.getElementById('cta-button').addEventListener('click', () => {
trackUserAction('cta_click', { buttonId: 'cta-button' })
})
document.addEventListener('scroll', throttle(() => {
const scrollPercent = Math.round(
(window.scrollY / (document.body.scrollHeight - window.innerHeight)) * 100
)
trackUserAction('scroll', { percentage: scrollPercent })
}, 1000))
Vollständige Analytics-Implementierung
Hier ist ein umfassendes Beispiel, das mehrere Tracking-Szenarien kombiniert:
class AnalyticsTracker {
constructor(endpoint = '/log') {
this.endpoint = endpoint
this.sessionStart = Date.now()
this.events = []
this.setupEventListeners()
}
setupEventListeners() {
// Sichtbarkeitsänderungen der Seite verfolgen
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
this.sendBatch()
}
})
// Seiten-Unload verfolgen
window.addEventListener('beforeunload', () => {
this.sendBatch()
})
// Fehler verfolgen
window.addEventListener('error', (event) => {
this.trackEvent('error', {
message: event.message,
filename: event.filename,
line: event.lineno
})
})
}
trackEvent(type, data) {
this.events.push({
type,
data,
timestamp: Date.now()
})
// Batch senden, wenn wir zu viele Events haben
if (this.events.length >= 10) {
this.sendBatch()
}
}
sendBatch() {
if (this.events.length === 0) return
const payload = {
sessionId: this.generateSessionId(),
sessionDuration: Date.now() - this.sessionStart,
events: this.events,
url: window.location.href,
userAgent: navigator.userAgent
}
if (navigator.sendBeacon) {
const success = navigator.sendBeacon(
this.endpoint,
JSON.stringify(payload)
)
if (success) {
this.events = [] // Gesendete Events löschen
}
}
}
generateSessionId() {
return Math.random().toString(36).substring(2, 15)
}
}
// Tracker initialisieren
const tracker = new AnalyticsTracker('/log')
// Benutzerdefinierte Events verfolgen
tracker.trackEvent('page_view', { page: window.location.pathname })
Browser-Unterstützung und Fallbacks
Die Beacon API hat ausgezeichnete Browser-Unterstützung in modernen Browsern. Für ältere Browser implementieren Sie einen graceful Fallback:
function sendData(url, data) {
if (navigator.sendBeacon) {
return navigator.sendBeacon(url, data)
}
// Fallback für ältere Browser
try {
const xhr = new XMLHttpRequest()
xhr.open('POST', url, false) // Synchron für Unload-Events
xhr.setRequestHeader('Content-Type', 'application/json')
xhr.send(data)
return true
} catch (error) {
console.warn('Fehler beim Senden der Daten:', error)
return false
}
}
Best Practices für die Beacon-Implementierung
Payloads klein halten
Die Beacon API ist für kleine Datenpakete konzipiert. Beschränken Sie Payloads auf wesentliche Informationen:
// Gut: Fokussierte, wesentliche Daten
const essentialData = {
event: 'conversion',
value: 29.99,
timestamp: Date.now()
}
// Vermeiden: Große, unnötige Daten
const bloatedData = {
event: 'conversion',
value: 29.99,
timestamp: Date.now(),
entireDOMState: document.documentElement.outerHTML,
allCookies: document.cookie,
completeUserHistory: getUserHistory()
}
Mehrere Events bündeln
Anstatt einzelne Beacons für jedes Event zu senden, bündeln Sie sie zusammen:
const eventBatch = []
function addEvent(eventData) {
eventBatch.push(eventData)
// Batch senden, wenn er eine bestimmte Größe erreicht
if (eventBatch.length >= 5) {
sendBatch()
}
}
function sendBatch() {
if (eventBatch.length > 0) {
navigator.sendBeacon('/log', JSON.stringify(eventBatch))
eventBatch.length = 0 // Batch leeren
}
}
Netzwerkfehler graceful handhaben
Da Beacons kein Response-Feedback liefern, implementieren Sie clientseitige Validierung:
function validateAndSend(data) {
// Datenstruktur validieren
if (!data || typeof data !== 'object') {
console.warn('Ungültige Daten für Beacon')
return false
}
// Payload-Größe prüfen (Browser begrenzen typischerweise auf 64KB)
const payload = JSON.stringify(data)
if (payload.length > 65536) {
console.warn('Payload zu groß für Beacon')
return false
}
return navigator.sendBeacon('/log', payload)
}
Beacon API vs Fetch während Seitenübergängen
Der Hauptunterschied wird bei Page-Unload-Events deutlich:
// Beacon API: Nicht-blockierend, zuverlässig
window.addEventListener('beforeunload', () => {
navigator.sendBeacon('/log', JSON.stringify(data)) // ✅ Zuverlässig
})
// Fetch API: Kann blockieren oder fehlschlagen
window.addEventListener('beforeunload', () => {
fetch('/log', {
method: 'POST',
body: JSON.stringify(data),
keepalive: true // Hilft, garantiert aber keinen Erfolg
}) // ❌ Kann während der Navigation fehlschlagen
})
Das keepalive
-Flag in Fetch-Anfragen bietet ähnliche Funktionalität, aber mit weniger Zuverlässigkeit als die Beacon API, die speziell für diesen Anwendungsfall entwickelt wurde.
Fazit
Die Beacon API bietet eine robuste Lösung für die Hintergrunddatenübertragung, ohne die Seitennavigation zu blockieren. Durch das asynchrone Einreihen von Anfragen in die Warteschlange gewährleistet sie zuverlässige Datenübertragung bei gleichzeitiger Aufrechterhaltung einer optimalen Benutzererfahrung. Ob Sie Analytics-Tracking, Fehlerberichterstattung oder Benutzeraktions-Logging implementieren - navigator.sendBeacon()
bietet die Zuverlässigkeit und Performance, die traditionelle HTTP-Methoden während Seitenübergängen nicht bieten können.
Die Fire-and-Forget-Natur von Beacons macht sie ideal für Szenarien, in denen Sie Daten senden müssen, aber keine Antwort benötigen. In Kombination mit angemessenen Batching-Strategien und Payload-Optimierung wird die Beacon API zu einem unverzichtbaren Werkzeug für moderne Webanwendungen, die sowohl Datenerfassung als auch Benutzererfahrung priorisieren.
FAQs
Die Beacon API ist ein JavaScript-Webstandard, der kleine Datenmengen an einen Server sendet, ohne auf eine Antwort zu warten. Im Gegensatz zu fetch oder XMLHttpRequest werden Beacon-Anfragen vom Browser in die Warteschlange eingereiht und asynchron gesendet, was sie perfekt für Analytics und Logging während Seitennavigationsereignissen macht, bei denen traditionelle Anfragen fehlschlagen oder die Benutzererfahrung blockieren könnten.
Nein, die Beacon API ist für kleine Datenpakete konzipiert, die von den meisten Browsern typischerweise auf 64KB begrenzt sind. Wenn Sie größere Datenmengen senden müssen, erwägen Sie das Bündeln kleinerer Anfragen oder verwenden Sie alternative Methoden wie die Fetch API mit dem keepalive-Flag für nicht-kritische Timing-Szenarien.
Die Beacon API hat ausgezeichnete Unterstützung in allen modernen Browsern einschließlich Chrome, Firefox, Safari und Edge. Sie funktioniert nicht im Internet Explorer. Für die Unterstützung älterer Browser implementieren Sie einen Fallback mit XMLHttpRequest oder fetch, obwohl diese Alternativen möglicherweise nicht die gleiche Zuverlässigkeit während Page-Unload-Events bieten.
Die navigator.sendBeacon-Methode gibt einen Boolean zurück, der anzeigt, ob die Anfrage erfolgreich vom Browser in die Warteschlange eingereiht wurde, nicht ob sie den Server erreicht hat. Da Beacons Fire-and-Forget sind, können Sie nicht auf die Server-Antwort zugreifen oder definitiv wissen, ob die Daten empfangen wurden. Dies ist beabsichtigt für optimale Performance.
Verwenden Sie die Beacon API, wenn Sie Daten während Seitenübergängen, Unload-Events oder wenn die Seite ausgeblendet wird senden müssen und keine Antwort benötigen. Verwenden Sie fetch für reguläre API-Aufrufe, bei denen Sie Antworten, Fehler handhaben müssen oder wenn das Timing nicht kritisch für die Seitennavigation ist.