最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

前端添加埋點(diǎn)四種方式和原理總結(jié)

 更新時(shí)間:2026年01月12日 09:35:51   作者:新節(jié)  
埋點(diǎn)是前端數(shù)據(jù)監(jiān)控的核心技術(shù),用于用戶行為分析、產(chǎn)品優(yōu)化、異常監(jiān)控等,這篇文章主要介紹了前端添加埋點(diǎn)四種方式和原理的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

前言

核心實(shí)現(xiàn)思路 埋點(diǎn)本質(zhì)上就是向埋點(diǎn)平臺的數(shù)據(jù)接收 URL 發(fā)送一個(gè) HTTP 請求,請求中攜帶了格式化的數(shù)據(jù)(通常是 URL 參數(shù)或 JSON)。您提供的響應(yīng)頭表明這是一個(gè) GET 請求,并且服務(wù)器配置為不緩存且允許跨域。

方法一:使用 Image Beacon(最經(jīng)典、最可靠的方法)

這是最傳統(tǒng)且兼容性最好的方式,利用圖片請求沒有跨域限制的特性。

代碼如下:

// 將屬性對象轉(zhuǎn)換為URL參數(shù)字符串
function formatParams(params) {
  return Object.keys(params)
    .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
    .join("&");
}
// 使用 Image Beacon
document.getElementById("ImageBeacon").addEventListener("click", () => {
  // 構(gòu)建埋點(diǎn)URL和參數(shù)
  const saUrl = "https://..."; // 數(shù)據(jù)接收地址
  const project = "fosun_test1"; // 您的項(xiàng)目名
  const event = "ButtonClick"; // 事件名稱,如 'PageView', 'ButtonClick'
  const distinctId = "user_123"; // 用戶ID
  const properties = {
    // 事件屬性
    $url: window.location.href,
    button_name: "提交按鈕"
  };
  const finalUrl = `${saUrl}?project=${project}&event=${event}&distinct_id=${distinctId}&${formatParams(properties)}`;

  // 創(chuàng)建Image對象發(fā)送請求
  const beacon = new Image(1, 1); // 創(chuàng)建一個(gè)1x1像素的圖片
  beacon.src = finalUrl; // 設(shè)置src即發(fā)起GET請求

  // 可選的錯(cuò)誤處理
  beacon.onerror = function () {
    console.error("Sensors beacon request failed.");
  };
  beacon.onload = function () {
    console.log("Sensors beacon request successful.");
  };
});

截圖如下:

方法二:使用 Navigator.sendBeacon(現(xiàn)代瀏覽器推薦)

這是 HTML5 專門為日志上報(bào)設(shè)計(jì)的新 API,非常適合埋點(diǎn)場景。

代碼如下:

// 使用 sendBeacon 發(fā)送數(shù)據(jù)
document.getElementById("sendBeacon").addEventListener("click", () => {
  // 構(gòu)建數(shù)據(jù)對象
  const data = {
    project: "fosun_test1",
    event: "ButtonClick",
    distinct_id: "user_123",
    properties: {
      $url: window.location.href,
      button_name: "提交按鈕"
    }
  };

  // 注意:sendBeacon 通常以 POST 方式發(fā)送字符串化的JSON
  const blob = new Blob([JSON.stringify(data)], { type: "application/x-www-form-urlencoded" });
  const success = navigator.sendBeacon("https://...", blob); // 數(shù)據(jù)接收地址
  if (success) {
    console.log("Beacon enqueued successfully!");
  } else {
    console.error("Beacon failed to queue.");
  }
});

截圖如下:

優(yōu)點(diǎn):

  • 專為日志設(shè)計(jì):即使頁面卸載也會保證發(fā)送。
  • 低優(yōu)先級:不會阻塞頁面卸載過程或與關(guān)鍵操作競爭網(wǎng)絡(luò)資源。

方法三:使用 Fetch API with keepalive(不推薦)

Fetch API 提供了 keepalive 選項(xiàng),用于在頁面卸載后繼續(xù)發(fā)送請求。這在需要確保數(shù)據(jù)上報(bào)的場景下非常有用。

// 使用 fetchKeepalive 發(fā)送數(shù)據(jù)
document.getElementById("keepalive").addEventListener("click", () => {
  const data = new URLSearchParams();
  data.append("project", "your_project_name");
  data.append("event", "ButtonClick");
  data.append("distinct_id", "user_123");
  data.append(
    "properties",
    JSON.stringify({
      $url: window.location.href,
      button_name: "提交按鈕"
    })
  );
  fetch("https://...", {
    method: "POST",
    body: data,
    keepalive: true, // 關(guān)鍵參數(shù):確保請求在頁面卸載后仍能繼續(xù)
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    }
  }).catch((error) => {
    console.error("Fetch beacon failed:", error);
  });
});

