Protokollieren von Aktivitäten mit der Web Beacon API
Veröffentlicht: 2022-03-10 Die Beacon-API ist eine JavaScript-basierte Web-API zum Senden kleiner Datenmengen vom Browser an den Webserver, ohne auf eine Antwort zu warten. In diesem Artikel sehen wir uns an, wofür das nützlich sein kann, was es von bekannten Techniken wie XMLHTTPRequest
('Ajax') unterscheidet und wie Sie damit beginnen können.
Wenn Sie bereits wissen, warum Sie Beacon verwenden möchten, können Sie direkt zum Abschnitt „Erste Schritte“ springen.
Wozu dient die Beacon-API?
Die Beacon - API wird verwendet , um kleine Datenmengen an einen Server zu senden , ohne auf eine Antwort zu warten . Dieser letzte Teil ist entscheidend und der Schlüssel dafür, warum Beacon so nützlich ist – unser Code bekommt nicht einmal eine Antwort zu sehen, selbst wenn der Server eine sendet. Beacons dienen speziell dazu, Daten zu senden und dann zu vergessen. Wir erwarten keine Antwort und wir bekommen keine Antwort.
Stellen Sie es sich wie eine Postkarte vor, die im Urlaub nach Hause geschickt wird. Sie geben eine kleine Datenmenge darauf (ein bisschen „Ich wünschte, Sie wären hier“ und „Das Wetter war schön“), legen es in den Briefkasten und erwarten keine Antwort. Niemand schickt eine Postkarte zurück mit der Aufschrift „Ja, ich wäre wirklich gerne dabei gewesen, vielen Dank!“
Für moderne Websites und Anwendungen gibt es eine Reihe von Anwendungsfällen, die sehr gut in dieses Senden-und-Vergessen-Muster passen.
Tracking-Statistiken und Analysedaten
Der erste Anwendungsfall, der den meisten Menschen in den Sinn kommt, ist die Analytik. Große Lösungen wie Google Analytics geben vielleicht einen guten Überblick über Dinge wie Seitenbesuche, aber was wäre, wenn wir etwas Individuelleres wollen? Wir könnten etwas JavaScript schreiben, um zu verfolgen, was auf einer Seite passiert (vielleicht wie ein Benutzer mit einer Komponente interagiert, wie weit er gescrollt hat oder welche Artikel angezeigt wurden, bevor er einem CTA folgt), aber wir müssen diese Daten dann senden an den Server, wenn der Benutzer die Seite verlässt. Beacon ist dafür perfekt, da wir nur die Daten protokollieren und keine Antwort benötigen.
Es gibt keinen Grund, warum wir nicht auch die Art von alltäglichen Aufgaben abdecken könnten, die häufig von Google Analytics erledigt werden, indem Berichte über den Benutzer selbst und die Fähigkeiten seines Geräts und Browsers erstellt werden. Wenn der Benutzer eine angemeldete Sitzung hat, können Sie diese Statistiken sogar einer bekannten Person zuordnen. Welche Daten auch immer Sie sammeln, Sie können sie mit Beacon an den Server zurücksenden.
Debuggen und Protokollieren
Eine weitere nützliche Anwendung für dieses Verhalten ist das Protokollieren von Informationen aus Ihrem JavaScript-Code. Stellen Sie sich vor, Sie haben eine komplexe interaktive Komponente auf Ihrer Seite, die für alle Ihre Tests perfekt funktioniert, aber gelegentlich in der Produktion fehlschlägt. Sie wissen, dass es fehlschlägt, aber Sie können den Fehler nicht sehen, um mit dem Debuggen zu beginnen. Wenn Sie einen Fehler im Code selbst erkennen können, können Sie Diagnosen sammeln und Beacon verwenden, um alles zur Protokollierung zurückzusenden.
Tatsächlich kann jede Protokollierungsaufgabe sinnvollerweise mit Beacon durchgeführt werden, sei es das Erstellen von Speicherpunkten in einem Spiel, das Sammeln von Informationen zur Verwendung von Funktionen oder das Aufzeichnen von Ergebnissen eines multivariaten Tests. Wenn Sie möchten, dass der Server etwas im Browser passiert, ist Beacon wahrscheinlich ein Konkurrent.
Können wir das nicht schon?
Ich weiß was du denkst. Nichts davon ist neu, oder? Seit mehr als einem Jahrzehnt können wir mithilfe von XMLHTTPRequest
vom Browser zum Server kommunizieren. In jüngerer Zeit haben wir auch die Fetch-API, die mit einer moderneren Promise-basierten Schnittstelle fast dasselbe tut. Warum brauchen wir angesichts dessen überhaupt die Beacon-API?
Der Schlüssel hier ist, dass der Browser die Anfrage in eine Warteschlange stellen und senden kann, ohne die Ausführung von anderem Code zu blockieren , da wir keine Antwort erhalten. Was den Browser betrifft, spielt es keine Rolle, ob unser Code noch läuft oder nicht, oder wo die Skriptausführung hin muss, da es nichts zurückzugeben gibt, kann er das Senden der HTTP-Anfrage einfach in den Hintergrund stellen, bis es bequem ist schicken Sie es.
Das kann bedeuten, zu warten, bis die CPU-Last geringer ist oder bis das Netzwerk frei ist, oder es sogar sofort zu senden, wenn es möglich ist. Wichtig ist, dass der Browser das Beacon in die Warteschlange stellt und die Kontrolle sofort zurückgibt. Es hält die Dinge nicht auf, während das Beacon sendet.
Um zu verstehen, warum dies eine große Sache ist, müssen wir uns ansehen, wie und wann diese Art von Anfragen von unserem Code ausgegeben werden. Nehmen Sie unser Beispiel eines Analytics-Logging-Skripts. Unser Code misst möglicherweise, wie lange die Benutzer auf einer Seite bleiben, daher ist es wichtig, dass die Daten im letztmöglichen Moment an den Server zurückgesendet werden. Wenn der Benutzer eine Seite verlässt, möchten wir die Zeitmessung stoppen und die Daten nach Hause senden.
Normalerweise verwenden Sie entweder das Ereignis unload
oder beforeunload
, um die Protokollierung auszuführen. Diese werden ausgelöst, wenn der Benutzer beispielsweise einem Link auf der Seite folgt, um wegzunavigieren. Das Problem dabei ist, dass Code, der auf einem der Entladeereignisse ausgeführt wird, die Ausführung blockieren und das unload
der Seite verzögern kann. Wenn das Entladen der Seite verzögert wird, verzögert sich auch das Laden der nächsten Seite, sodass sich das Erlebnis wirklich träge anfühlt.
Denken Sie daran, wie langsam HTTP-Anfragen sein können. Wenn Sie an die Leistung denken, sind zusätzliche HTTP-Anforderungen normalerweise einer der Hauptfaktoren, die Sie zu reduzieren versuchen, da es sehr langsam sein kann, an das Netzwerk zu gehen und eine Antwort zu erhalten. Das Allerletzte, was Sie tun möchten, ist, diese Langsamkeit zwischen die Aktivierung eines Links und den Beginn der Anforderung für die nächste Seite zu legen.
Beacon umgeht dies, indem es die Anfrage ohne Blockierung in die Warteschlange stellt und die Kontrolle sofort wieder an Ihr Skript zurückgibt. Der Browser kümmert sich dann im Hintergrund darum, diese Anfrage zu senden, ohne sie zu blockieren. Dadurch wird alles viel schneller, was die Benutzer zufriedener macht und uns alle unsere Jobs behalten lässt.
Einstieg
Wir verstehen also, was Beacon ist und warum wir es verwenden könnten, also fangen wir mit etwas Code an. Die Grundlagen könnten nicht einfacher sein:
let result = navigator.sendBeacon(url, data);
Das Ergebnis ist boolesch, true
, wenn der Browser die Anfrage akzeptiert und in die Warteschlange gestellt hat, und false
, wenn dabei ein Problem aufgetreten ist.
Verwendung von navigator.sendBeacon()
navigator.sendBeacon
benötigt zwei Parameter. Die erste ist die URL, an die die Anfrage gestellt werden soll. Die Anforderung wird als HTTP-POST ausgeführt, wobei alle im zweiten Parameter angegebenen Daten gesendet werden.
Der Datenparameter kann in einem von mehreren Formaten vorliegen, die alle direkt von der Fetch-API übernommen werden. Dies kann ein Blob
, ein BufferSource
, FormData
oder URLSearchParams
– im Grunde alle Body-Typen, die bei einer Anfrage mit Fetch verwendet werden.
Ich verwende FormData
für grundlegende Schlüsselwertdaten, da es unkompliziert und einfach zurückzulesen ist.
// URL to send the data to let url = '/api/my-endpoint'; // Create a new FormData and add a key/value pair let data = new FormData(); data.append('hello', 'world'); let result = navigator.sendBeacon(url, data); if (result) { console.log('Successfully queued!'); } else { console.log('Failure.'); }
Browser-Unterstützung
Die Unterstützung in Browsern für Beacon ist sehr gut, mit den einzigen nennenswerten Ausnahmen Internet Explorer (funktioniert in Edge) und Opera Mini. Für die meisten Anwendungen sollte das in Ordnung sein, aber es lohnt sich, den Support zu testen, bevor Sie versuchen, navigator.sendBeacon
zu verwenden.
Das geht ganz einfach:
if (navigator.sendBeacon) { // Beacon code } else { // No Beacon. Maybe fall back to XHR? }
Wenn Beacon nicht verfügbar ist und Ihre Anfrage wichtig ist, können Sie auf eine Blockiermethode wie XHR zurückgreifen. Abhängig von Ihrer Zielgruppe und Ihrem Zweck können Sie sich auch dafür entscheiden, sich nicht darum zu kümmern.
Ein Beispiel: Protokollieren der Zeit auf einer Seite
Um dies in der Praxis zu sehen, erstellen wir ein einfaches System, um zu messen, wie lange ein Benutzer auf einer Seite bleibt. Wenn die Seite geladen wird, notieren wir die Uhrzeit, und wenn der Benutzer die Seite verlässt, senden wir die Startzeit und die aktuelle Uhrzeit an den Server.
Da uns nur die aufgewendete Zeit (nicht die tatsächliche Tageszeit) wichtig ist, können wir performance.now()
verwenden, um einen einfachen Zeitstempel zu erhalten, während die Seite geladen wird:
let startTime = performance.now();
Wenn wir unsere Anmeldung in eine Funktion einpacken, können wir sie aufrufen, wenn die Seite entladen wird.
let logVisit = function() { // Test that we have support if (!navigator.sendBeacon) return true; // URL to send the data to, eg let url = '/api/log-visit'; // Data to send let data = new FormData(); data.append('start', startTime); data.append('end', performance.now()); data.append('url', document.URL); // Let's go! navigator.sendBeacon(url, data); };
Schließlich müssen wir diese Funktion aufrufen, wenn der Benutzer die Seite verlässt. Mein erster Instinkt war, das unload
-Ereignis zu verwenden, aber Safari auf einem Mac scheint die Anfrage mit einer Sicherheitswarnung zu blockieren, also funktioniert beforeunload
hier gut für uns.
window.addEventListener('beforeunload', logVisit);
Wenn die Seite entladen wird (oder kurz davor), wird unsere Funktion logVisit()
aufgerufen und sofern der Browser die Beacon-API unterstützt, wird unser Beacon gesendet.
(Beachten Sie, dass wir, wenn es keine Beacon-Unterstützung gibt, true
zurückgeben und so tun, als ob alles großartig funktioniert hätte. Die Rückgabe von false
würde das Ereignis abbrechen und das Entladen der Seite stoppen. Das wäre bedauerlich.)
Überlegungen beim Tracking
Da sich so viele der potenziellen Verwendungszwecke für Beacon um die Verfolgung von Aktivitäten drehen, wäre es meiner Meinung nach nachlässig, die soziale und rechtliche Verantwortung nicht zu erwähnen, die wir als Entwickler beim Protokollieren und Verfolgen von Aktivitäten haben, die auf Benutzer zurückgeführt werden könnten.
DSGVO
Wir können an die jüngsten europäischen DSGVO-Gesetze denken, wenn sie sich auf E-Mails beziehen, aber natürlich bezieht sich die Gesetzgebung auf die Speicherung jeglicher Art von personenbezogenen Daten. Wenn Sie wissen, wer Ihre Benutzer sind und ihre Sitzungen identifizieren können, sollten Sie überprüfen, welche Aktivitäten Sie protokollieren und wie sie sich auf Ihre angegebenen Richtlinien beziehen.
Oft müssen wir nicht so viele Daten nachverfolgen, wie es uns die Entwickler sagen. Es kann besser sein, absichtlich keine Informationen zu speichern, die einen Benutzer identifizieren würden, und dann verringern Sie die Wahrscheinlichkeit, dass etwas falsch gemacht wird.
DNT: Nicht verfolgen
Zusätzlich zu den gesetzlichen Anforderungen verfügen die meisten Browser über eine Einstellung, die es dem Benutzer ermöglicht, den Wunsch zu äußern, nicht getrackt zu werden. Do Not Track sendet einen HTTP-Header mit der Anfrage, der so aussieht:
DNT: 1
Wenn Sie Daten protokollieren, die einen bestimmten Benutzer verfolgen können, und der Benutzer einen positiven DNT
-Header sendet, ist es am besten, den Wünschen des Benutzers zu folgen und diese Daten zu anonymisieren oder sie überhaupt nicht zu verfolgen.
In PHP können Sie diesen Header beispielsweise sehr einfach wie folgt testen:
if (!empty($_SERVER['HTTP_DNT'])) { // User does not wish to be tracked ... }
Abschließend
Die Beacon-API ist eine wirklich nützliche Methode, um Daten von einer Seite zurück an den Server zu senden, insbesondere im Zusammenhang mit der Protokollierung. Die Browserunterstützung ist sehr breit und ermöglicht Ihnen, Daten nahtlos zu protokollieren, ohne das Surferlebnis des Benutzers und die Leistung Ihrer Website zu beeinträchtigen. Die nicht blockierende Natur der Anfragen bedeutet, dass die Leistung viel schneller ist als bei Alternativen wie XHR und Fetch.
Wenn Sie mehr über die Beacon-API lesen möchten, sind die folgenden Seiten einen Blick wert.
- „W3C-Beacon-Spezifikation“, W3C-Kandidatenempfehlung
- „MDN Beacon-Dokumentation“, MDN-Webdokumentation, Mozilla
- „Informationen zur Browserunterstützung“, caniuse.com