前端埋点实现方案

news2024/11/18 15:37:15

前言

领导今天又来活了😣,要记录每个页面的停留时间,以及页面的操作,是由哪个页面跳转过来的,给每个页面生成GUID上报给服务端,并且需要携带设备型号和设备唯一标识🙄

名称解释

UV(Unique visitor)

是指通过互联网访问、浏览这个网页的自然人。访问您网站的一台电脑客户端为一个访客。00:00-24:00内相同的客户端只被计算一次。一天内同个访客多次访问仅计算一个UV。

IP(Internet Protocol)

独立IP是指访问过某站点的IP总数,以用户的IP地址作为统计依据。00:00-24:00内相同IP地址之被计算一次。

UV与IP区别

如:你和你的家人用各自的账号在同一台电脑上登录新浪微博,则IP数+1,UV数+2。由于使用的是同一台电脑,所以IP不变,但使用的不同账号,所以UV+2

PV(Page View)

即页面浏览量或点击量,用户每1次对网站中的每个网页访问均被记录1个PV。用户对同一页面的多次访问,访问量累计,用以衡量网站用户访问的网页数量。

VV(Visit View)

用以统计所有访客1天内访问网站的次数。当访客完成所有浏览并最终关掉该网站的所有页面时便完成了一次访问,同一访客1天内可能有多次访问行为,访问次数累计。

PV与VV区别

如:你今天10点钟打开了百度,访问了它的三个页面;11点钟又打开了百度,访问了它的两个页面,则PV数+5,VV数+2.PV是指页面的浏览次数,VV是指你访问网站的次数。

埋点分类

代码埋点

通过代码的方式在页面中嵌入逻辑🎨,比如捕获一个点击事件,在这个点击事件之前加入代码埋点⛑,上报给后台🥐。国内已经有很多成型的服务商了如友盟,百度统计等🌯,都提供了比较成型的方案🎨,并可以在后台管理系统中查看比较详细的数据分析🧵,但是肯定会有领导想要把这些事情掌握在自己的手中,我们就只能通过自身开发来实现代码埋点🍞。
在这里插入图片描述

优点:

控制精准,可以非常精确地选择什么时候发送数据。 传递多样化自定义属性、自定义事件,传递比较丰富的数据到服务端。

缺点:

埋点代价比较大,每一个控件的埋点都需要添加相应的代码,不仅工作量大,必须是技术人员才能完成。
更新的代价比较大,每一次更新埋点方案,都必须改代码。

可视化埋点

个人理解的可视化埋点应该是肯定需要第三方的服务商支持🍜,不会有做专门业务的公司去做可视化埋点的解决方案。可视化埋点开发人员除集成采集可视化SDK 外👜,不需要额外去写埋点代码🍠,而是由业务人员或运营人员通过访问分析平台的圈选功能🤔,来“圈”出需要对用户行为进行捕捉的控件🎪,并给出事件命名🚘。圈选完毕后,这些配置会同步到各个用户的终端上😮,由采集SDK按照圈选的配置自动进行用户行为数据的采集和发送🚇。
在这里插入图片描述

优点:

埋点代价小,更新代价小 埋点只需业务同学接入,开发只需对接可视化SDK

缺点:

无法做到自定义获取数据 可视化埋点覆盖的功能有限 仅支持客户端行为

无痕埋点

无痕埋点又叫全埋点🥪,网上又很多文章写的都是无痕埋点是将所有事件的操作全部上报😀,但是我们在实现的过程中肯定是不会监听那么多的事件吧😋,但是好像也有第三方服务商sdk集成了所有事件😏。

我的个人理解无痕埋点是针对某一个单一事件,在全局实现监听达到上报,而不是全部事件上报才叫无痕埋点🥙。只要有某个事件在全局实现监听,针对这个事件的埋点方式就称为无痕埋点🌯

优点:

由于采集的是全量数据,所以产品迭代过程中是不需要关注埋点逻辑的,也不会出现漏埋、误埋等现象。
无埋点方式因为收集的是全量数据,可以大大减少运营和产品的试错成本 如果集成sdk之后无需埋点,方便快捷

缺点:

缺点与可视化埋点相同,未解决个性化自定义获取数据的问题,缺乏数据获取的灵活性; 数据量过大,如果不使用第三方服务商,针对自身的服务器是个考验

实现方案步骤(uni-app,其他项目逻辑相同)