方法四:直接使用神策官方 SDK(最推薦)

實(shí)際上,您不需要手動實(shí)現(xiàn)這些。神策提供了非常完善的官方 SDK,只需簡單初始化即可。

  1. 安裝 SDK

    npm install sa-sdk-javascript
    
  2. 初始化并調(diào)用

    <script>
      // 初始化神策分析
      var sensors = window["sensorsDataAnalytic201505"];
      sensors.init({
        server_url: "https://your-sensors-data-server.com/sa", // 數(shù)據(jù)接收地址
        heatmap: {
          // 可選:點(diǎn)擊圖/觸達(dá)圖配置
          clickmap: "default",
          scroll_notice_map: "default"
        }
      });
    
      // 標(biāo)識用戶
      sensors.login("user_123");
    
      // 發(fā)送事件
      sensors.track("ButtonClick", {
        button_name: "提交按鈕"
      });
    </script>
    

這是最推薦的方式,因?yàn)楣俜?SDK 處理了所有的兼容性、批量上報(bào)、重試機(jī)制等復(fù)雜問題。

神策請求參數(shù)詳解

無論用哪種方法,最終發(fā)送給神策服務(wù)器的 URL 通常包含以下核心參數(shù):

參數(shù)含義示例
project項(xiàng)目名稱production
event事件名稱$pageview (頁面瀏覽)
distinct_id匿名/用戶 ID123456
properties事件屬性{ "$url": "https://example.com" }
time事件時(shí)間戳(可選)1631234567890

總結(jié)與選擇

方法適用場景優(yōu)點(diǎn)缺點(diǎn)
Image Beacon需要極致兼容性(如舊版 IE)兼容性最好,無跨域問題無法發(fā)送大量數(shù)據(jù)
sendBeacon現(xiàn)代瀏覽器,頁面卸載時(shí)上報(bào)專為日志設(shè)計(jì),不阻塞卸載兼容性稍差(IE 不支持)
fetch keepalive現(xiàn)代瀏覽器,需要更多控制功能強(qiáng)大,可控制請求細(xì)節(jié)兼容性比 sendBeacon 差
官方 SDK所有生產(chǎn)環(huán)境功能完整,穩(wěn)定可靠,省心需要引入 SDK

最終建議:對于生產(chǎn)環(huán)境,強(qiáng)烈推薦直接使用神策官方 SDK。它封裝了所有最佳實(shí)踐,您只需要關(guān)心業(yè)務(wù)邏輯(觸發(fā)什么事件),而不需要關(guān)心網(wǎng)絡(luò)傳輸?shù)膶?shí)現(xiàn)細(xì)節(jié)。只有在一些非常特殊的場景下,才需要考慮自己實(shí)現(xiàn)埋點(diǎn)請求。

常見問題:神策使用 Image Beacon 是怎么獲取用戶數(shù)據(jù)的?

像神策這種發(fā)送一個(gè)圖片給后端,他們是怎么通過圖片分析數(shù)據(jù)的?

神策并不是真的去“分析”圖片本身的內(nèi)容(比如圖片里的像素、顏色等),而是巧妙地利用瀏覽器請求圖片的行為來傳遞數(shù)據(jù)。

可以這樣理解:圖片的 URL(地址)不是指向一張真實(shí)的圖片,而實(shí)際上是一個(gè)精心編排的、包含了你所有埋點(diǎn)數(shù)據(jù)的“代碼字符串”

整個(gè)過程就像一個(gè)秘密通信協(xié)議:

核心原理:URL 即消息

埋點(diǎn)系統(tǒng)會動態(tài)生成一個(gè) 1x1 像素的透明 GIF 圖片的 URL,但這個(gè) URL 的路徑和參數(shù)部分被用來編碼數(shù)據(jù)。

舉個(gè)例子: 一個(gè)真實(shí)的埋點(diǎn)圖片請求 URL 可能長這樣:

https://data-sensors.com/sa.gif?project=my_web&event=pageview&user_id=123&page_url=https%3A%2F%2Fexample.com&button_name=checkout&time=1631234567890

分解這個(gè) URL:

