埋点,它的学名是事件追踪(Event Tracking),主要是针对特定用户行为或业务过程进行捕获、处理和发送的相关技术及实施过程。埋点是数据领域的一个专业术语,也是互联网领域的一个俗称。
埋点是产品数据分析的基础,一般用于推荐系统的反馈、用户行为的监控和分析、新功能或者运营活动效果的统计分析等。
埋点包含两个重要概念:事件(event),属性(param)
无痕埋点(全埋点),利用浏览器或APP自带的监听方式,对用户的浏览页面、点击等行为进行收集,一般用于粗颗粒度的数据分析,例如公司的slardar
数据噪声大,不管有用没有,数据都会被收集
无法定制化埋点,无法采集到指定事件和业务属性
可供DA使用的信息较少
接入简单,几乎无侵入,不需要额外的开发成本
用户操作行为收集非常完整,几乎不会遗漏
优点:
缺点:
代码埋点,前端开发人员在代码中自定义监听和收集
工作量大,而且对代码侵入性很大,后期维护也不是很方便
可以精确埋点,具备明确的事件标识
业务属性非常丰富
埋点触发方式可以灵活定义
DA使用更方便和精确
优点:
缺点:
埋点sdk,sdk向外暴露上报埋点的接口,监听和收集过程开发人员无感知。例如公司的tea
暂时想不到
业务开发只需关注事件标识、业务属性等
兼顾无痕埋点优点和代码埋点的优势
优点:
缺点:
通常前端是按照页面维度统计埋点的,常见的事件属性如下:
属性 | 描述 |
---|---|
uid | 用户id,若用户未登陆,则返回特定标识id |
url | 当前事件触发页面的url |
eventTime | 触发埋点的时间戳 |
localTime | 触发埋点时的用户本地时间,使用标准YYYY-MM-DD HH:mm:ss格式表示,方便后期直接使用字符串查询 |
deviceType | 当前用户使用的设备类型,比如apple、三星、chrome等 |
deviceId | 当前用户使用的设备id |
osType | 当前用户使用的系统类型,比如windows、macos、ios、android等 |
osVersion | 当前用户使用的系统版本 |
appVersion | 当前应用版本 |
appId | 当前应用id |
extra | 自定义数据,一般是序列化的字符串,且数据结构应保持稳定 |
事件 | 上报时机 | 描述 |
---|---|---|
页面停留 | 当前页面切换或者页面卸载时 | 记录前一页浏览时间 |
pv | 进入页面时 | 页面访问次数,uv只需要根据deviceId过滤 |
交互事件 | 用户交互事件触发时 | 比如点击、长按等 |
逻辑事件 | 符合逻辑条件时 | 比如登陆、跳转页面等 |
目前性能指标数据大部分来源于 window.performance API。
参数名 | 描述 |
---|---|
connectEnd | HTTP(TCP) 返回浏览器与服务器之间的连接建立时的时间戳。如果建立的是持久连接,则返回值等同于fetchStart属性的值。连接建立指的是所有握手和认证过程全部结束。 |
connectStart | HTTP(TCP) 域名查询结束的时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 fetchStart一致。 |
domComplete | 当前文档解析完成,即Document.readyState 变为 'complete'且相对应的readystatechange 被触发时的时间戳 |
domContentLoadedEventEnd | 当所有需要立即执行的脚本已经被执行(不论执行顺序)时的时间戳。 |
domContentLoadedEventStart | 当解析器发送DOMContentLoaded 事件,即所有需要被执行的脚本已经被解析时的时间戳。 |
domInteractive | 当前网页DOM结构结束解析、开始加载内嵌资源时(即Document.readyState属性变为“interactive”、相应的readystatechange事件触发时)的时间戳。 |
domLoading | 当前网页DOM结构开始解析时(即Document.readyState属性变为“loading”、相应的 readystatechange事件触发时)的时间戳。 |
domainLookupEnd | DNS 域名查询完成的时间。如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等 |
domainLookupStart | DNS 域名查询开始的UNIX时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和fetchStart一致。 |
fetchStart | 浏览器准备好使用HTTP请求来获取(fetch)文档的时间戳。这个时间点会在检查任何应用缓存之前。 |
loadEventEnd | 当load事件结束,即加载事件完成时的时间戳。如果这个事件还未被发送,或者尚未完成,它的值将会是0. |
loadEventStart | load事件被发送时的时间戳。如果这个事件还未被发送,它的值将会是0。 |
navigationStart | 同一个浏览器上一个页面卸载(unload)结束时的时间戳。如果没有上一个页面,这个值会和fetchStart相同。 |
redirectEnd | 最后一个HTTP重定向完成时(也就是说是HTTP响应的最后一个比特直接被收到的时间)的时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0. |
redirectStart | 第一个HTTP重定向开始时的时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回0。 |
requestStart | 返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的时间戳。 |
responseEnd | 返回浏览器从服务器收到(或从本地缓存读取,或从本地资源读取)最后一个字节时(如果在此之前HTTP连接已经关闭,则返回关闭时)的时间戳。 |
responseStart | 返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的时间戳。如果传输层在开始请求之后失败并且连接被重开,该属性将会被数制成新的请求的相对应的发起时间 |
secureConnectionStart | HTTPS 返回浏览器与服务器开始安全链接的握手时的时间戳。如果当前网页不要求安全连接,则返回0。 |
unloadEventEnd | 和 unloadEventStart 相对应,unload事件处理完成时的时间戳。如果没有上一个页面,这个值会返回0。 |
unloadEventStart | 上一个页面unload事件抛出时的时间戳。如果没有上一个页面,这个值会返回0。 |
指标名 | 描述 |
---|---|
FP | 页面首次绘制时间 |
FCP | 页面首次有内容绘制的时间 |
FMP | 页面首次有效绘制时间,FMP >= FCP |
TTI | 页面完全可交互时间 |
FID | 页面加载阶段,用户首次交互操作的延时时间 |
MPFID | 页面加载阶段,用户交互操作可能遇到的最大延时时间 |
LOAD | 页面完全加载的时间(load 事件发生的时间) |
FP (First Paint)指标通常会反映页面的白屏时间,而白屏时间会反映当前 Web 页面的网络加载性能情况,当加载性能非常良好的情况下,白屏的时间就会越短,用户等待内容的时间就会越短,流失的概率就会降低。
该指标可以通过 performance.getEntriesByType('paint')
方法获取 PerformancePaintTiming API
提供的打点信息,找到 name 为 first-paint 的对象,描述的即为 FP 的指标数据,如下图所示:
FCP (First Contentful Paint) 为首次有内容渲染的时间点,在性能统计指标中,从用户开始访问 Web 页面的时间点到 FCP 的时间点这段时间可以被视为无内容时间,一般 FCP >= FP。
该指标可以通过 performance.getEntriesByType('paint')
方法获取 PerformancePaintTiming API 提供的打点信息,找到 name 为 first-contentful-paint 的对象,描述的即为 FCP 的指标数据,如下图所示:
FMP(First Meaningful Paint),即首次绘制有意义内容的时间,当整体页面的布局和文字内容全部渲染完成后,即可认为是完成了首次有意义内容的绘制。所以 FMP 衡量了用户看到网页的主要内容的时间,是用户体验角度的一种重要的衡量指标。
前端业界现在比较认可的一个计算 FMP 的方式就是「页面在加载和渲染过程中最大布局变动之后的那个绘制时间 」。可通过 MutationObserver 监听每一次页面整体的 DOM 变化,触发 MutationObserver 的回调,在回调计算出当前 DOM 树的变动分数,分数变化最剧烈的时刻,即为 FMP 的时间点。
TTI(Time To Interactive),即从页面加载开始到页面处于完全可交互状态所花费的时间。页面处于完全可交互状态时,满足以下 3 个条件:
window.performance.getEntriesByType('resource')
会返回当前页面加载的所有资源(js、css、img...)的各类性能指标,可用于静态资源性能数据采集。
主要类型有:script、link、img、css、xmlhttprequest、beacon、fetch、other。PerformanceResourceTiming - Web APIs | MDN
参数名 | 描述 |
---|---|
connectEnd | 一个 DOMHighResTimeStamp,表示浏览器完成建立与服务器的连接以检索资源之后的时间。 |
connectStart | 一个 DOMHighResTimeStamp,表示浏览器开始建立与服务器的连接以检索资源之前的时间。 |
decodedBodySize | 一个 number,表示在删除任何应用的内容编码之后,从消息主体的请求(HTTP 或缓存)中接收到的大小(以八位字节为单位)。 |
domainLookupEnd | 一个 DOMHighResTimeStamp,表示浏览器完成资源的域名查找之后的时间。 |
domainLookupStart | 一个 DOMHighResTimeStamp,表示在浏览器立即开始资源的域名查找之前的时间 |
duration | 返回一个 timestamp,即 responseEnd 和 startTime 属性的差值。 |
encodedBodySize | 一个 number,表示在删除任何应用的内容编码之前,从有效内容主体的请求(HTTP 或缓存)中接收到的大小(以八位字节为单位)。 |
entryType | 返回 "resource"。 |
fetchStart | 一个 DOMHighResTimeStamp,表示浏览器即将开始获取资源之前的时间。 |
initiatorType | 一个 string,代表启动性能条目的资源的类型 |
name | 返回资源 URL。 |
nextHopProtocol | 一个 string,代表用于获取资源的网络协议,由 ALPN 协议 ID(RFC7301) 定义。 |
redirectEnd | 一个 DOMHighResTimeStamp,表示收到上一次重定向响应的发送最后一个字节时的时间。 |
redirectStart | 一个 DOMHighResTimeStamp 代表启动重定向的请求开始之前的时间。 |
requestStart | 一个 DOMHighResTimeStamp,表示浏览器开始向服务器请求资源之前的时间。 |
responseEnd | 一个 DOMHighResTimeStamp,表示在浏览器接收到资源的最后一个字节之后或在传输连接关闭之前(以先到者为准)的时间。 |
responseStart | 一个 DOMHighResTimeStamp,表示浏览器从服务器接收到响应的第一个字节后的时间。 |
secureConnectionStart | 一个 DOMHighResTimeStamp,表示浏览器即将开始握手过程以保护当前连接之前的时间。 |
serverTiming | 一个 PerformanceServerTiming 数组,包含服务器计时指标的 PerformanceServerTiming 条目。 |
startTime | 返回一个 timestamp,表示资源获取开始的时间。该值等效于 fetchStart。 |
transferSize | 一个 number 代表所获取资源的大小(以八位字节为单位)。该大小包括响应标头字段以及响应有效内容主体。 |
workerStart | 一个 DOMHighResTimeStamp, 如果服务 Worker 线程已经在运行,则返回在分派 FetchEvent 之前的时间戳,如果尚未运行,则返回在启动 Service Worker 线程之前的时间戳。如果服务 Worker 未拦截该资源,则该属性将始终返回 0。 |
指标名 | 描述 | 计算方式 |
---|---|---|
DNS查询 | DNS 阶段耗时 | domainLookupEnd - domainLookupStart |
TCP连接 | TCP 阶段耗时 | connectEnd - connectStart |
SSL建连 | SSL 连接时间 | connectEnd - secureConnectionStart |
首字节网络请求 | 首字节响应时间(ttfb) | responseStart - requestStart |
内容传输 | 内容传输,Response阶段耗时 | responseEnd - responseStart |
DOM解析 | Dom解析时间 | domInteractive - responseEnd |
资源加载 | 资源加载 | loadEventStart - domContentLoadedEventEnd |
首字节 | 首字节 | responseStart - fetchStart |
DOM Ready | dom ready | domContentLoadedEventEnd - fetchStart |
redirect时间 | 重定向时间 | redirectEnd - redirectStart |
DOM render | dom渲染耗时 | domComplete - domLoading |
load | 页面加载耗时 | loadEventEnd - navigationStart |
unload | 页面卸载耗时 | unloadEventEnd - unloadEventStart |
请求耗时 | 请求耗时 | responseEnd - requestStart |
白屏时间 | 白屏时间 | domLoading - navigationStart |
目前所能捕捉的错误有三种:
资源加载错误,通过 addEventListener('error', callback, true)
在捕获阶段捕捉资源加载失败错误。
js 执行错误,通过 window.onerror
捕捉 js 错误。
跨域的脚本会给出 "Script Error." 提示,拿不到具体的错误信息和堆栈信息。此时需要在script标签增加crossorigin="anonymous"
属性,同时资源服务器需要增加CORS相关配置,比如Access-Control-Allow-Origin: *
promise 错误,通过 addEventListener('unhandledrejection', callback)
捕捉 promise 错误,但是没有发生错误的行数,列数等信息,只能手动抛出相关错误信息。
// 在捕获阶段,捕获资源加载失败错误
addEventListener('error', e => {
const target = e.target
if (target != window) {
monitor.errors.push({
type: target.localName,
url: target.src || target.href,
msg: (target.src || target.href) + ' is load error',
time: Date.now()
})
}
}, true)
// 监听 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()
})
})
复制代码
在这个场景中,需要考虑两个问题:
可以看到,除开ie浏览器,目前主流现代浏览器对beacon的支持率非常高。Beacon - MDN文档
Beacon 接口用来调度向 Web 服务器发送的异步非阻塞请求。
POST
方法,并且不需要有响应。通俗的讲就是,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)
}
复制代码
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 = removeImage
img.onerror = removeImage
img.src = `${url}?params=${serilizeParams(params)}`
document.body.appendChild(img)
}
复制代码
由于img图片为get请求方式,不同服务器针对uri的长度有限制,长度超过限制时会出现HTTP 414错误,所以还要注意上报频率,减少一次性上传的属性过多。
HTTP 1.1 defines Status Code 414 Request-URI Too Long for the cases where a server-defined limit is reached. You can see further details on RFC 2616. For the case of client-defined limits, there is no sense on the server returning something, because the server won't receive the request at all.
优先使用sendBeacon的方式,Image方式作为fallback。
function sendLog(url: string, params: object) {
if(navigator.sendBeacon) {
sendBeacon(url, params)
} else {
sendImage(url, params)
}
}
复制代码
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/W_P3IMqvh9EZHz-OdU6Fmw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。