两方面上报:

1.事件上报(目前只有点击事件埋点),2.停留时间上报

事件上报:通过给元素绑定自定义指令的方式实现(减少对原有代码的侵入)🍜,将信息存储在缓存池中定时上报,上报之后清空之前的上报信息🥠。
停留时间上报:需要重新封装路由,创建路由拦截在跳转之前记录来源,以及上一个页面的停留时间,当拦截器捕获成功之后🌯,如果发现停留时间大于xx秒进行上报🥙。

优点:清晰合理,比较适合新项目。

缺点:针对老项目需要与产品和运营对接埋点方案绑定自定义事件🤪,如果是老项目需要对uni.navigateTo,uni.redirectTo,uni.reLaunch,uni.switchTab
进行二次封装。

问:为什么何将信息存储,而不是实时上报? 答:考虑到服务器的压力,采用了定时上报的方式。

问:为什么监听停留时长大于XX秒才进行上报?
答:1.服务器的压力问题。2考虑到用户可能做一些没意义的操作,所以停留时长大于XX秒才属于有效页面。

实现方法

事件埋点上报

  • 在common文件夹下创建自定义指令文件,在main.js中引用该文件。
import Vue from "vue";
// 自定义埋点指令
Vue.directive("buried", {
  bind: (el, binding) => {
    if (binding.value) {
      //这里参数是根据自己业务可以自己定义
      let params = {
        currentUrl: binding.value.currentUrl,
        triggerType: binding.value.triggerType,
        title: binding.value.title,
        frontTriggerType: binding.value.triggerType,
        behavior: binding.value.behavior,
      };
      //如果是浏览类型,直接保存,目前只考虑点击类型
      if (binding.value.triggerType == "browse") {
        console.log("browse", params);
        //调用后台接口保存数据
      } else if (binding.value.triggerType == "click") {
        //如果是click类型,监听click事件
        el.addEventListener(
          "click",
          () => {
            // 将操作和内容存储在缓存中定时上报
            let buriedArray = uni.getStorageSync('buriedArray') //获取埋点集合
            buriedArray.push(params)  // 将埋点集合存入缓存中
            uni.setStorageSync('buriedArray', buriedArray)
          },
          false
        );
      }
    }
  },
});

复制代码
在app.vue中的onLaunch生命周期中创建定时任务与缓存池,在onHide生命周期中销毁定时任务

let timeInterval = null
onLaunch(){
  uni.setStorageSync('buriedArray', [])
		// 定时上报埋点数据
		timeInterval = setInterval(() => {
			if (uni.getStorageSync('buriedArray').length > 0) {
				// 上报逻辑,根据需求自行完善
				upLoadBuriedInfo(uni.getStorageSync('buriedArray'))
				// 上报成功之后清空埋点数据重新上报
				uni.setStorageSync('buriedArray', [])
			}
		}, time)
}
onHide: function () {
		timeInterval && clearInterval(timeInterval)
}

停留时间上报

  • 首先读取page.json中的文件获取path和title(原文链接),先在项目根目录创建一个router文件夹🍞,在vue.config.js里面加入如下代码,这样每次打包之后router文件夹下的index.js中就会生成一个 title和path的对应表。😚
const path = require('path')
const fs = require('fs')

const fromFile = path.join(__filename, '../pages.json')
const toFile = path.join(__filename, '../router/index.js')
const buffPrefix = Buffer.from('export default ')

const fileData = fs.readFileSync(fromFile)

// 转成可读的js, 正则删除注释, 不然JSON.parse会报错
const fileObj = JSON.parse(fileData.toString().replace(/\/\/.*/g, ''))

// 遍历,只取路径和标题,其他的不要,已减小文件体积
const routes = fileObj.pages.map(e => {
	return {
		title: e.style ? e.style.navigationBarTitleText ? e.style.navigationBarTitleText : e.name : '未知',
		path: '/'+e.path,
	}
})
fs.writeFileSync(toFile, buffPrefix + Buffer.from(JSON.stringify(routes)))

module.exports = {
	configureWebpack: {
		plugins: []
	}
}
  • 在common中创建routeGuards.js 监听路由拦截,进行上报,在main.js中引用该文件
import Vue from 'vue';
import v5 from 'uuid/v5';
import UniRouteGuard from '@/js_sdk/pocky-route-gurads/lib';
import router from '@/router'
Vue.use(UniRouteGuard);

const guard = new UniRouteGuard();

let startTime = Date.now();
guard.beforeEach((to, from, next) => {
	let currentTime = Date.now();
	if (from.url && from.url == '/pages/first/index') {
		next()
		return
	}
	console.log(router)
	if (to.url) {
		if (to.url.indexOf('?') > -1) {
			to.url = to.url.substr(0, to.url.indexOf('?'))
		}
	}
	let fromName = router.find(item => item.path == from.url) ? router.find(item => item.path == from.url).title : '未知'
	let toName = router.find(item => item.path == to.url) ? router.find(item => item.path == to.url).title : '未知'
  const stayTime=  parseInt((currentTime - startTime) / 1000)
	const MY_NAMESPACE = '1b671a64-40d5-491e-99b0-da01ff1f3341';

	console.log(`由${fromName}跳转到${toName}并在${fromName}中停留了${stayTime}秒钟`);
	let params = {
		fromUrl: from.url, //来源地址
		toUrl: to.url, // 目的地址
		fromName: fromName, // 来源名称
		toName: toName, // 目的名称
		stayTime: stayTime, // 停留时长
		guid: v5(from.url, MY_NAMESPACE), //页面uuid
		appUuid: uni.getStorageSync('appUuid') ? uni.getStorageSync('appUuid') : '', // app唯一标识
		model: uni.getStorageSync("model")? uni.getStorageSync('model') : '', // 手机型号
	}
	console.log(params)
  if(stayTime>10){
   // 上报逻辑
    console.log('停留的时间大于10秒钟了,可以进行上报')
  }
  startTime = Date.now();
	next();
});

因为uni-app
没有提供自身的路由拦截插件🥠,所以需要我们手动去封装🚘。这种方案针对新项目比较合适,但是针对老项目路由跳转的逻辑都已经通过原生的方式写完了😣,我们在进行封装的话修改的点太多了🤔,所以在网上找到了这个插件不用修改跳转api并且可以获取到上一个页面的路由(全局路由守卫),原文介绍的是通过npm的方式进行安装,我采用的是hbuilderX导入的方式(有需要的同学可以自行查找)🤙。

使用方法

  • 事件埋点:将需要埋点的元素绑定改指令v-buried绑定参数
<!-- 
triggerType: 事件类型
title: 页面标题
currentUrl: 页面路由
behavior: 操作行为
-->
<view v-buried="{
triggerType:'click',
title:'我的',
currentUrl: currentPath,
behavior:'点击我的收藏按钮'}">
</view>
  • 页面跳转

需要在page.json中进行修改如果使用的是自定义导航条或者没有使用导航条需要进行命名
需要将页面中跳转路径修改成绝对路径否则路由会匹配不到
在这里插入图片描述

在这里插入图片描述

uni-app集成友盟统计

  • 首先在友盟上创建一个应用获取其对应的appkey

在这里插入图片描述

  • 在uni-app的App模块配置中勾选友盟统计并填写对应的key(渠道id随意填写就可以)
    在这里插入图片描述

  • 这样实际上就在uni-app中集成了友盟统计,如果想看到详细的上报数据可以在友盟后台进行查看(注:必须打包之后或者采用自定义基座的方式才能够进行上报,上报结果可能第二天才会生效,具体上报规则可以查看友盟官网解释)。
    在这里插入图片描述

这样最基本的集成就完成了。

那我们如何埋入我们的自定义事件呢,比如我将一个燃气罩加入了购物车把他当成一个事件,并且能在友盟后台查看到我加入商品的属性以及加入空气炸锅或者加入电饼铛的一些数量对比

  • 1.在友盟后台注册相应的自定义事件 (我的应用->设置->添加事件)
    在这里插入图片描述

  • 2.创建事件完毕之后在代码中进行上报的代码的编写(步骤一和步骤二谁先谁后都可以)

// https://www.html5plus.org/doc/zh_cn/statistic.html 文档链接
// 第一个参数: 在友盟后台注册的事件id,第二个参数:业务数据
plus.statistic.eventTrig("purchase", {"type":"book","quantity":"3"});
复制代码
  • 上报可能会有延迟,发行过一段时间之后就可以在友盟后台查看到相关数据。

在这里插入图片描述

  • 点击查看按钮可以看到更详细的数据,以及上报的业务数据对比
    在这里插入图片描述

