document英 [ˈdɒkjumənt , ˈdɒkjument]文件;公文;文献;
requirements 英 [rɪˈkwaɪəmənts] 必要条件;必备的条件
access英 [ˈækses] 访问,存取(计算机文件);
product 英 [ˈprɒdʌkt] 产品;制品;
designer英 [dɪˈzaɪnə(r)]设计者;构思者
在实际的业务问题中,难免会遇到这样的问题:分析时缺少关键的数据指标,或数据指标的维度和属性满足不了分析需求,这个时候该怎么办呢?这时我们就要通过数据埋点获取我们想要的数据内容。
埋点是数据采集的专用术语,在数据驱动型业务中,如营销策略、产品迭代、业务分析、用户画像等,都依赖于数据提供决策支持,希望通过数据来捕捉特定的用户行为,如按钮点击量、阅读时长等统计信息。因此,数据埋点可以简单理解为:针对特定业务场景进行数据采集和上报的技术方案。
现在公司通常都会有数据产品经理或业务线数据分析师,结合版本迭代过程进行埋点规划。如果是代码埋点,还需要开发完成相应的埋点代码。
为监测网站上/app上用户的行为,是需要在网页/app中加上一些代码的,当用户触发相应行为时,进行数据上报,也就是代码埋点。
利用可视化交互手段,数据产品/数据分析师可以通过可视化界面(管理后台连接设备) 配置事件,可视化埋点仍需要先配置相关事件,再采集。
无埋点也被叫做全埋点,是指开发人员集成采集 SDK 后,SDK 便直接开始捕捉和监测用户在应用里的所有行为,并全部上报,不需要开发人员添加额外代码。数据分析师/数据产品 通过管理后台的圈选功能来选出自己关注的用户行为,并给出事件命名。之后就可以结合时间属性、用户属性、事件进行分析了。所以无埋点并不是真的不用埋点了。
无埋点和可视化埋点均不需要开发支持,仅数据业务人员进行设置即可。但两者数据上报埋点设置存在加大的差异:无埋点是无差别采集所有用户数据,可视化埋点是根据配置的要采集数据信息进行数据收集,因而无埋点上报的数据量远大于可视化埋点
在进行可视化埋点和无埋点是可以借助三方平台方案进行实现,如神策、友盟、腾讯移动分析、Talkingdata,GrowingIO等。如果对数据安全比较重视,业务又相对复杂,公司则通常是使用代码埋点方式采集数据,并搭建相应的数据产品实现其数据应用或是分析的诉求。
在埋点的技术方案中,首先要重视的,是用户唯一标识的建设。如果做不到对用户的唯一识别,那么基础的UV统计,都将是错误的。因此,在数据埋点方案中,有两个信息是一定要记录的,即设备ID+用户ID。设备ID代表用户使用哪个设备,如安卓的ANDROID_ID/IMEI,IOS中的IDFA/UDID,浏览器的Cookie,小程序的OpenID等。用户ID,代表用户在产品中所注册的账号,通常是手机号,也可以是邮箱等其他格式。当这两个信息能够获得时,不论是用户更换设备,或者是同一台设备不同账号登录,我们都能够根据这两个ID,来识别出谁在对设备做操作。
在Web开发过程中,Web端数据采集主要通过三种方式实现:服务器日志、URL解析及JS回传。
服务器日志:指Web服务器软件,例如Httpd、Nginx、Tomcat等自带的日志,例如Nginx的access.log日志等;
URL解析:指访问服务器时,将URL信息及携带的参数进行解析后,上传服务器,例如在进行数据搜索时http://www.meiduo.site?search=iphone
,我们可以获得本次用户搜索的内容search为“iphone”;
JS回传:指在Web页面上添加的各类统计插件,通过在页面嵌入自定义的Javascript代码来获取用户的访问行为(比如鼠标悬停的位置,点击的事件等),然后通过Ajax请求到后台记录日志。
这些数据的获取需要前端开发人员和后端开发人员配合,通过代码的形式采集到对应数据内容,还用一些特定数据需要单独在前端页面进行采集,页面浏览量,页面点击量等
流程规范会分成五个步骤,即规划评审、技术开发、埋点验证、发布上线、监测评估。
数据埋点的方案一旦确定,返工和排查问题的成本都很高,但数据埋点之后的分析工作,又涉及到了PD(product designer)、BI(Business Intelligence)、算法、数据等多个角色。因此非常有必要,将需求内容和数据口径统一,所有人在一套标准下,将需求定义出来,明确我们的分析的场景和目标,随后业务侧再介入,进行埋点方案的设计和开发。
通常情况下,我们需要记录用户在使用产品过程中的操作行为,通过4W1H模型可以比较好的保障信息是完备的。4W1H包括:
Who(谁)设备ID、用户ID、手机号、微信识别码等;
When(在什么时间)记录日志的时间戳、日志上报的时间戳
Where(在什么位置)IP地址,GPS地址在哪;
How(以什么方式)操作系统、设备型号、网络环境、APP版本、当前页面等信息;
What (做了什么事情)如果是搜索行为,则记录关联词;如果是内容点击,则记录内容ID、内容类型、列表位置;如果是交易动作,记录交易的商品ID、类型、数量;如果是支付过程,记录付款的方式与付款金额。
我们统计时,按照上述约定,统计用户在某个时间和地点中,看到了哪些信息,并完成了怎样的动作。上下游的相关人员,在使用这份数据时,产生的歧义或者是分歧会小很多。
当需求确定后,我们就可以开始开发动作了,这里基本上是对研发研发进行约束。埋点的开发,简单讲,是分成行为埋点(用户浏览什么内容、浏览时间)和事件(视频点击次数、视频下载次数)埋点两个大类,每一类根据端的不同进行相应的开发。
埋点的验证很关键,如果上线后才发现问题,那么历史数据是无法追溯的。
验证有两种方式,一种是实时的功能验证,一种是离线的日志验证。
实时功能验证,指功能开发好后,在灰度环境上测试相应的埋点功能是否正常,比如点击相应的业务模块,日志是否会正确的打印出来。通常而言,我们需要验证如下三个类型的问题:
1、记录正确:APP发生相应的动作,检查日志是否打印正确,如:打开页面(行为埋点)、点击按钮(事件埋点)时,是否日志会记录;
2、位置正确:查看SPM、SCM码与平台申请的是否一致;
3、内容正确:设备ID、用户ID等必须记录的内容是否正确,行为、事件记录内容是否与页面实际发生的一致。
离线的日志验证,我们需要把日志写到测试环境中,查看数据上报的过程是否正确,以及对上报后的数据进行统计,侧面验证记录的准确性,如统计基本的PV、UV,行为、事件的发生数量。
很多时候,数据是需要多方验证的,存在一定的上下游信息不同步问题,比如对某个默认值的定义有歧义,日志统计会有效的发现这类问题。
应用的发布上线通常会有不同的周期,例如移动端会有统一的发版时间,而网页版只需要根据自己的节奏走,因此数据开始统计的时间是不同的。最后,应用应当对所有已发布的埋点数据,有统一的管理方法。
大多数时候,数据埋点的技术方案,只需要设计一次,但数据准确性的验证,却需要随着产品的生命周期持续下去,对于埋点收集的数据进行持续监测,评估数据质量如何,发现问题后提出优化方案,比如,是否在设计上改进,或者是否是工程上的 bug。确定方案的责任人来优化方案内容,在下一轮迭代中推进实施。
通过埋点方案的学习,我们知道整个埋点实施的过程,在规划评审阶段,数据分析人员需要进行埋点数据设计,在进行设计过程中会遇到两大问题:
为了解决以上问题,分析人员需要编写一份数据需求文档--DRD(Data Requirements Document),通过这份规范的文档,我们便能够地与研发工程师进行沟通。
以短视频业务为例
需求:分析视频的受欢迎程度
从视频显示内容中我们能直观获取到的字段属性数据为:
点赞量:1.8w
评论量:748
转发量:85
这些数据对应了不同的事件(用户行为)内容,我们在设计数据需求文档时要添加上这些字段属性
id | 事件(用户行为) | 数量 | ...... |
---|---|---|---|
1 | likes (点赞) | 1.8w | |
2 | comment (评论) | 748 | |
3 | forward (转发) | 85 | |
4 | ...... | ...... |
单纯的从这些事件中,我们并不能有效的分析出视频的受欢迎程度。我们只是大概的从数据里知道点赞很高,这并不能反应视频受欢迎,有可能是用户误操作,也有可能是刷赞程序没有观看视频直接请求的点赞接口。
这时我们为了保证数据的有效性,就需要通过一些指标来真正的反应出我们视频的受欢迎程度,如点赞率(点赞人数/实际观看人数),转发率(转发量/实际观看人数)。
在计算的数据中我们就缺失一个关键的时间观看人数这个条数据,那我们就需要在数据需求文档中增加上这一条数据内容,同时要求开发人员增加统计实际观看人数的代码。
id | 事件(用户行为) | 数量 | ...... |
---|---|---|---|
1 | likes (点赞) | 1.8w | |
2 | comment (评论) | 748 | |
3 | forward (转发) | 85 | |
4 | count(观看人数) | 2w | |
...... | ...... | ...... |
在 受欢迎程度 的这需求中,我们还可以衍生出很多子需求,如:
哪些地区的用户喜欢看我的视频?
哪些年龄段的用户喜欢看我的视频?
要满足这些需求,我们就需要在原来的字段属性基础上再增加用户的年龄信息,用户所在位置信息等等
通过观察分析这样一组相关联的数据,我们可以对我们的用户群体进行精准定位,拍摄出用户喜欢的视频内容。
我们除了要根据需求选择的一组关联数据字段属性外,我们还有要对数据进行持续追踪,这就需要再增加一个时间维度的数据,比如通过观察半年的视频情况,发现在某个时间段的视频观看量有所下滑,那我们就可以定位到这一时间段的视频,分析这一时间内的视频为什么会出现下滑。
通过我们对数据字段属性的不断丰富 ,我们能够得到更加完整想起的用户画像。
由此我们也可以看出,数据分析的本质就是通过观察一组或多组关联数据连续变化的情况,分析出数据变化的原因和可能性
以上的字段属性选取过程是凭经验选择埋点数据 ,以需求划分字段属性,这对于分析人员有以下要求
作为一个小白,在没有行业经验的的加持我们该如何去进行字段属性的选取呢?
答案是4W1H规范
WHO(什么人),When(在什么时间),Where(在什么地点),How(以什么方式),What(干了什么事情)
我们可以将所有事件按照对应的信息进行字段属性提取,然后然后根据需求将字段属性进行聚类划分,如前面提到的点赞、转发、评论这三个属性都是与视频受欢迎程度相关的,那我们就可以将它们放在一起。同时我们也可以将共用的字段属性部分进行抽取作为公共属性,如:Who(什么人),这就是前面提到用户唯一标识,用来确认用户身份,这是我们在进行需求分析时都会用到的字段数属性,我们就可以将该字段单独拿出作为公共属性交给某一个开发人员统一维护,这样我们就不必每次需求分析时都找开发去获取该字段属性
根据4W1H规范我们可以清晰的看到用户的行为路径,方便了我们进行数据字段属性的选取,做到了:
前面我们知道了如何选取数据字段属性,那选取后的字段属性该交给前端还是后端开发人员进行埋点呢,这是我们需要遵循的原则就是:数据只能从前端获取的前端进行埋点,其它数据建议全部后端埋点
什么是只能前端获取的数据呢?比如用户在一个页面停留的时间,用户观看视频的时长,用户观看视频的次数等等,后端将视频数据返回前端了,那用户到底对这个视频看了多长时间及观看次数,只能是前端通过控制手机上的播放器插件才能获取到这个数据内容,而后端是无法获取这个数据内容。
除了这些只能是前端获取的数据外,其它数据都建议后端埋点。
在前端进行数据埋点存在如下缺陷:
1、数据实时性差
我们开发的手机端APP在进行数据采集时,如果频繁往后端发送请求,就会造成手机资源(内存,CPU)被严重消耗,影响手机性能。这时为了避免手机资源被过度消耗,前端APP一遍采用的策略是将数据统一收集后定时发送到后端,比如用户观看了10个视频,不在是每个视频观看时都发送数据,而是将用户观看的10个视频数据统一收集之后再在规定的时间点发送到后端,这样原来需要发送10个请求现在只需要发送1次。但是这样做的就会造成我们获取的数据是滞后的,同时还可能会因为前端代码的原因造成统一收集后每个视频观看的时间戳是一样的,影响我们分析结果的准确性。
不考虑性能,用户使用卡顿,体验差;注重性能,获取到数据可能会存在误差。鱼和熊掌要看自己公司的选择。
2、无法确认what完成情况
以订单支付为例,如果我们在前端进行支付数据获取,用户点击了支付按钮就算用户完成了支付,这样统计的数据是错误的。整个支付流程是在后端完成的,只有后端代码执行完成够才能知道支付是成功了还是失败了。前端的按钮点击事件是无法确认该事件是否执行成功的,所以我们需要后端去统计这个事件执行的结果
3、代码改动依赖于版本更新
前端APP在添加了埋点代码后是需要用户更新到自己的手机上,如果这时候用户不更新自己的APP,那我们是无法采集到对应的用户数据的;还有就是APP应用的上架更新也是需要进行相关审核,这个审核周期是不可控的。但是对于后端来说,添加完埋点代码后,只需要将自己公司内部的后端服务重启一下就可以实现服务更新,去执行新代码采集对应的用户数据。
综合以上几点,我们在选择埋点位置时尽量选择后端埋点。
数据分析人员在编写数据需求文档时,就需要根据以上两点进行编写。通过4W1H进行字段属性选择,尽量在后端进行埋点。除了这些之外,我们还需要描述清楚事件内容也就是用户具体的操作行为是怎样的,选取的数据字段属性的类型是什么等等。
接下来我们将以前面完成的爱读书为例,编写对应的需求文档,完成埋点代码。
我们以其中的一个事件(用户行为)为例,当用户点击进入详情页时我们进行相关数据统计
当用户进入详情页页后,对应的表示该用户阅读了该图书,我们就需要记录用户的阅读量
我们先定义出我们的事件(用户行为)内容
事件id | 事件英文名称 | 时间显示名 | 事件定义描述 |
---|---|---|---|
1 | bookClick | 图书详情点击 | 1.pc端在点击页面上的元素(按钮等)的时候触发 2.阅读次数:点击元素的次数 3.触发用户数:点击元素的用户 4.触发的内容:点击的图书名称 5.触发路径位置:从哪个页面触发 |
...... |
根据事件(用户行为)我们按照规范选出我们的字段内容
Who--用户标识信息,这里我们没有用户登录,那我们就以设备id作为标识
When--用户点击时间戳,有程序获取当前时间
Where--通过用户的IP地址确定其位置
How--获取用户设备的系统信息
What--用户的点击详情页
在这些属性字段中,我们可以吧用户标识,时间戳,用户IP地址,设备信息这些字段属性对于每个事件来说都会用到,我们可以设计为公共属性
公共属性
字段名称 | 类型 | 说明 | 上线版本 | 上线时间 | 备注 |
---|---|---|---|---|---|
identification | 字符串 | 用户标识 | V1.0 | 2021-01-01 | |
time | 日期 | 事件触发时间 | V1.0 | 2021-01-01 | 自动生成 |
ip | 字符串 | IP | V1.0 | 2021-01-01 | |
equipment | 字符串 | 设备信息 | V1.0 | 2021-01-01 |
对于what部分就是我们用户的操作事件,在这部分我们通过对事件定义的描述信息中我们还需要指定的字段属性有阅读次数,图书名,从哪里进入的
属性变量名 | 事件属性显示名 | 属性值类型 | 属性定义 | 分析说明 | 埋点形式 |
---|---|---|---|---|---|
entrance | 入口 | 字符串 | 点立详情的上一步页面,pc端是页面地址,app端是文字形式 | 后端 | |
bookname | 图书名 | 字符串 | 点击时的图书书名 | 后端 | |
read | 阅读量 | 字符串 | 点击时阅读量+1 | 后端 |
最终我们会得到一份完整的数据需求文档
开发人员需要根据数据文档中的内容进行字段的收集保存,根据前面方案中提到的数据埋点形式,可以将数据存储到日志中,在原有的代码基础上,我们需要额外增加一段日志写入的代码
@route("/detail") def detail(env): # 获取前端传递数据 data = env['requests']['query_str'] header = env['requests']['header'] # 创建链接 conn = connect(host='localhost', port=3306, database='booksite', user='root', password='mysql', charset='utf8') # 创建游标 cursor = conn.cursor() # 执行sql语句 按照指定条件查询 sql = "select * from bookinfo where %s;"%data cursor.execute(sql) # 获取数据 元组 ((),()) stock_data = cursor.fetchone() data_dict = { "id":stock_data[0], "name":stock_data[1], "auth":stock_data[2], "img_url":stock_data[3], "read":stock_data[5], "comment":stock_data[6], "score":stock_data[8], "content":stock_data[7], "synopsis":stock_data[9] } # 将阅读量更新后写入数据库 read = stock_data[5] + 1 sql = 'update bookinfo set bread=%d where id=%d;'%(read,stock_data[0]) cursor.execute(sql) conn.commit() # 将埋点数据写入日志 logger.info({ 'bookClick':{ # 事件名称 "identification":header['User-Agent'].split(' ')[-1], # 获取设备号 "ip":header['client_addr'], # 用户设备ip "equipment":header['User-Agent'],#用户系统信息 "entrance":header['Referer'], # 用户跳转路径 "bookname":stock_data[1], # 书名 "read":read, # 阅读量 } }) json_str = json.dumps(data_dict, ensure_ascii=False) return json_strCopy
查看日志信息
后续我们还可以增加评论事件统计用户评论信息和评论量,还有用户打分事件,这些事件我们可以放在一起分析出图书的受欢迎程度是怎样的
在日志中的数据可以通过搭建ETL(数据仓库)进行抽取、准换、加载。数据分析人员可以从ETL中获取数据进行相关数据分析工作,这部分内容我们会在后续的课程中陆续进行学习。