前端埋点数据收集和数据上报

原文地址

什么是埋点

学名叫时间追踪(Event Tracking), 主要针对用户行为或者业务过程进行捕获,处理和发送相关技术及实施过程.
埋点是数据领域的一个专业术语,也是互联网领域的俗称,是互联网领域的俗称

埋点是产品数据分析的基础,一般用于推荐系统的反馈、用户行为的监控和分析、新功能或者运营活动效果的统计分析等。

埋点包含两个重要概念:事件(event),属性(param)

  • 事件(event):应用中发生了什么,例如用户操作、系统事件或系统错误。以你拍一产品为例,包含以下事件:enter_page(进入页面)、leave_page(离开页面)。
  • 属性(param):为了描述用户群细分而定义的属性,例如语言偏好或地理位置。以“进入课后练习”事件为例,它包含如下事件属性:enter_from(从哪个页面来),class_id(课程id)等。
  • 属性值(value):属性的维度,即行为触发时的具体维度。例如:enter_from:home(主页)、system(系统)等。

主流方案

无痕埋点(全埋点),利用浏览器或APP自带的监听方式,对用户的浏览页面、点击等行为进行手机,一般用于粗颗粒度的数据分析,例如公司的slardar
缺点:

  • 数据噪声大,不管有用没有,数据都会被收集
  • 无法定制化埋点,无法采集到指定事件和业务属性
  • 可供DA使用的信息较少
    优点:
  • 接入简单,几乎无侵入,不需要额外的开发成本
  • 用户操作行为收集非常完整,几乎不会遗漏

代码埋点, 前端开发人员在代码中自定义监听和收集
缺点:

  • 工作量大,而且对代码侵入性大,后期维护不方便
    优点:
  • 可以精确埋点,具备明确的事件标识
  • 业务员属性非常丰富
  • 埋点触发方式可以灵活定义
  • DA使用更方便和精确

埋点SDK,SDK向外暴露上报埋点的接口,监听和收集过程开发人员无感知,例如公司的tea
缺点:NA
优点:

  • 业务开发只需要关注事件标识,业务属性等
  • 兼顾无痕埋点优点和代码埋点的优势

常见的埋点属性

通常前端是按照页面维度统计埋点的,常见的事件属性如下

属性描述
uid用户id,如果用户未登录,则返回特定标识id
url当前事件触发页面的url
eventTime触发埋点的时间戳
localTime触发埋点的用户本地时间,使用标准YYYY=MM-DD HH:mm:ss格式表示,方便后期直接使用字符串查询
device Type当前用户使用的设备类型,比如apple、三星、chrome
deviceId当前用户使用的设备id
osType系统类型入windows,macos,ios,android
osVersion系统版本
appVersion应用版本
appId当前应用id
extra自定义数据,一般是序列化的字符串,且数据结构应该保持稳定

常见埋点事件

事件上报时机描述
页面停留当前页面切换或者页面卸载时记录前一页浏览时间
pv进入页面时页面访问次数,uv只需要根据deviceId过滤
交互事件用户交互事件触发时比如点击、长按等
逻辑事件符合逻辑条件时比如登录、跳转页面等

性能数据采集方案

目前性能指标数据大部分来源于 window.performance API。

在这里插入图片描述
在这里插入图片描述