uni-app 自带统计

  • 无需集成其他相关sdk只需在manifest.json中勾选uni统计配置即可注:必须打包之后才能够进行上报,上报结果可能第二天才会生效,具体上报规则可以查看uni-app官网解释)

在这里插入图片描述

  • 查看上报后台
    在这里插入图片描述

  • uni统计也支持自定义埋点事件的上报

// 注意如果第一个参数是title第二个参数必须是字符串
uni.report("upload",{
					title: '上报数据',
					content: '上报内容'
				})
  • 可在事件和转化模块中进行查看
    在这里插入图片描述

在测试uni-app自带的统计中也遇到了一些问题,如果有朋友能够解决的话也可以帮助顶顶帖,我在进行完善问题贴。

总结

针对埋点的方案,自己也是不太熟悉,没有实战经验,找了很多途径,文中可能会有不对的地方,希望小伙伴们可以多多指点。一起加油!🤪

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

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

相关文章

蓝牙运动耳机排行榜,目前排名最好的运动耳机推荐

对于运动人士来说&#xff0c;运动过程中佩戴着耳机听歌&#xff0c;既能让运动变得更加激情有动力&#xff0c;同时还能释放压力&#xff0c;放松心情。在选择运动耳机方面的要求也高&#xff0c;运动耳机不仅需要佩戴稳固舒适&#xff0c;它的防水性能也不能差&#xff0c;当…

Java并发常见面试题(一)

进程和线程 进程 进程是程序的一次执行过程&#xff0c;是系统运行程序的基本单位&#xff0c;因此进程是动态的。系统运行一个程序即是一个进程从创建、运行到消亡的过程。 在Java中&#xff0c;当我们启动main函数其实就是启动了一个JVM进程&#xff0c;而main函数所在的线…

封装自己的 jquery 框架

说到jquery&#xff0c;那就给大家先简单的介绍一下什么是jquery jquery是JavaScript函数的一种封装。jQuery封装了JavaScript常用的功能代码&#xff08;函数&#xff09;&#xff0c;提供一种简便的JavaScript设计模式&#xff0c;优化HTML文档操作、事件处理、动画设计和Aja…

机器人运动学【2】

目录1.刚体状态的表达2.顺向运动学及DH表3.逆向运动学1.刚体状态的表达 我们前面已经学习了刚体移动和转动的表达&#xff0c;那么怎么将两者在数学上结合呢&#xff1f;这里我们开始构造如下矩阵&#xff0c;记作: 下面我们来看一下只有移动情况下的刚体的描述&#xff1a; …

使用canal解决Mysql和Redis数据同步(TCP)

使用canal解决Mysql和Redis数据同步(TCP) 工作原理分析 我们在面试的时候常常听面试官问这么一个问题&#xff1a;你们的Mysql和Redis怎么做数据同步的&#xff0c;根据不同的业务场景又很多方案&#xff0c;你可能会说先写库再删缓存&#xff0c;或者延迟双删或其他方案。今…

springboot集成flowable简单实例入门

此案例是demo。功能有创建流程、完成审批、生成流程图。适合有java基础的人员看。 第一步.画流程图 resources资源包下&#xff0c;新建processes包&#xff0c;新建一个文件&#xff0c;我命名他apply-rest.bpmmn20.xml。bpmn20.xml后缀文件是流程图配置文件。idea的右下角的…

ImageMol

ai圈也是卷的狠啊~~ 又发现一个全球首个分子图像自监督学习框架来也 分子是维持物质化学稳定性的最小单位。对分子的研究&#xff0c;是药学、材料学、生物学、化学等众多科学领域的基础性问题。 分子的表征学习&#xff08;Molecular Representation Learning&#xff09;是…

实践 | 大型基金管理公司数据脱敏体系建设

金融行业数据脱敏安全管理要求高、数据类型复杂、脱敏数据规模庞大。作为业内领先&#xff0c;且支持信创环境的数据安全产品&#xff0c;美创数据脱敏系统在金融行业应用广泛&#xff0c;可满足各类复杂环境下的数据脱敏需求&#xff1a; 台州银行—分布式大数据平台下的及时脱…

SQL Server数据库理论篇(进行时......)

