簡析hotjar錄屏功能實現原理


簡析hotjar錄屏功能實現原理

眾所周知,hotjar中錄屏功能是其重要的一個賣點,看着很牛X酷炫的樣子,今天就簡單的分析一下其可能實現(這里只根據其請求加上個人理解分析,並不代表hotjar中真實實現必然如此)的原理。

1、獲取完整DOM內容

如果要實現完整的錄屏功能,在客戶端在沒有客戶允許的前提下,目前是無法做到的,所以只能考慮在服務端來實現,在服務端實現的第一步,就必然需要重現客戶端的渲染結果,此時需要完整的發送客戶端內容到服務端,在服務端進行完整的渲染。

從布瑪的效果來看,獲取DOM內容會涉及如下三個請求:

請求1 用來判斷該頁面內容在服務端是否存在
Request URL: https://in.hotjar.com/api/v1/sites/848493/pages/2338866123/content-id/34b2f50d09fbe08a4444e6691b1be779

Request Method: GET
Status Code: 200 

//響應結果  
{"exists": false}


請求2 預檢請求  沒啥說的,應該都知道干啥的
Request URL: https://in.hotjar.com/api/v1/sites/848493/url-hash/4f9e7b2f60ba35900e873ed12b1502ec/content
Request Method: OPTIONS
Status Code: 200 

請求3 發送完整DOM內容
Request URL: https://in.hotjar.com/api/v1/sites/848493/url-hash/4f9e7b2f60ba35900e873ed12b1502ec/content
Request Method: POST
Status Code: 200 

Request Payload
content: "{"docType":"<!DOCTYPE html>\n","rootId":1,"childre" .......
content_md5: "34b2f50d09fbe08a4444e6691b1be779"
page_id: 2338866123
page_url: "xxxxxxxxx.html"

//響應結果
{"page_content_id": 8784354270, "success": true}

從請求3 中可以看到,content部分其實就是對完整html的json化,這部分內容比較長,只貼出部分內容。

2、獲取鼠標移動軌跡

只是獲取完整DOM內容只是第一步,在hotjar的錄屏功能中,還有一個是獲取鼠標運動軌跡,想要繪制運動軌跡,必然要知悉鼠標在時間軸上的位置信息,所以hotjar中,必然要采集鼠標在不同時間點的位置信息,這個可以通過其websocket 請求

Request URL: wss://ws7.hotjar.com/api/v1/client/ws
Request Method: GET
Status Code: 101 Switching Protocols

在ws 請求過程中,會有mouse-move數據包的發送,其基本結構如下:

mouse_move: [{time: 106597, x: 215, y: 115}, {time: 106695, x: 181, y: 105}, {time: 106796, x: 134, y: 139},…]
page_visit_id: 14777325238
page_visit_key: "e9fa998e-5811-4d2f-81d2-bd296c7129af"

其中可以看到mouse_move 數據結構中,包含了時間軸上不斷變化的坐標值(x,y),有了基於時間軸的xy坐標,我們繪制內容就變的不那么復雜了。

3、檢測並發送DOM變化

除了鼠標運行軌跡之外,用戶在頁面上的所有行為都會被完整的記錄下來,頁面的任何變化也都被記錄了下來,如果需要在服務端完整的重新演化這種變化,那么需要把完整的變化結構發送到服務器,讓服務端進行變化回溯,hotjar是通過ws中發送mutation發送這種結構包的,當然要發送這種結構包,首先要先觀測DOM變化,這里也有一種簡單的方式(暫時不確定hotjar的實現)HTML5 DOM4級MutatioObserver方法,可以檢查頁面中的DOM是否發生變化,大家可以做一下簡單的測試:

//選擇目標觀測節點
let target = document.querySelector('目標節點選擇器');

// 創建觀察者對象
var observer = new window.MutationObserver(function(mutations) {
  mutations.forEach(function(mutation) {
    console.log(mutation);
  });    
});
 
// 觀測項配置:
var config = { attributes: true, childList: true }
 
// 開始觀測目標節點
observer.observe(target, config);

獲取到變化的DOM結構(這種變化也是時序的變化,因為任何操作都可能導致變化,變化必然是有先后順序的),然后通過ws發送到服務器,通過chrome network可以看到ws中mutation基本的包結構如下:

mouse_move: [{time: 118994, x: 404, y: 135}]
mutation: [{time: 118308,…}, {time: 118312,…}, {time: 118336, c: [{id: 7480,…}]}
page_visit_id: 14777325238
page_visit_key: "e9fa998e-5811-4d2f-81d2-bd296c7129af"

里面包含了DOM節點變化,其中包含變化節點如何變化的(通過節點的所有attribute來應用)

4、變化和軌跡回溯生成視頻

最后一切數據准備完畢,需要生成視頻了,生成視頻當然涉及很多的計算,因為要演化和回溯用戶的所有操作,我猜可能的思路是這樣的:

  1. 在服務器啟動瀏覽器 並 啟動錄屏軟件(錄屏軟件只是猜測可能有其它多種方式)
  2. 根據頁面發送的完整DOM進行初始化內容展示
  3. 按照時序合並鼠標軌跡和mutation包數據
  4. 根據時間軸自動操作改變DOM
  5. 訪次結束完成錄制

總結

hotjar中還涉及到更多的細節實現,里面很多內容也並沒有考慮,比如發送view_port report_content包等都沒什么在文章中體現出來,但這些並不影響主線分析,另外因為只是簡要分析,所以並不涉及實現細節,有興趣的歡迎留言討論。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM