一、基本原理●1、利用xpath的唯一性绑定点元素,添加事件发送数据点●2、后台管理系统构建可视化选择点元素功能并保存配置●3、前端根据页面的URL获取dot配置并初始化(通过xpath绑定事件)。使用传统ajax请求发送数据的缺点是容易阻塞请求,对用户不友好,弊端很大。当用户关闭页面时,请求将被截断,即终止发送,不适用于记录浏览时间。axios.post(网址,数据);//以axios为例2.对于动态图片,我们可以通过在beforeunload事件处理函数中创建一个图片元素,并设置其src属性来保证数据的发送,从而实现延迟卸载,因为大多数浏览器的处理函数都会延迟卸载,以确保图像已加载,因此可以在卸载事件中发送数据。constsendLog=(url,data)=>{让img=document.createElement('img');常量参数=[];Object.keys(data).forEach((key)=>{params.push(`${key}=${encodeURIComponent(data[key])}`);});img.onload=()=>img=null;img.src=`${url}?${params.join('&')}`;};3.sendBeacon为了解决上述问题,有一个navigator.sendBeacon方法。使用这种方式发送请求可以保证数据的有效传递,不会阻塞页面的卸载或加载,而且编码比上面的方式更简单。exportconstsendBeacon=(url,analyticsData)=>{constapiUrl=config.apiRoot+urlletdata=getParams(analyticsData)//兼容不支持sendBeacon的浏览器if(!navigator.sendBeacon){constclient=newXMLHttpRequest()//第三个参数表示同步发送client.open('POST',apiUrl,false)client.setRequestHeader('Content-Type','application/x-www-form-urlencoded')client.send(data)return}constformData=newFormData()Object.keys(analyticsData).forEach((key)=>{letvalue=analyticsData[key]if(typeofvalue!=='string'){//formData只能追加字符串或者Blobvalue=JSON.stringify(value)}formData.append(key,value)})navigator.sendBeacon(apiUrl,formData)}最后我们使用动态图片的方式,因为阿里云提供的阿里云-collection-通过WebTracking收集日志来应对大量的数据采集,不会对网站本身的服务器造成压力。3.构建SDK使用webpack构建项目,打包单个sdk的js文件包,将sdk导入到前端(这部分就不细说了,有兴趣的可以搜索webpack的相关资料)写一个带有webpack的简单JSSDK●可视化选择xpath-reference插件SDK主要功能:暴力暴露初始化方法和打点方法(为了支持手动打点)添加选择xpath的功能,暴露给后台管理系统使用链接URL读取打点配置列表初始化绑定打点事件函数进入页面即可recordadotrecordBrowsingtimeSDK与父iframe的通信函数(为了向后台管理系统传递数据)记录游览时长示例://统计时长constviewTime=(data)=>{letstartTime=newDate().getTime()//浏览开始时间letendTime=null//浏览结束时间//页面卸载触发window.addEventListener('unload',()=>{endTime=newDate().getTime()letparams={viewTime:(endTime-startTime)/1000,eventType:'view',accessId:ACCESS_ID}params=Object.assign(params,data)sendLog(params)},false)}//选择xpath跨域跨页communicationimportPostmatefrom'postmate'importInspectorfrom'../plugins/inspect'//选择xpath节点插件letchildIframe=nullconstmyInspect=newInspector()constgetXpathForm=function(options){myInspect.setOptions(options,(data)=>{letparams={xpath:data,route:window.QWK_ANALYSIS_SDK_OPTIONS.路线||''}childIframe.emit('send-data-event',params)})}exportdefault{//与父iframe通信initMessage(){//在开发模式下启用节点选择调试if(process.env.BUILD_ENV==='dev'){document.querySelector('#selected').onclick=()=>{myInspect.setOptions({deactivate:true},(data)=>{console.log(data)})}}consthandshake=newPostmate.Model({//iframeparentgetsxpathgetXpath:(options)=>{getXpathForm(options)},//删除选择deactivate:()=>{myInspect.deactivate()}})//当父级<->子级握手完成时,可能会向父级握手发送事件.then((child)=>{childIframe=child})}}//导出SDK//main.js入口文件import{init}from'./lib/init'importactionfrom'./lib/action'importselectXpathfrom'./lib/select-xpath'//import{documentReady}from'./plugins/common'//初始化选择xpath的跨域通信selectXpath.initMessage()//documentReady(()=>{////初始化////init().then(res=>res)//})//导出SDK模块export{init,action}4.后台管理系统搭建xpath可视化选择第一步:第三方网站引入SDK到在sdk中写一个选择xpath的函数,暴露出来调用后台管理系统●可视化选择xpath-reference插件Step2:搭建管理系统搭建iframe加载网站,如图:这里需要调用SDK中选择网站xpath函数的方法,必须和加载的iframe中的网站通信因为是iframe加载的第三方网站,会存在跨域问题,所以我们需要一个插件来实现这个功能postmateGitHublink