参数名描述
connectEndHTTP(TCP) 返回浏览器与服务器之间的连接建立时的时间戳。如果建立的是持久连接,则返回值等同于fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。
connectStartHTTP(TCP) 域名查询结束的时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 fetchStart一致。
domComplete当前文档解析完成,即Document.readyState 变为 'complete’且相对应的readystatechange 被触发时的时间戳
domContentLoadedEventEnd当所有需要立即执行的脚本已经被执行(不论执行顺序)时的时间戳。
domContentLoadedEventStart当解析器发送DOMContentLoaded 事件,即所有需要被执行的脚本已经被解析时的时间戳。
domInteractive当前网页DOM结构结束解析、开始加载内嵌资源时(即Document.readyState属性变为“interactive”、相应的readystatechange事件触发时)的时间戳。
domLoading当前网页DOM结构开始解析时(即Document.readyState属性变为“loading”、相应的 readystatechange事件触发时)的时间戳。
domainLookupEndDNS 域名查询完成的时间。如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
domainLookupStartDNS 域名查询开始的UNIX时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和fetchStart一致。
fetchStart浏览器准备好使用HTTP请求来获取(fetch)文档的时间戳。这个时间点会在检查任何应用缓存之前。
loadEventEnd当load事件结束,即加载事件完成时的时间戳。如果这个事件还未被发送,或者尚未完成,它的值将会是0.
loadEventStartload事件被发送时的时间戳。如果这个事件还未被发送,它的值将会是0。
navigationStart同一个浏览器上一个页面卸载(unload)结束时的时间戳。如果没有上一个页面,这个值会和fetchStart相同。
redirectEnd最后一个HTTP重定向完成时(也就是说是HTTP响应的最后一个比特直接被收到的时间)的时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0.
redirectStart第一个HTTP重定向开始时的时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0。
requestStart返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的时间戳。
responseEnd返回浏览器从服务器收到(或从本地缓存读取,或从本地资源读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的时间戳。
responseStart返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的时间戳。如果传输层在开始请求之后失败并且连接被重开,该属性将会被数制成新的请求的相对应的发起时间
secureConnectionStartHTTPS 返回浏览器与服务器开始安全链接的握手时的时间戳。如果当前网页不要求安全连接,则返回0。
unloadEventEnd和 unloadEventStart 相对应,unload事件处理完成时的时间戳。如果没有上一个页面,这个值会返回0。
unloadEventStart上一个页面unload事件抛出时的时间戳。如果没有上一个页面,这个值会返回0。

常见性能指标

指标名字描述
FP页面首次绘制时间
FCP页面首次有内容绘制的时间
FMP页面首次有效绘制时间 FMP>=FCP
TTI页面完全可交互时间
FID页面加载阶段,用户首次交互操作的延时时间
MPFID页面加载阶段,用户交互操作可能遇到的最大延时时间
LOAD页面完全加载的时间(load事件发生的时间)

FP

FP(FIrst Paint) 指标通常会反映页面的白屏时间,白屏时间会反应当前,用户等待内容时间就会越短,Web页面的网络加载性能情况,当加载性能非常良好的情况下,白屏时间就会越短,用户流失概率越低

该指标可以通过 preformance.getEntriesByType(‘paint’) 方法获取 PerformancePaintTming API 提供的打点信息,找到name为first-paint的 对象,描述的即为FP的指标数据:
在这里插入图片描述

FCP

FCP(First Contentful Paint) 为首次有内容渲染的时间点,在性能统计指标中,从用户开始访问Web页面的时间点到FCP的时间,可以视为无内容时间,一般FCP >= FP

指标可以通过 performance.getEntriesByType(‘paint’) 方法获取PerformancePaintTiming API 提供的打点信息,找到 name 为 first-contentful-paint 的对象,描述的即为 FCP 的指标数据,如下图所示:

FMP

FMP(First Meaningful Paint), 即首次绘制有意义内容的时间,当整体页面的布局和文字内容全部渲染完成后,即可认为是完成了首次有意义内容的绘制。所以FMP衡量了用户看到网页的主要内容的时间,是用户体验角度的一种重要衡量指标

前端业界现在比较认可的一个计算 FMP 的方式就是「页面在加载和渲染过程中最大布局变动之后的那个绘制时间 」。可通过 MutationObserver 监听每一次页面整体的 DOM 变化,触发 MutationObserver 的回调,在回调计算出当前 DOM 树的变动分数,分数变化最剧烈的时刻,即为 FMP 的时间点。

TTI

TTI(Time To Interactive),即从页面加载开始到页面处于完全可交互状态所花费的时间。页面处于完全可交互状态时,满足以下 3 个条件:

页面已经显示有用内容。
页面上的可见元素关联的事件响应函数已经完成注册。
事件响应函数可以在事件发生后的 50ms 内开始执行。

资源加载指标

window.performance.getEntriesByType(‘resource’)会返回当前页面加载的所有资源(js、css、img…)的各类性能指标,可用于静态资源性能数据采集。

主要类型有:script、link、img、css、xmlhttprequest、beacon、fetch、other。
PerformanceResourceTiming - Web APIs | MDN

其他指标计算方式

指标名描述计算方式
DNS查询DNS 阶段耗时domainLookupEnd - domainLookupStart
TCP连接TCP 阶段耗时connectEnd - connectStart
SSL建连SSL 连接时间connectEnd - secureConnectionStart
首字节网络请求首字节响应时间(ttfb)responseStart - requestStart

错误数据采集方案

有三种

  • 资源加载错误,通过 addEventListener(‘error’, callback, true) 在捕获阶段捕捉资源加载失败错误。
  • js 执行错误,通过 window.onerror 捕捉 js 错误。
    • 跨域的脚本会给出 “Script Error.” 提示,拿不到具体的错误信息和堆栈信息。此时需要在script标签增加crossorigin="anonymous"属性,同时资源服务器需要增加CORS相关配置,比如Access-Control-Allow-Origin: *
  • promise 错误,通过 addEventListener(‘unhandledrejection’, callback)捕捉 promise 错误,但是没有发生错误的行数,列数等信息,只能手动抛出相关错误信息。
// 在捕获阶段,捕获资源加载失败错误
Element.addEventListener('error', e => {
const target = e.targetif (target != window) {monitor.errors.push({type: target.localName,url: target.src || target.href,msg: (target.src || target.href) + ' is load error',time: Date.now()})}
})// 监听 js 错误
window.onerror = function(msg, url, row, col, error) {monitor.errors.push({type: 'javascript',row: row,col: col,msg: error && error.stack? error.stack : msg,url: url,time: Date.now()})
}
// 监听 promise 错误 缺点是获取不到行数数据
addEventListener('unhandledrejection', e => {monitor.errors.push({type: 'promise',msg: (e.reason && e.reason.msg) || e.reason || '',time: Date.now()})
})

数据上报方案

在这个场景中,需要考虑两个问题:

如果数据上报接口与业务系统使用同一域名,浏览器对请求并发量有限制,所以存在网络资源竞争的可能性。
浏览器通常在页面卸载时会忽略异步ajax请求,如果需要必须进行数据请求,一般在unload或者beforeunload事件中创建同步ajax请求,以此延迟页面卸载。从用户侧角度,就是页面跳转变慢。

Navigator.sendBeacon

优点:
在页面卸载时可靠地发送数据,不会阻塞页面关闭。
支持在后台发送数据。

缺点:
只能发送POST请求,无法获取响应结果。

在这里插入图片描述
除开ie浏览器,目前主流现代浏览器对beacon的支持率非常高。Beacon - MDN文档

Beacon 接口用来调度向 Web 服务器发送的异步非阻塞请求。

  • Beacon 请求使用 HTTP POST方法,并且不需要有响应。
  • Beacon 请求能确保在页面触发 unload 之前完成初始化。

通俗的讲就是,Beacon可将数据异步发送至服务端,且能够保证在页面卸载完成前发送请求(解决ajax页面卸载会终止请求的问题)。使用方法如下:

navigator.sendBeacon(url, data);

其中 data 参数是可选的,它的类型可以为 ArrayBufferView, Blob, DOMString 或者 FormData。如果浏览器成功地将 beacon 请求加入到待发送的队列里,这个方法将会返回 true ,否则将会返回 false

使用Beacon时需要后台需要使用post方法接收参数,考虑到跨域问题,后台还需要改造接口配置CORS。同时请求头必须满足CORS-safelisted request-header,其中content-type的类型必须为application/x-www-form-urlencoded, multipart/form-data, 或者text/plain。

type ContentType = 'application/x-www-form-urlencoded' | 'multipart/form-data' | 'text/plain';const serilizeParams = (params: object) => {return window.btoa(JSON.stringify(params))
}function sendBeacon(url: string, params: object) {const formData = new FormData()formData.append('params', serilizeParams(params))navigator.sendBeacon(url, formData)
}

Image

优点:
简单易用,兼容性好,可以跨域上报。
不会阻塞页面加载和关闭。

缺点:
只能发送GET请求,无法获取响应结果。
不支持异步操作。

sendBeacon的兼容性问题是不可避免的,不过可以充分利用大部分浏览器会在页面卸载前完成图片的加载的特性,通过在页面添加img的方式上报数据。

function sendImage(url: string, params: object) {const img = new Image()img.style.display = 'none'const removeImage = function() {img.parentNode.removeChild(img)}img.onload = removeImageimg.onerror = removeImageimg.src = `${url}?params=${serilizeParams(params)}`document.body.appendChild(img)
}

由于img图片为get请求方式,不同服务器针对uri的长度有限制,长度超过限制时会出现HTTP 414错误,所以还要注意上报频率,减少一次性上传的属性过多。

兼容方案

优先使用sendBeacon的方式,Image方式作为fallback。


function sendLog(url: string, params: object) {if(navigator.sendBeacon) {sendBeacon(url, params)} else {sendImage(url, params)}
}

实际上很多都用GIF来做埋点?
向服务器端上报数据,可以通过请求接口,请求普通文件,或者请求图片资源的方式进行。只要能上报数据,无论是请求GIF文件还是请求js文件或者是调用页面接口,服务器端其实并不关心具体的上报方式。那为什么所有系统都统一使用了请求GIF图片的方式上报数据呢?
●防止跨域
一般而言,打点域名都不是当前域名,所以所有的接口请求都会构成跨域。而跨域请求很容易出现由于配置不当被浏览器拦截并报错,这是不能接受的。但图片的src属性并不会跨域,并且同样可以发起请求。(排除接口上报)
●防止阻塞页面加载,影响用户体验
通常,创建资源节点后只有将对象注入到浏览器DOM树后,浏览器才会实际发送资源请求。反复操作DOM不仅会引发性能问题,而且载入js/css资源还会阻塞页面渲染,影响用户体验。
但是图片请求例外。构造图片打点不仅不用插入DOM,只要在js中new出Image对象就能发起请求,而且还没有阻塞问题,在没有js的浏览器环境中也能通过img标签正常打点,这是其他类型的资源请求所做不到的。(排除文件方式)
●相比PNG/JPG,GIF的体积最小
最小的BMP文件需要74个字节,PNG需要67个字节,而合法的GIF,只需要43个字节。
同样的响应,GIF可以比BMP节约41%的流量,比PNG节约35%的流量。
并且大多采用的是1*1像素的透明GIF来上报
1x1像素是最小的合法图片。而且,因为是通过图片打点,所以图片最好是透明的,这样一来不会影响页面本身展示效果,二者表示图片透明只要使用一个二进制位标记图片是透明色即可,不用存储色彩空间数据,可以节约体积。

XMLHttpRequest或Fetch API

优点:

可以发送异步请求,支持GET和POST等多种HTTP方法。
可以获取响应结果,并进行进一步处理。
缺点:

需要手动处理请求和响应的逻辑。
需要处理跨域请求的问题(如设置CORS)。

使用XMLHttpRequest或Fetch API发送异步请求来上报数据。可以选择使用GET或POST方法,并将数据作为请求体或URL参数发送。

WebSocket

优点:

实时性好,支持双向通信。
适用于实时监控和大规模数据上报。
缺点:

需要服务器端支持WebSocket协议。
较复杂且不适用于简单的埋点需求。

上报的平台

常见的前端数据埋点工具包括Google Analytics、百度统计、友盟统计等,当然也可以使用公司内部的接口或者平台进行上报

以Google Analytics为例:
Google Analytics是一款由谷歌公司开发的网站分析工具,用于跟踪和报告网站流量。它可以帮助网站所有者了解访问者的行为,包括他们是谁、他们从哪里来、他们在网站上做了什么等等。通过Google Analytics,网站所有者可以更好地了解他们的受众群体,优化网站内容和营销策略,从而提升网站的效果和用户体验。Google Analytics提供了丰富的数据分析功能,包括实时数据、用户行为分析、转化跟踪、流量来源分析等等。它是一款强大的工具,被广泛应用于各种网站和在线营销活动中。

如何使用Google Analytics

既然使用Google Analytics,首先我们肯定需要拥有一个谷歌账号,这里大家需要自行创建。 其次,需要知道Google Analytics的入口,这里是使用的两个地址:

Google Tag Manager:tagmanager.google.com/

Analytics:analytics.google.com/

Google Tag Manager
Google Tag Manager(GTM)是一种标签管理系统,由Google开发和提供。它允许网站管理员在不需要修改网站代码的情况下管理和部署各种跟踪代码、分析代码和营销标签。通过GTM,用户可以轻松地添加、更新和删除标签,而无需依赖开发人员。

GTM的主要功能包括:
大白话来说就是:该平台用来收集前端触发的埋点事件,并且可以通过自定义配置触发条件、触发事件回调来实现数据上报,这里使用它来收集数据并上报至Google Analytics

Google Analytics
顾名思义,它就是用来收集、查看、显示数据的一个网站

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/871395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度解读李彦宏的“不要卷模型,要卷应用”

深度解读李彦宏的“不要卷模型,要卷应用” —— AI技术的应用之道 引言 在2024世界人工智能大会的舞台上,李彦宏的“不要卷模型,要卷应用”言论犹如一石激起千层浪,引发了业界对AI技术发展路径的深思。本文将深入探讨这一观点&a…

Eagle 4.0 更新了哪些功能,值得购买吗?

这个全新的版本带来了一系列重磅级别的更新,包括全新的「插件系统」、「全新的 UI 风格」以及「AI 工具」等。所有这些,都是为了提供给用户更加优质的使用体验,让工作的流程更加流畅,更加高效。 我们的团队始终倾听用户的声音&am…

C语言:指针详解(5)

目录 一、sizeof()函数和strlen()函数的对比 二、数组和指针笔试题解析 三、指针运算笔试题解析 正文开始 一、sizeof()函数和strlen()函数的对比 1.sizeof()函数 在学习操作符的时候,我们了解了sizeof()函数。sizeof()函数是用来计算变量所占内存空间大小的&a…

算法笔记——LCR

一.LCR 152. 验证二叉搜索树的后序遍历序列 题目描述: 给你一个二叉搜索树的后续遍历序列,让你判断该序列是否合法。 解题思路: 根据二叉搜索树的特性,二叉树搜索的每一个结点,大于左子树,小于右子树。…

男女相貌之秘 -高直上人

描述 高直上人,一个富有才华的老师! 对于大家的学习有不可多得的帮助。 内容 目前主要的内容以面相为主,对于学习面相有比较大的帮助! 但是网络上面错综复杂,很多老旧的版本影响学习! 而这里我整理了相…

Python3.6.6 OpenCV 将视频中人物标记或者打马赛克或加图片并保存为不同格式

1、轻松识别视频人物并做出标记 需安装face_recongnition与dlib,过程有点困难,还请网上查找方法 import face_recognition import cv2 #镜像源 -i https://pypi.mirrors.ustc.edu.cn/simple # 加载视频 video_file E:\\videos\\1.mp4 video_capture …

Qt下使用OpenCV的鼠标回调函数进行圆形/矩形/多边形的绘制

文章目录 前言一、设置imshow显示窗口二、绘制圆形三、绘制矩形四、绘制多边形五、示例完整代码总结 前言 本文主要讲述了在Qt下使用OpenCV的鼠标回调在OpenCV的namedWindow和imshow函数显示出来的界面上进行一些图形的绘制,并最终将绘制好的图形显示在QLabel上。示…

UE4 解决创建布料报错:三角形退化

**【问题】**创建创建布料时报错:三角形退化 【方法】 1.要重新绑定:导入到ue4为静态网格体,勾选“移除退化”,再导出fbx,再重新绑定 2.不用重新绑定:使用排除法(费时)&#xff0c…

全栈物联网项目:结合 C/C++、Python、Node.js 和 React 开发智能温控系统(附代码示例)

1. 项目概述 本文详细介绍了一个基于STM32微控制器和AWS IoT云平台的智能温控器项目。该项目旨在实现远程温度监控和控制,具有以下主要特点: 使用STM32F103微控制器作为主控芯片,负责数据采集、处理和控制逻辑采用DHT22数字温湿度传感器,精确采集环境温湿度数据通过ESP8266 W…

Mac和VirtualBox Ubuntu共享文件夹

1、VirtualBox中点击设置->共享文件夹 2、设置共享文件夹路径和名称(重点来了:共享文件夹名称) 3、保存设置后重启虚拟机,执行下面的命令 sudo mkdir /mnt/share sudo mount -t vboxsf share /mnt/share/ 注:shar…

Leetcode-203-移除链表元素-临时变量作用域-c++

题目详见https://leetcode.cn/problems/remove-linked-list-elements/ 题解代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullpt…

你需要知道的笔记本养护的几个小知识

笔记本充电器可以长期不拔吗? 可以,但建议偶尔使用电池激发电池活性并且修正电量计精度; 当充电器接入后,笔记本会优先使用充电器进行供电而不会使用电池供电,同时充电器也会为缺电的电池补充电量。 现在笔记本电脑普遍…

大数据开发中的数据驱动决策:关键问题与实践指南

目录 决策前的准备工作1. 我已经掌握了哪些信息?2. 我们已经做出决定了吗?3. 我们需要哪些额外信息以及何时需要? 决策过程中的关键问题1. 我们需要做这个决定吗?2. 错误地做出这个决定的代价是什么? 决策后的反思1. 我…

《Python零基础入门》——关于PyCharm使用技巧及python基本概念

从本次文章开始,我们将学习一门新的编程语言——Python。作为最热门的编程语言,Python相对比较清晰、简单。 python主要的编译工具就是pycharm,关于pycharm的安装及python配置环境,大家可自行参考网络上的教程,本文不…

# Redis 入门到精通(一)数据类型(4)

Redis 入门到精通(一)数据类型(4) 一、redis 数据类型–sorted_set实现时效性任务管理 1、sorted_set 类型数据操作的注意事项 score 保存的数据存储空间是64位,如果是整数范围是-9007199254740992~9007199254740992…

QT creator与VS2019 QT加载模块方法

QT creator与VS2019加载模块方法 QT creator,pro文件添加 VS2019 QT

酷克数据亮相第13届PostgreSQL中国技术大会,获数据库杰出贡献奖

7 月 12 日,第 13 届 PostgreSQL 中国技术大会在杭州盛大开幕。本次大会以“聚焦云端创新,汇聚智慧共享”为主题,邀请了国内外 PG 领域众多行业大咖、学术精英及技术专家,共同探讨数据库领域的发展趋势、技术创新和实践经验。酷克…

[Vulnhub] Tr0ll3 aircrack-ng+lynx

信息收集 IP AddressOpening Ports192.168.101.147TCP:22 $ ssh start192.168.101.147 用户:Start startTr0ll3:~$ find / -type f -perm 0777 2>/tmp/1 startTr0ll3:~$ cat /var/log/.dist-manage/wytshadow.cap | nc 192.168.101.128 10035 WIFI握手包 aircrack-ng 破…

记一次 .NET某上位视觉程序 离奇崩溃分析

一:背景 1. 讲故事 前段时间有位朋友找到我,说他们有一个崩溃的dump让我帮忙看下怎么回事,确实有太多的人在网上找各种故障分析最后联系到了我,还好我一直都是免费分析,不收取任何费用,造福社区。 话不多…

[译] Rust标准库有些特殊,让我们改它

本篇是对 RustConf 2023中的The standard library is special. Let’s change that.这一视频的翻译与整理, 过程中为符合中文惯用表达有适当删改, 版权归原作者所有. 今天我将讨论Rust的标准库,更具体地说,是关于标准库有何特殊之处,以及为什么我们应该改变这一点。首先声明一下…