使用 Web Beacon API 記錄活動

已發表: 2022-03-10
快速總結 ↬ Beacon API 是一種輕量級且高效的方式,可將信息從網頁記錄回服務器。 了解如何使用它以及它與傳統 Ajax 技術的不同之處。

Beacon API 是一種基於 JavaScript 的 Web API,用於將少量數據從瀏覽器發送到 Web 服務器,而無需等待響應。 在本文中,我們將看看它有什麼用處,它與XMLHTTPRequest ('Ajax') 等熟悉的技術有何不同,以及如何開始使用它。

如果您已經知道為什麼要使用 Beacon,請隨時直接跳到入門部分。

信標 API 有什麼用?

Beacon API 用於在不等待響應的情況下向服務器發送少量數據。 最後一部分很關鍵,也是 Beacon 如此有用的關鍵——我們的代碼甚至無法看到響應,即使服務器發送了響應。 信標專門用於發送數據然後忘記它。 我們不期望得到回應,也沒有得到回應。

把它想像成度假時寄回家的明信片。 你在上面放了少量的數據(有點“希望你在這裡”和“天氣真好”),把它放在郵箱裡,你不期望得到回應。 沒有人寄回明信片說“是的,我真希望我真的在那裡,非常感謝!”

對於現代網站和應用程序,有許多用例非常巧妙地屬於這種發送後忘記的模式。

跳躍後更多! 繼續往下看↓

跟踪統計和分析數據

大多數人想到的第一個用例是分析。 像谷歌分析這樣的大型解決方案可能會很好地概述頁面訪問等內容,但如果我們想要更多定制的東西怎麼辦? 我們可以編寫一些 JavaScript 來跟踪頁面中發生的事情(可能是用戶如何與組件交互,他們滾動到多遠,或者在他們遵循 CTA 之前已經顯示了哪些文章)但是我們需要發送該數據當用戶離開頁面時發送給服務器。 Beacon 非常適合這一點,因為我們只是記錄數據而不需要響應。

我們沒有理由不能涵蓋 Google Analytics 經常處理的那種日常任務,報告用戶本身以及他們的設備和瀏覽器的功能。 如果用戶有登錄會話,您甚至可以將這些統計信息與已知個人聯繫起來。 無論您收集什麼數據,您都可以使用 Beacon 將其發送回服務器。

調試和記錄

此行為的另一個有用應用程序是記錄來自您的 JavaScript 代碼的信息。 想像一下,您的頁面上有一個複雜的交互式組件,它完美地適用於您的所有測試,但偶爾會在生產中失敗。 您知道它失敗了,但是您看不到錯誤以開始調試它。 如果您可以檢測到代碼本身的故障,則可以收集診斷信息並使用 Beacon 將其全部發回以進行日誌記錄。

事實上,任何日誌記錄任務都可以使用 Beacon 有效地執行,例如在遊戲中創建保存點、收集有關功能使用的信息或記錄多變量測試的結果。 如果這是您希望服務器知道的瀏覽器中發生的事情,那麼 Beacon 很可能是一個競爭者。

我們不能這樣做嗎?

我知道你在想什麼。 這些都不是新的,是嗎? 十多年來,我們一直能夠使用XMLHTTPRequest從瀏覽器與服務器進行通信。 最近,我們還有 Fetch API,它使用更現代的基於 Promise 的接口做很多相同的事情。 鑑於此,我們為什麼需要 Beacon API?

這裡的關鍵是,因為我們沒有得到響應,瀏覽器可以將請求排隊並發送,而不會阻塞任何其他代碼的執行。 就瀏覽器而言,我們的代碼是否仍在運行,或者腳本執行到哪裡都沒有關係,因為沒有什麼可以返回,它可以只是後台發送 HTTP 請求,直到方便發送。

這可能意味著等到 CPU 負載降低,或者網絡空閒,或者如果可以的話,甚至直接發送它。 重要的是瀏覽器將信標排隊並立即返回控制權。 信標發送時它不會阻止任何事情。

要理解為什麼這很重要,我們需要看看這些請求是如何以及何時從我們的代碼發出的。 以我們的分析日誌記錄腳本為例。 我們的代碼可能會計時用戶在頁面上花費的時間,因此在可能的最後時刻將數據發送回服務器變得至關重要。 當用戶離開頁面時,我們希望停止計時並將數據發送回主頁。

通常,您會使用unloadbeforeunload事件來執行日誌記錄。 當用戶執行諸如跟隨頁面上的鏈接導航離開之類的操作時會觸發這些。 這裡的問題是在unload事件之一上運行的代碼可能會阻塞執行並延遲頁面的卸載。 如果頁面的卸載延遲,那麼加載下一頁也會延遲,因此體驗感覺非常緩慢。

請記住 HTTP 請求的速度有多慢。 如果您正在考慮性能,通常您嘗試減少的主要因素之一是額外的 HTTP 請求,因為進入網絡並獲得響應可能非常慢。 您要做的最後一件事就是在鏈接的激活和下一頁請求的開始之間放慢速度。

Beacon 通過在不阻塞的情況下對請求進行排隊,立即將控制權返回給您的腳本來解決這個問題。 然後瀏覽器負責在後台發送該請求而不會阻塞。 這讓一切變得更快,讓用戶更快樂,讓我們都保住工作。

入門

所以我們了解了 Beacon 是什麼,以及我們為什麼會使用它,所以讓我們開始編寫一些代碼。 基礎再簡單不過了:

 let result = navigator.sendBeacon(url, data);

結果是布爾值, true瀏覽器接受並排隊請求,則返回false ,如果這樣做有問題,則返回 false。

使用navigator.sendBeacon()

navigator.sendBeacon有兩個參數。 第一個是發出請求的 URL。 該請求作為 HTTP POST 執行,發送第二個參數中提供的任何數據。

數據參數可以是多種格式之一,如果這些格式都直接取自 Fetch API。 這可以是BlobBufferSourceFormDataURLSearchParams — 基本上是使用 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事件,但 Mac 上的 Safari 似乎用安全警告阻止了請求,所以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 等替代方案快得多。

如果您想了解有關 Beacon API 的更多信息,以下站點值得一看。

  • “W3C 信標規範”,W3C 候選推薦
  • “MDN 信標文檔”,MDN 網絡文檔,Mozilla
  • “瀏覽器支持信息”,caniuse.com