URL 部分作用說明
https://data-sensors.com/sa.gif接收端點(diǎn)神策服務(wù)器的地址,路徑叫 sa.gif 只是為了偽裝成圖片。
?project=my_web查詢參數(shù)(數(shù)據(jù)載體)從問號 ? 開始的部分才是關(guān)鍵!這些參數(shù)就是埋點(diǎn)數(shù)據(jù)。
&event=pageview事件名稱告訴服務(wù)器用戶進(jìn)行了“頁面瀏覽”這個(gè)行為。
&user_id=123用戶標(biāo)識告訴服務(wù)器是哪個(gè)用戶做的。
&page_url=...事件屬性告訴用戶是在哪個(gè)頁面做的。
&time=...時(shí)間戳告訴服務(wù)器事件發(fā)生的確切時(shí)間。

當(dāng)瀏覽器嘗試加載這個(gè)“圖片”時(shí),會發(fā)生以下事情:

  1. 瀏覽器:認(rèn)為這是一個(gè)普通的圖片資源,向 https://data-sensors.com/sa.gif 發(fā)起一個(gè) HTTP GET 請求。
  2. 神策服務(wù)器
    • 接收到這個(gè)請求,完全忽略請求的是 .gif 這個(gè)事實(shí)。
    • 服務(wù)器端的程序(如 Nginx、Node.js、Java 等)會解析 URL 中的查詢參數(shù)(即 ? 后面的部分)。
    • 將這些參數(shù)(project=my_web, event=pageview…)解析成結(jié)構(gòu)化的 JSON 數(shù)據(jù)。
    • 將這些數(shù)據(jù)存入數(shù)據(jù)庫或大數(shù)據(jù)平臺,用于后續(xù)的分析和計(jì)算。
    • 最后,服務(wù)器返回一個(gè)極其微小的 1x1 像素的透明 GIF 圖片作為響應(yīng)內(nèi)容(就是你響應(yīng)頭里 content-type: image/gif 對應(yīng)的內(nèi)容)。
  3. 瀏覽器:接收到這個(gè)微小的圖片數(shù)據(jù),并渲染它(當(dāng)然,在頁面上你什么都看不到)。

為什么選擇用圖片(Image Beacon)?

這種技術(shù)被稱為 “Image Beacon”(圖片信標(biāo)),它被廣泛采用是因?yàn)橛兄T多優(yōu)點(diǎn):

優(yōu)點(diǎn)解釋
沒有跨域問題圖片資源不受同源策略的限制,可以從任何域名下加載。這是最大的優(yōu)勢。
兼容性極好所有瀏覽器,包括非常古老的版本,都支持圖片加載。
簡單可靠實(shí)現(xiàn)起來非常簡單,只需要?jiǎng)?chuàng)建一個(gè) Image 對象并設(shè)置 src 屬性即可。
不阻塞頁面圖片加載是異步的,不會阻塞頁面的渲染或卸載過程。
開銷極小請求的圖片只有 1x1 像素,幾乎是所有網(wǎng)絡(luò)請求中數(shù)據(jù)量最小的,對性能影響微乎其微。

與現(xiàn)代方法的對比

雖然 Image Beacon 非常經(jīng)典,但現(xiàn)在也有更現(xiàn)代的技術(shù):

技術(shù)工作原理優(yōu)點(diǎn)缺點(diǎn)
Image Beacon偽裝成圖片的 GET 請求,數(shù)據(jù)在 URL 中兼容性最好,無跨域問題URL 長度有限制,不適合傳輸大量數(shù)據(jù)
navigator.sendBeacon()HTML5 新 API,專門用于發(fā)送少量數(shù)據(jù)即使頁面關(guān)閉也會保證發(fā)送,不阻塞兼容性稍差(IE 完全不支持)
Fetch API使用 JavaScript 發(fā)起異步請求功能強(qiáng)大,可控制性強(qiáng)可能受跨域策略限制

總結(jié)

所以,神策并不是分析圖片,而是掛羊頭賣狗肉

  • 羊頭(請求頭)Content-Type: image/gif -> 讓瀏覽器以為這是個(gè)圖片。
  • 狗肉(請求體和目的)?event=xxx&user_id=xxx -> 在 URL 參數(shù)中攜帶數(shù)據(jù),服務(wù)器解析后存入數(shù)據(jù)庫。

最終,您在海量數(shù)據(jù)中看到的用戶行為分析報(bào)表、轉(zhuǎn)化漏斗、留存分析等,全都是基于解析這些 URL 參數(shù)后存入數(shù)據(jù)庫的數(shù)據(jù)計(jì)算出來的,與那張微小的透明圖片本身沒有任何關(guān)系。

