Регистрация активности с помощью API веб-маяков
Опубликовано: 2022-03-10 Beacon API — это веб-API на основе JavaScript для отправки небольших объемов данных из браузера на веб-сервер без ожидания ответа. В этой статье мы рассмотрим, для чего это может быть полезно, чем оно отличается от привычных методов, таких как XMLHTTPRequest
(«Ajax»), и как вы можете начать его использовать.
Если вы уже знаете, почему хотите использовать Beacon, смело переходите непосредственно к разделу «Начало работы».
Для чего нужен API маяка?
Beacon API используется для отправки небольших объемов данных на сервер без ожидания ответа . Эта последняя часть имеет решающее значение и является ключом к тому, почему Beacon так полезен — наш код никогда не увидит ответа, даже если сервер отправит его. Маяки специально предназначены для отправки данных, а затем забывания об этом. Мы не ожидаем ответа и не получаем ответа.
Думайте об этом как об открытке, отправленной домой во время отпуска. Вы помещаете на него небольшое количество данных (немного «Хотел бы вы быть здесь» и «Погода была прекрасная»), кладете его в почтовый ящик и не ожидаете ответа. Никто не присылает ответную открытку со словами: «Да, я действительно хотел бы быть там, большое спасибо!»
Для современных веб-сайтов и приложений существует ряд вариантов использования, которые очень точно попадают в этот шаблон «отправил и забыл».
Отслеживание статистики и данных аналитики
Первый вариант использования, который приходит на ум большинству людей, — это аналитика. Большие решения, такие как Google Analytics, могут дать хороший обзор таких вещей, как посещения страниц, но что, если нам нужно что-то более индивидуальное? Мы могли бы написать некоторый JavaScript для отслеживания того, что происходит на странице (например, как пользователь взаимодействует с компонентом, как далеко он прокручивается или какие статьи были показаны до того, как они следуют призыву к действию), но затем нам нужно отправить эти данные. на сервер, когда пользователь покидает страницу. Beacon идеально подходит для этого, так как мы просто регистрируем данные и не нуждаемся в ответе.
Нет никаких причин, по которым мы не могли бы также охватить ряд рутинных задач, часто выполняемых Google Analytics, сообщая о самих пользователях и возможностях их устройства и браузера. Если у пользователя есть сеанс входа в систему, вы даже можете связать эту статистику с известным человеком. Какие бы данные вы ни собирали, вы можете отправить их обратно на сервер с помощью Beacon.
Отладка и ведение журнала
Еще одно полезное приложение для этого поведения — регистрация информации из вашего кода JavaScript. Представьте, что у вас на странице есть сложный интерактивный компонент, который отлично работает во всех ваших тестах, но иногда дает сбой в работе. Вы знаете, что это сбой, но вы не можете увидеть ошибку, чтобы начать ее отладку. Если вы можете обнаружить сбой в самом коде, вы можете затем собрать диагностику и использовать Beacon, чтобы отправить все это обратно для регистрации.
На самом деле с помощью Beacon можно с пользой выполнить любую задачу регистрации, будь то создание точек сохранения в игре, сбор информации об использовании функций или запись результатов многовариантного теста. Если в браузере происходит что-то, о чем вы хотите, чтобы сервер знал, то Beacon, скорее всего, является претендентом.
Разве мы уже не можем сделать это?
Я знаю, о чем ты думаешь. Все это не ново, не так ли? Мы можем обмениваться данными из браузера с сервером с помощью XMLHTTPRequest
уже более десяти лет. Совсем недавно у нас также появился Fetch API, который делает то же самое с более современным интерфейсом на основе обещаний. Учитывая это, зачем нам вообще нужен Beacon API?
Суть здесь в том, что поскольку мы не получаем ответа, браузер может поставить запрос в очередь и отправить его, не блокируя выполнение какого-либо другого кода. Что касается браузера, то не имеет значения, работает наш код или нет, или куда делось выполнение скрипта, так как возвращать нечего, он может просто отложить отправку HTTP-запроса в фоновом режиме до тех пор, пока не будет удобно Отправь это.
Это может означать ожидание, пока загрузка ЦП не снизится, или пока сеть не освободится, или даже просто отправка сразу, если это возможно. Важно то, что браузер ставит маяк в очередь и немедленно возвращает управление. Он не задерживает вещи, пока маяк посылает.
Чтобы понять, почему это так важно, нам нужно посмотреть, как и когда такого рода запросы выдаются из нашего кода. Возьмем наш пример сценария ведения журнала аналитики. Наш код может определять время, которое пользователи проводят на странице, поэтому становится критически важным, чтобы данные отправлялись обратно на сервер в последний возможный момент. Когда пользователь покидает страницу, мы хотим остановить отсчет времени и отправить данные домой.
Как правило, вы должны использовать событие unload
или beforeunload
для выполнения ведения журнала. Они запускаются, когда пользователь делает что-то вроде перехода по ссылке на странице, чтобы уйти. Проблема здесь в том, что код, запущенный на одном из событий unload
, может заблокировать выполнение и задержать выгрузку страницы. Если выгрузка страницы задерживается, то загрузка следующей страницы также задерживается, поэтому работа кажется очень вялой.
Имейте в виду, насколько медленными могут быть HTTP-запросы. Если вы думаете о производительности, обычно одним из основных факторов, которые вы пытаетесь сократить, являются дополнительные HTTP-запросы, потому что выход в сеть и получение ответа может быть очень медленным. Самое последнее, что вы хотите сделать, это поставить эту медлительность между активацией ссылки и началом запроса на следующую страницу.
Beacon обходит это, помещая запрос в очередь без блокировки, немедленно возвращая управление вашему сценарию. Затем браузер позаботится об отправке этого запроса в фоновом режиме без блокировки. Это делает все намного быстрее, что делает пользователей счастливее и позволяет всем нам сохранить свою работу.
Начиная
Итак, мы поняли, что такое Beacon и почему мы можем его использовать, так что давайте начнем с кода. Основы не могут быть проще:
let result = navigator.sendBeacon(url, data);
Результат — логическое значение, true
, если браузер принял и поставил запрос в очередь, и false
, если при этом возникла проблема.
Использование navigator.sendBeacon()
navigator.sendBeacon
принимает два параметра. Первый — это URL-адрес, на который нужно сделать запрос. Запрос выполняется как HTTP POST, отправляя любые данные, указанные во втором параметре.
Параметр данных может быть в одном из нескольких форматов, каждый из которых берется непосредственно из Fetch API. Это может быть Blob
, BufferSource
, FormData
или URLSearchParams
— в основном любой из типов тела, используемых при выполнении запроса с помощью Fetch.
Мне нравится использовать FormData
для основных данных типа «ключ-значение», так как это несложно и легко считывается.
// 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.'); }
Поддержка браузера
Поддержка Beacon в браузерах очень хорошая, за исключением Internet Explorer (работает в Edge) и Opera Mini. Для большинства применений это должно быть хорошо, но стоит протестировать поддержку, прежде чем пытаться использовать navigator.sendBeacon
.
Это легко сделать:
if (navigator.sendBeacon) { // Beacon code } else { // No Beacon. Maybe fall back to XHR? }
Если Beacon недоступен, а ваш запрос важен, вы можете вернуться к методу блокировки, например XHR. В зависимости от вашей аудитории и целей вы также можете не беспокоиться.
Пример: регистрация времени на странице
Чтобы увидеть это на практике, давайте создадим базовую систему для определения времени, в течение которого пользователь остается на странице. Когда страница загружается, мы фиксируем время, а когда пользователь покидает страницу, мы отправляем время начала и текущее время на сервер.
Поскольку нас интересует только затраченное время (а не фактическое время суток), мы можем использовать performance.now()
для получения базовой метки времени при загрузке страницы:
let startTime = performance.now();
Если мы обернем нашу регистрацию в функцию, мы сможем вызывать ее, когда страница выгружается.
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); };
Наконец, нам нужно вызвать эту функцию, когда пользователь покидает страницу. Моим первым побуждением было использовать событие unload
, но Safari на Mac, похоже, блокирует запрос с предупреждением о безопасности, поэтому в данном случае beforeunload
отлично подходит для нас.
window.addEventListener('beforeunload', logVisit);
Когда страница выгружается (или непосредственно перед этим), будет вызвана наша logVisit()
и, если браузер поддерживает Beacon API, будет отправлен наш маяк.
(Обратите внимание, что если нет поддержки Beacon, мы возвращаем true
и делаем вид, что все работает отлично. Возврат false
отменяет событие и останавливает выгрузку страницы. Это было бы прискорбно.)
Соображения при отслеживании
Поскольку многие из потенциальных применений Beacon связаны с отслеживанием активности, я думаю, было бы упущением не упомянуть о социальной и юридической ответственности, которую мы несем как разработчики при регистрации и отслеживании активности, которая может быть связана с пользователями.
GDPR
Мы можем думать о недавних европейских законах GDPR, поскольку они касаются электронной почты, но, конечно же, законодательство касается хранения любых типов персональных данных. Если вы знаете, кто ваши пользователи, и можете идентифицировать их сеансы, вам следует проверить, какие действия вы регистрируете и как они связаны с вашими заявленными политиками.
Часто нам не нужно отслеживать столько данных, сколько наши инстинкты, как говорят нам разработчики. Может быть лучше намеренно не хранить информацию, которая позволила бы идентифицировать пользователя, и тогда вы уменьшите вероятность того, что что-то сделаете неправильно.
DNT: не отслеживать
В дополнение к юридическим требованиям, в большинстве браузеров есть настройка, позволяющая пользователю выразить желание не быть отслеженным. Do Not Track отправляет HTTP-заголовок с запросом, который выглядит следующим образом:
DNT: 1
Если вы регистрируете данные, которые могут отслеживать конкретного пользователя, и пользователь отправляет положительный заголовок DNT
, то было бы лучше следовать пожеланиям пользователя и анонимизировать эти данные или вообще не отслеживать их.
В PHP, например, вы можете очень легко протестировать этот заголовок следующим образом:
if (!empty($_SERVER['HTTP_DNT'])) { // User does not wish to be tracked ... }
В заключение
Beacon API — это действительно полезный способ отправки данных со страницы обратно на сервер, особенно в контексте ведения журнала. Поддержка браузеров очень широка, и это позволяет вам беспрепятственно регистрировать данные, не оказывая негативного влияния на работу пользователя в Интернете и производительность вашего сайта. Неблокирующий характер запросов означает, что производительность намного выше, чем у альтернатив, таких как XHR и Fetch.
Если вы хотите узнать больше об API Beacon, вам стоит посетить следующие сайты.
- «Спецификация W3C Beacon», рекомендация кандидата W3C
- «Документация MDN Beacon», веб-документы MDN, Mozilla
- «Информация о поддержке браузера», caniuse.com