SQL Server数据库理论篇 一. 数据库的关系分类 1.1.0 关系型数据库和非关系数据库区别&#xff1f; 结论&#xff1a;两种数据库的本质在于存储数据的形式不同 1.关系型数据库概念 关系型数据库最大的特征就是表&#xff0c;我们将对象的属性映射为表的一个个列名&#xff…

(九)centos7案例实战——redis一主二从三哨兵高可用服务搭建

前言 本节内容是使用centos服务器搭建一套高可用的redis服务&#xff0c;采用的是一主二从三哨兵的模式。 需要注意的是搭建集群的过程中&#xff0c;我们要保证集群服务器之间可以相互访问&#xff0c;并且redis所需要访问的端口是开放的。我们从redis的下载&#xff0c;源码…

ffmpeg 安装教程

官网&#xff1a;Download FFmpeg window 转&#xff1a;ffmpeg安装教程_moon son的博客-CSDN博客_ffmpeg安装 然后解压&#xff0c;配置全局变量环境。点击“系统属性->高级系统设置->环境变量->系统变量”&#xff0c;选择“Path”条目&#xff0c;点击“编辑->…

将项目部署到Linux系统上

目的是让我们的项目在linux上也能运行起来 有两种部署方式&#xff0c;手工部署或者是通过shell脚本自动部署 手工部署 准备工作&#xff1a;使用ifconfig指令查出服务器的ip地址&#xff1a;192.168.58.130 1.在本地Idea中开发一个springboot项目&#xff0c;并且打包成ja…

以太网模块的传输距离怎么看

光模块的关键标准组织主要有两个&#xff1a;IEEE和MSA。其中GBASE开头的标准主要是IEEE802.3提出与定义的。要弄清光模块的传输距离&#xff0c;首先让我们要弄清楚它的命名是怎样的。 100G光模块的命名规则&#xff1a; 400G光模块的命名规则&#xff1a; 其中100G和400G光模…

SpringBoot整合Mybatis方式1:使用XML方式整合Mybatis

SpringBoot整合Mybatis简介SpringBoot整合Mybatis方式1&#xff1a;使用XML方式整合Mybatis1.用idea创建一个添加mybatis需要的相关依赖的工程。2.准备数据库和表3.创建表映射类4.创建mapper文件4.1 创建UsersMapper.xml文件&#xff0c;并添加sql语句4.2 创建mapper对应的代理…

Docker的Cgroup资源限制

Docker通过Cgroup来控制容器使用的资源配额&#xff0c;包括 CPU、内存、磁盘三大方面&#xff0c;基本覆盖了常见的资源配颡和使用量控制。 Cgoup 是CotrolGroups 的缩写&#xff0c;是Linux 内核提供的一种可以限制、记录、隔高进程组所使用的物理资源&#xff08;如CPU、内存…

基于jsp的学生培训管理系统

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

【教学类-18-01】20221123《蒙德里安红黄蓝格子画》(大班)

效果展示&#xff1a; 单页效果 多页效果 预设效果 背景需求&#xff1a; 2022年11月23日&#xff0c;作为艺术特色幼儿园&#xff0c;蒙德里安风格装饰在我们幼儿园的环境中。 蒙德里安是几何抽象画派的先驱&#xff0c;以几何图形为绘画的基本元素&#xff0c;与德士堡等创…

MyBatis-Plus 和swagger

MyBatis-Plus 1.1MyBatis Plus 简介 mybatisplus 官网&#xff1a; https://baomidou.com/ MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c; 为简化开发、提高效率而生。 1.2主要特性&a…

【项目管理】Java使用pdfbox调用打印机打印PDF文件

【项目管理】Java使用pdfbox调用打印机打印PDF文件1.项目前言2.项目实现3.关键代码4.效果演示5.问题处理5.1 安装对应字体5.2 修改对应代码系统&#xff1a;Win10 Java&#xff1a;1.8.0_333 IDEA&#xff1a;2020.3.4 Gitee&#xff1a;https://gitee.com/lijinjiang01/Printe…

如何使用轮播图实现水平内容自动切换

通过轮播图实现一个水平内容自动切换 效果展示 前置准备 三张背景图片 具体步骤 添加一个轮播图组件 添加一个图片 添加一个标题 添加数据表 添加事件 添加触发器 绑定数据 步骤拆解 添加一个轮播图组件 1.1 拖拽 轮播图 到 编辑区 1.2 调整 轮播图 样式 添加一个图片 …