案例代碼

上面的案例代碼如下:

<!DOCTYPE html>
<html>
  <head>
    <title>Markdown Renderer</title>
    <style>
      button {
        display: block;
        margin: 20px;
        font-size: 16px;
      }
    </style>
  </head>
  <body>
    <div id="result"></div>
    <button id="ImageBeacon">ImageBeacon添加埋點(diǎn)</button>
    <button id="sendBeacon">Navigator.sendBeacon添加埋點(diǎn)</button>
    <button id="keepalive">fetchKeepalive添加埋點(diǎn)</button>
    <script>
      // 將屬性對象轉(zhuǎn)換為URL參數(shù)字符串
      function formatParams(params) {
        return Object.keys(params)
          .map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
          .join("&");
      }
      // 使用 Image Beacon
      document.getElementById("ImageBeacon").addEventListener("click", () => {
        // 構(gòu)建埋點(diǎn)URL和參數(shù)
        const saUrl = "https://..."; // 數(shù)據(jù)接收地址
        const project = "fosun_test1"; // 您的項(xiàng)目名
        const event = "ButtonClick"; // 事件名稱,如 'PageView', 'ButtonClick'
        const distinctId = "user_123"; // 用戶ID
        const properties = {
          // 事件屬性
          $url: window.location.href,
          button_name: "提交按鈕"
        };
        const finalUrl = `${saUrl}?project=${project}&event=${event}&distinct_id=${distinctId}&${formatParams(properties)}`;
        // 創(chuàng)建Image對象發(fā)送請求
        const beacon = new Image(1, 1); // 創(chuàng)建一個(gè)1x1像素的圖片
        beacon.src = finalUrl; // 設(shè)置src即發(fā)起GET請求
        // 可選的錯(cuò)誤處理
        beacon.onerror = function () {
          console.error("Sensors beacon request failed.");
        };
        beacon.onload = function () {
          console.log("Sensors beacon request successful.");
        };
      });

      // 使用 sendBeacon 發(fā)送數(shù)據(jù)
      document.getElementById("sendBeacon").addEventListener("click", () => {
        // 構(gòu)建數(shù)據(jù)對象
        const data = {
          project: "fosun_test1",
          event: "ButtonClick",
          distinct_id: "user_123",
          properties: {
            $url: window.location.href,
            button_name: "提交按鈕"
          }
        };
        // 注意:sendBeacon 通常以 POST 方式發(fā)送字符串化的JSON
        const blob = new Blob([JSON.stringify(data)], { type: "application/x-www-form-urlencoded" });
        const success = navigator.sendBeacon("https://...", blob);
        if (success) {
          console.log("Beacon enqueued successfully!");
        } else {
          console.error("Beacon failed to queue.");
        }
      });

      // 使用 fetchKeepalive 發(fā)送數(shù)據(jù)
      document.getElementById("keepalive").addEventListener("click", () => {
        const data = new URLSearchParams();
        data.append("project", "your_project_name");
        data.append("event", "ButtonClick");
        data.append("distinct_id", "user_123");
        data.append(
          "properties",
          JSON.stringify({
            $url: window.location.href,
            button_name: "提交按鈕"
          })
        );
        fetch("https://...", {
          method: "POST", // 也可能是GET,取決于神策服務(wù)器的配置
          body: data,
          keepalive: true, // 關(guān)鍵參數(shù):確保請求在頁面卸載后仍能繼續(xù)
          headers: {
            "Content-Type": "application/x-www-form-urlencoded"
          }
        }).catch((error) => {
          console.error("Fetch beacon failed:", error);
        });
      });
    </script>
  </body>
</html>

總結(jié)

到此這篇關(guān)于前端添加埋點(diǎn)四種方式和原理總結(jié)的文章就介紹到這了,更多相關(guān)前端添加埋點(diǎn)方式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

灵宝市| 沅江市| 昌乐县| 张家口市| 新密市| 宝鸡市| 卢龙县| 宾阳县| 青铜峡市| 手机| 宜兴市| 汝城县| 磐石市| 礼泉县| 霞浦县| 泰宁县| 林口县| 溆浦县| 磐石市| 蓝山县| 永胜县| 仙居县| 柞水县| 扬中市| 北流市| 密云县| 临武县| 河池市| 新密市| 凤凰县| 萨嘎县| 乌海市| 丰县| 余庆县| 卢龙县| 拜城县| 全椒县| 东丽区| 松桃| 麟游县| 上饶县|