WebビーコンAPIを使用したロギングアクティビティ
公開: 2022-03-10 Beacon APIは、応答を待たずにブラウザからWebサーバーに少量のデータを送信するためのJavaScriptベースのWebAPIです。 この記事では、それが何に役立つのか、 XMLHTTPRequest
( 'Ajax')のようなおなじみのテクニックと何が違うのか、そしてどのようにそれを使い始めることができるのかを見ていきます。
ビーコンを使用する理由がすでにわかっている場合は、「はじめに」セクションに直接ジャンプしてください。
ビーコンAPIは何のためにありますか?
Beacon APIは、応答を待たずに少量のデータをサーバーに送信するために使用されます。 この最後の部分は重要であり、ビーコンが非常に役立つ理由の鍵となります。サーバーが応答を送信したとしても、コードが応答を確認することはありません。 ビーコンは、特にデータを送信し、それを忘れるためのものです。 応答を期待しておらず、応答もありません。
休暇中に家に送られるはがきのように考えてください。 少量のデータ(「ここにいたらいいのに」と「天気が良かった」)をメールボックスに入れても、応答は期待できません。 「はい、実際にそこにいたらいいのにと思います。ありがとうございました!」というハガキは返送されません。
最新のWebサイトやアプリケーションの場合、この送信と忘れのパターンに非常にうまく当てはまるユースケースがいくつかあります。
統計と分析データの追跡
ほとんどの人が頭に浮かぶ最初のユースケースは分析です。 グーグルアナリティクスのような大きなソリューションは、ページ訪問のようなものの良い概観を与えるかもしれませんが、もっとカスタマイズされたものが必要な場合はどうでしょうか? ページで何が起こっているか(ユーザーがコンポーネントをどのように操作したか、スクロールした距離、CTAに従う前にどの記事が表示されたかなど)を追跡するJavaScriptを作成することもできますが、そのデータを送信する必要があります。ユーザーがページを離れたときにサーバーに送信されます。 ビーコンはこれに最適です。データをログに記録するだけで、応答は必要ないからです。
ユーザー自身とそのデバイスとブラウザの機能について報告する、GoogleAnalyticsによって頻繁に処理される種類のありふれたタスクもカバーできなかった理由はありません。 ユーザーがログインセッションを持っている場合は、それらの統計を既知の個人に関連付けることもできます。 収集したデータが何であれ、ビーコンを使用してサーバーに送り返すことができます。
デバッグとロギング
この動作に役立つもう1つのアプリケーションは、JavaScriptコードから情報をログに記録することです。 ページ上に複雑なインタラクティブコンポーネントがあり、すべてのテストで完全に機能するが、本番環境で失敗することがあると想像してください。 失敗していることはわかっていますが、デバッグを開始するためにエラーを確認することはできません。 コード自体の障害を検出できる場合は、診断を収集し、ビーコンを使用してすべてをログに送信することができます。
実際、ゲームでセーブポイントを作成したり、機能の使用に関する情報を収集したり、多変量テストの結果を記録したりするなど、あらゆるロギングタスクをビーコンを使用して便利に実行できます。 サーバーに知らせたいブラウザで発生することがある場合は、ビーコンが競合相手である可能性があります。
私たちはすでにこれを行うことはできませんか?
私はあなたが何を考えているか知っています。 これはどれも新しいことではありませんか? 10年以上の間、 XMLHTTPRequest
を使用してブラウザからサーバーに通信することができました。 最近では、より最新のPromiseベースのインターフェースでほぼ同じことを行うFetchAPIもあります。 それを考えると、なぜビーコンAPIが必要なのですか?
ここで重要なのは、応答がないため、ブラウザは他のコードの実行をブロックすることなく、リクエストをキューに入れて送信できることです。 ブラウザに関する限り、コードがまだ実行されているかどうか、またはスクリプトの実行がどこに到達したかは関係ありません。コードを返すものがないため、都合がよいまでHTTPリクエストの送信をバックグラウンドで実行できます。それを送る。
これは、CPUの負荷が低くなるまで、またはネットワークが解放されるまで、あるいは可能であればすぐに送信するまで待つことを意味する場合があります。 重要なことは、ブラウザがビーコンをキューに入れ、すぐに制御を返すことです。 ビーコンが送信している間、それは物事を保持しません。
これが大きな問題である理由を理解するには、これらの種類のリクエストがコードからいつどのように発行されるかを調べる必要があります。 分析ログスクリプトの例を見てみましょう。 私たちのコードは、ユーザーがページに費やす時間を計る可能性があるため、可能な限り最後の瞬間にデータをサーバーに送り返すことが重要になります。 ユーザーがページを離れるとき、タイミングを停止してデータを家に送り返したいと思います。
通常、ログを実行するには、 unload
イベントまたはbeforeunload
イベントのいずれかを使用します。 これらは、ユーザーがページ上のリンクをたどって移動するなどの操作を行ったときに発生します。 ここでの問題は、 unload
イベントの1つで実行されているコードが実行をブロックし、ページのアンロードを遅らせる可能性があることです。 ページのアンロードが遅れると、次のページの読み込みも遅れるので、エクスペリエンスが非常に遅く感じられます。
HTTPリクエストがどれほど遅くなる可能性があるかを覚えておいてください。 パフォーマンスについて考えている場合、通常、削減しようとする主な要因の1つは、余分なHTTPリクエストです。これは、ネットワークに接続して応答を取得するのが非常に遅い場合があるためです。 あなたがしたい最後のことは、リンクのアクティブ化と次のページのリクエストの開始の間にその遅さを置くことです。
ビーコンは、ブロックせずにリクエストをキューに入れ、制御をすぐにスクリプトに戻すことで、これを回避します。 その後、ブラウザはブロックせずにバックグラウンドでそのリクエストを送信します。 これにより、すべてがはるかに高速になり、ユーザーがより幸せになり、私たち全員が仕事を続けることができます。
入門
これで、ビーコンとは何か、なぜビーコンを使用するのかがわかったので、コードから始めましょう。 基本はこれ以上簡単なものではありません。
let result = navigator.sendBeacon(url, data);
結果はブール値であり、ブラウザがリクエストを受け入れてキューに入れた場合はtrue
、問題が発生した場合はfalse
になります。
navigator.sendBeacon()
使用
navigator.sendBeacon
は2つのパラメーターを取ります。 1つ目は、リクエストを行うURLです。 リクエストはHTTPPOSTとして実行され、2番目のパラメーターで提供されたデータを送信します。
データパラメータは、いくつかの形式のいずれかにすることができます。これらはすべて、FetchAPIから直接取得されます。 これは、 Blob
、 BufferSource
、 FormData
、またはURLSearchParams
にすることができます。基本的に、Fetchを使用してリクエストを行うときに使用される任意のボディタイプです。
複雑でなく、読み返しやすいので、基本的なKey-Valueデータに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.'); }
ブラウザのサポート
ビーコンのブラウザでのサポートは非常に優れていますが、注目すべき例外はInternet Explorer(Edgeで動作)とOperaMiniだけです。 ほとんどの場合、これで問題ありませんが、 navigator.sendBeacon
を使用する前に、サポートをテストする価値があります。
それは簡単です:
if (navigator.sendBeacon) { // Beacon code } else { // No Beacon. Maybe fall back to XHR? }
ビーコンが利用できず、リクエストが重要な場合は、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
イベントを使用することでしたが、Mac上のSafariはセキュリティ警告でリクエストをブロックしているようです。そのため、ここではアンロード前にbeforeunload
動作します。
window.addEventListener('beforeunload', logVisit);
ページがアンロードされると(またはアンロードされる直前に)、 logVisit()
関数が呼び出され、ブラウザーがビーコンAPIをサポートしている場合は、ビーコンが送信されます。
(ビーコンのサポートがない場合は、 true
を返し、すべてうまくいったふりをしますfalse
を返すと、イベントがキャンセルされ、ページのアンロードが停止します。これは残念なことです。)
追跡時の考慮事項
ビーコンの潜在的な用途の多くは活動の追跡を中心に展開しているため、ユーザーに結び付けられる可能性のある活動を記録および追跡する際の開発者としての社会的および法的責任は言うまでもありません。
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などの代替手段よりもパフォーマンスがはるかに速いことを意味します。
Beacon APIについて詳しく知りたい場合は、次のサイトを一見の価値があります。
- 「W3Cビーコン仕様」、W3C候補の推奨事項
- 「MDNBeaconドキュメント」、MDN Webドキュメント、Mozilla
- 「ブラウザサポート情報」caniuse.com