サブスクリプションなしでウェブサイトのライブ訪問者を追跡する
あるクライアントが、誰が自分のウェブサイトにリアルタイムでアクセスしているかを確認したいと考えていました。
彼らはTidioのウィジェットを気に入っていましたが、サブスクリプション料金を支払いたくはありませんでした。
課題は2つの側面がありました:
- サイトは、別のホスティング環境上のWordPressを使用していた。
- WordPressの設定にFirebaseを直接追加することができなかった。
私はFirebaseを使用して外部トラッカーを構築しました。その仕組みは以下の通りです。
解決策
WordPressのヘッダーに単一のscriptタグを使用しました。このスクリプトは、独立したFirebaseプロジェクトに接続します。
• ライブプレゼンス: Firebase Realtime DatabaseとonDisconnect()関数を使用しました。これにより、ユーザーがタブを閉じたり接続が切れたりした際に、自動的に「オンライン」リストから削除されます。
• 訪問者履歴: Netlify Functionを使用してFirestoreにデータを書き込みます。これにより、サーバーサイドでのIPジオロケーションが可能になります。
• セキュリティ: 匿名認証(anonymous authentication)を使用しました。訪問者は自身のセッションノードにのみ書き込みができ、管理者のみが全リストを読み取ることができます。
厄介なバグ
構築はスムーズには進みませんでした。3つの大きな技術的な障害に直面しました。
1. キャッシュの罠
履歴にセッションが全く表示されませんでした。調査したところ、トラッカースクリプトに1年間のキャッシュポリシーが設定されていることが判明しました。訪問者は古いバージョンのスクリプトを使い続けてしまっていたのです。
- 解決策: トラッカースクリプトのキャッシュポリシーを5分間に設定しました。
2. 偽のCORSエラー
ブラウザがCORSエラーを報告しました。ドメインのホワイトリストの問題だと思いましたが、単純なcurlテストではサーバーは正常に動作していました。
真相は異なっていました。実際にはサーバーがクラッシュしていたのです。
Node.jsでは、ステータスコード204を使用する場合、ボディに空文字列を使用することはできません。nullを使用する必要があります。空文字列を使用したことで、CORSヘッダーが送信される前にクラッシュが発生していました。ブラウザはヘッダーを受け取れなかったため、CORSの問題だと判断したのです。
- 解決策: レスポンスボディを
''からnullに変更しました。
3. データの欠落
「今日」や「過去7日間」のフィルターで何も表示されませんでした。一部のユーザーの場所が「Unknown(不明)」と表示されました。 これは、タイムスタンプと位置情報の計算を最初のページロード時にしか行っていなかったことが原因でした。ユーザーのブラウザに古いセッションが残っている場合、サーバーは「開始」イベントを見逃してしまいます。
- 解決策: 計算を冪等(idempotent)にしました。現在、スクリプトはすべてのイベントでこれらの値を再計算します。
まとめ
• ブラウザでのCORSエラーは、必ずしも設定の問題とは限りません。サーバーのクラッシュが隠れている可能性があります。常にサーバーログを確認してください。
• curlによるPOSTテストは、ブラウザの挙動を完全にテストできるわけではありません。ブラウザはまずOPTIONSプリフライトリクエストを送信します。有効なテストにするには、これを含める必要があります。
• 204のような「コンテンツなし」のHTTPステータスにはnullを使用してください。空文字列は使用しないでください。
