Rejestrowanie aktywności za pomocą interfejsu API Web Beacon
Opublikowany: 2022-03-10 Beacon API to internetowy interfejs API oparty na języku JavaScript, który umożliwia wysyłanie niewielkich ilości danych z przeglądarki na serwer sieciowy bez oczekiwania na odpowiedź. W tym artykule przyjrzymy się, do czego może to być przydatne, czym różni się od znanych technik, takich jak XMLHTTPRequest
('Ajax') i jak możesz zacząć z niego korzystać.
Jeśli wiesz, dlaczego chcesz już korzystać z Beacona, możesz przejść bezpośrednio do sekcji Pierwsze kroki.
Do czego służy interfejs Beacon API?
Beacon API służy do wysyłania niewielkich ilości danych na serwer bez oczekiwania na odpowiedź . Ta ostatnia część ma kluczowe znaczenie i jest kluczem do tego, dlaczego Beacon jest tak użyteczny — nasz kod nigdy nie otrzymuje odpowiedzi, nawet jeśli serwer ją wyśle. Beacony służą specjalnie do wysyłania danych, a następnie zapominania o nich. Nie oczekujemy odpowiedzi i nie otrzymujemy odpowiedzi.
Pomyśl o tym jak o pocztówce wysłanej do domu na wakacjach. Umieszczasz na nim niewielką ilość danych (trochę „Szkoda, że tu nie byłeś” i „Pogoda była piękna”), wkładasz do skrzynki pocztowej i nie oczekujesz odpowiedzi. Nikt nie wysyła pocztówki zwrotnej z napisem „Tak, naprawdę chciałbym tam być, bardzo dziękuję!”
W przypadku nowoczesnych witryn i aplikacji istnieje wiele przypadków użycia, które doskonale pasują do tego wzorca „wyślij i zapomnij”.
Śledzenie statystyk i danych analitycznych
Pierwszym przypadkiem użycia, który przychodzi do głowy większości ludzi, jest analityka. Duże rozwiązania, takie jak Google Analytics, mogą dać dobry przegląd takich rzeczy, jak odwiedziny na stronie, ale co by było, gdybyśmy chcieli czegoś bardziej dostosowanego? Moglibyśmy napisać kod JavaScript, aby śledzić, co dzieje się na stronie (na przykład, w jaki sposób użytkownik wchodzi w interakcję z komponentem, jak daleko przewinął się lub które artykuły zostały wyświetlone, zanim podążą za wezwaniem do działania), ale wtedy musimy wysłać te dane do serwera, gdy użytkownik opuszcza stronę. Beacon jest do tego idealny, ponieważ po prostu rejestrujemy dane i nie potrzebujemy odpowiedzi.
Nie ma powodu, dla którego nie moglibyśmy również omówić tego rodzaju przyziemnych zadań często wykonywanych przez Google Analytics, raportowania o samym użytkowniku oraz możliwościach jego urządzenia i przeglądarki. Jeśli użytkownik ma zalogowaną sesję, możesz nawet powiązać te statystyki ze znaną osobą. Jakiekolwiek dane zbierzesz, możesz odesłać je z powrotem na serwer za pomocą Beacon.
Debugowanie i rejestrowanie
Inną przydatną aplikacją do tego zachowania jest rejestrowanie informacji z kodu JavaScript. Wyobraź sobie, że masz na swojej stronie złożony interaktywny komponent, który doskonale sprawdza się we wszystkich testach, ale czasami nie działa w środowisku produkcyjnym. Wiesz, że to się nie udaje, ale nie widzisz błędu, aby rozpocząć debugowanie. Jeśli możesz wykryć błąd w samym kodzie, możesz zebrać dane diagnostyczne i użyć Beacon, aby odesłać wszystko do zarejestrowania.
W rzeczywistości każde zadanie rejestrowania można z pożytkiem wykonać za pomocą Beacon, na przykład tworzenie punktów zapisu w grze, zbieranie informacji o użyciu funkcji lub rejestrowanie wyników testu na wielu odmianach. Jeśli jest to coś, co dzieje się w przeglądarce, o czym chcesz, aby serwer wiedział, prawdopodobnie jest to Beacon.
Czy nie możemy już tego zrobić?
Wiem, o czym myślisz. Nic z tego nie jest nowe, prawda? Od ponad dekady jesteśmy w stanie komunikować się z przeglądarki z serwerem za pomocą XMLHTTPRequest
. Od niedawna mamy również Fetch API, które robi to samo z bardziej nowoczesnym interfejsem opartym na obietnicach. Biorąc to pod uwagę, dlaczego w ogóle potrzebujemy Beacon API?
Kluczem jest tutaj to, że ponieważ nie otrzymujemy odpowiedzi, przeglądarka może ustawić żądanie w kolejce i wysłać je bez blokowania wykonywania jakiegokolwiek innego kodu. Jeśli chodzi o przeglądarkę, nie ma znaczenia, czy nasz kod nadal działa, czy nie, ani gdzie ma nastąpić wykonanie skryptu, ponieważ nie ma nic do zwrócenia, może po prostu w tle wysyłanie żądania HTTP, dopóki nie będzie to wygodne Wyślij to.
Może to oznaczać czekanie, aż obciążenie procesora będzie mniejsze lub aż sieć będzie wolna, a nawet wysłanie go od razu, jeśli to możliwe. Ważną rzeczą jest to, że przeglądarka kolejkuje sygnał nawigacyjny i natychmiast zwraca kontrolę. Nie zatrzymuje rzeczy podczas wysyłania sygnału nawigacyjnego.
Aby zrozumieć, dlaczego jest to wielka sprawa, musimy przyjrzeć się, jak i kiedy tego rodzaju żądania są wysyłane z naszego kodu. Zapoznaj się z naszym przykładem skryptu rejestrowania danych analitycznych. Nasz kod może mierzyć czas, jaki użytkownicy spędzają na stronie, więc kluczowe staje się, aby dane były wysyłane z powrotem na serwer w ostatnim możliwym momencie. Kiedy użytkownik chce opuścić stronę, chcemy zatrzymać synchronizację i wysłać dane z powrotem do domu.
Zazwyczaj do wykonania rejestrowania używa się zdarzenia unload
lub beforeunload
. Są one uruchamiane, gdy użytkownik robi coś takiego jak kliknięcie linku na stronie, aby opuścić stronę. Problem polega na tym, że kod działający na jednym ze zdarzeń unload
może zablokować wykonanie i opóźnić wyładowanie strony. Jeśli rozładowywanie strony jest opóźnione, ładowanie kolejnej strony również jest opóźnione, a więc wrażenia są naprawdę powolne.
Pamiętaj, jak powolne mogą być żądania HTTP. Jeśli myślisz o wydajności, zazwyczaj jednym z głównych czynników, które próbujesz ograniczyć, są dodatkowe żądania HTTP, ponieważ wychodzenie do sieci i uzyskiwanie odpowiedzi może być bardzo powolne. Ostatnią rzeczą, którą chcesz zrobić, to umieścić tę powolność między aktywacją łącza a początkiem żądania następnej strony.
Beacon omija ten problem, ustawiając żądanie w kolejce bez blokowania, zwracając kontrolę natychmiast z powrotem do skryptu. Przeglądarka następnie zajmuje się wysyłaniem tego żądania w tle bez blokowania. Dzięki temu wszystko jest znacznie szybsze, co sprawia, że użytkownicy są szczęśliwsi, a my wszyscy zachowujemy pracę.
Pierwsze kroki
Rozumiemy więc, czym jest Beacon i dlaczego możemy go używać, więc zacznijmy od jakiegoś kodu. Podstawy nie mogą być prostsze:
let result = navigator.sendBeacon(url, data);
Wynik jest wartością logiczną, true
, jeśli przeglądarka zaakceptowała i umieściła żądanie w kolejce, i false
, jeśli wystąpił problem.
Korzystanie navigator.sendBeacon()
navigator.sendBeacon
przyjmuje dwa parametry. Pierwszy to adres URL, do którego należy wysłać żądanie. Żądanie wykonywane jest jako HTTP POST, wysyłając dowolne dane podane w drugim parametrze.
Parametr data może mieć jeden z kilku formatów, z których wszystkie są pobierane bezpośrednio z interfejsu API Fetch. Może to być Blob
, BufferSource
, FormData
lub URLSearchParams
— w zasadzie dowolny typ treści używany podczas wysyłania żądania za pomocą Fetch.
Lubię używać FormData
do podstawowych danych klucz-wartość, ponieważ jest nieskomplikowany i łatwy do odczytania.
// 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.'); }
Obsługa przeglądarki
Obsługa Beacon w przeglądarkach jest bardzo dobra, a jedynymi godnymi uwagi wyjątkami są Internet Explorer (działa w Edge) i Opera Mini. W przypadku większości zastosowań powinno to wystarczyć, ale warto przetestować obsługę przed próbą użycia navigator.sendBeacon
.
To proste:
if (navigator.sendBeacon) { // Beacon code } else { // No Beacon. Maybe fall back to XHR? }
Jeśli Beacon nie jest dostępny, a Twoja prośba jest ważna, możesz wrócić do metody blokowania, takiej jak XHR. W zależności od odbiorców i celu, możesz równie dobrze zdecydować się nie zawracać sobie głowy.
Przykład: czas logowania na stronie
Aby zobaczyć to w praktyce, stwórzmy podstawowy system mierzący czas przebywania użytkownika na stronie. Kiedy strona się załaduje, zanotujemy czas, a kiedy użytkownik opuści stronę, wyślemy czas rozpoczęcia i aktualny czas na serwer.
Ponieważ zależy nam tylko na spędzonym czasie (nie o rzeczywistej porze dnia), możemy użyć performance.now()
, aby uzyskać podstawowy znacznik czasu podczas ładowania strony:
let startTime = performance.now();
Jeśli zamkniemy nasze logowanie do funkcji, możemy je wywołać, gdy strona się wyładuje.
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); };
Na koniec musimy wywołać tę funkcję, gdy użytkownik opuści stronę. Moim pierwszym odruchem było użycie zdarzenia unload
, ale Safari na Macu wydaje się blokować żądanie ostrzeżeniem o zabezpieczeniach, więc beforeunload
działa tutaj dobrze.
window.addEventListener('beforeunload', logVisit);
Gdy strona się wyładuje (lub tuż przed tym) zostanie wywołana nasza logVisit()
i pod warunkiem, że przeglądarka obsługuje Beacon API, zostanie wysłany nasz sygnał nawigacyjny.
(Zauważ, że jeśli nie ma obsługi Beacon, zwracamy true
i udajemy, że wszystko działało świetnie. Zwrócenie false
spowoduje anulowanie zdarzenia i zatrzymanie wyładowania strony. To byłoby niefortunne.)
Rozważania podczas śledzenia
Ponieważ tak wiele potencjalnych zastosowań Beacona kręci się wokół śledzenia aktywności, myślę, że niestosowne byłoby nie wspominanie o obowiązkach społecznych i prawnych, jakie mamy jako programiści podczas rejestrowania i śledzenia aktywności, które mogą być powiązane z użytkownikami.
RODO
Możemy myśleć o ostatnich europejskich przepisach RODO, ponieważ dotyczą one poczty e-mail, ale oczywiście przepisy dotyczą przechowywania wszelkiego rodzaju danych osobowych. Jeśli wiesz, kim są Twoi użytkownicy i potrafisz zidentyfikować ich sesje, powinieneś sprawdzić, jaką aktywność rejestrujesz i jaki ma to związek z określonymi przez Ciebie zasadami.
Często nie musimy śledzić tylu danych, ile instynktownie podpowiadają nam programiści. Lepiej celowo nie przechowywać informacji, które mogłyby zidentyfikować użytkownika, a wtedy zmniejszysz prawdopodobieństwo popełnienia błędu.
DNT: nie śledź
Oprócz wymogów prawnych większość przeglądarek ma ustawienie umożliwiające użytkownikowi wyrażenie chęci, by nie być śledzonym. Do Not Track wysyła nagłówek HTTP z żądaniem, które wygląda tak:
DNT: 1
Jeśli rejestrujesz dane, które mogą śledzić konkretnego użytkownika, a użytkownik wysyła pozytywny nagłówek DNT
, najlepiej będzie postępować zgodnie z życzeniami użytkownika i anonimizować te dane lub wcale ich nie śledzić.
Na przykład w PHP możesz bardzo łatwo przetestować ten nagłówek w następujący sposób:
if (!empty($_SERVER['HTTP_DNT'])) { // User does not wish to be tracked ... }
Na zakończenie
Beacon API jest naprawdę użytecznym sposobem wysyłania danych ze strony z powrotem na serwer, szczególnie w kontekście logowania. Obsługa przeglądarek jest bardzo szeroka i umożliwia bezproblemowe rejestrowanie danych bez negatywnego wpływu na wrażenia użytkownika podczas przeglądania i wydajność witryny. Nieblokujący charakter żądań oznacza, że wydajność jest znacznie szybsza niż w przypadku alternatyw, takich jak XHR i Fetch.
Jeśli chcesz dowiedzieć się więcej o Beacon API, warto zajrzeć na poniższe strony.
- „Specyfikacja W3C Beacon”, Rekomendacja kandydata W3C
- „Dokumentacja MDN Beacon”, dokumentacja internetowa MDN, Mozilla
- „Informacje wsparcia przeglądarki”, caniuse.com