作者:vivo 互联网大数据团队- Zhao Wei、Tian Fengbiao、Li Xiong
本文从提高用户行为剖析功率角度动身,详细介绍了H5埋点计划规划,埋点数据收集流程,供给可借鉴的用户行为数据收集计划;且完好呈现了针对页面剖析,留存剖析的数仓模型规划计划,在数仓模型规划过程中遇见的痛点难点问题也相应的给出了处理思路及事例代码;在数据展现模块,供给了剖析方针数据展现的逻辑流程及UI事例,旨在协助有需求的同学全方位的了解用户行为数据全链路剖析流程。
一、背景
针对用户行为数据进行收集有个专业术语叫埋点,在h5页面上做的埋点统称为H5埋点。H5页面因其灵活性,快捷的交互和丰富的功用,以及在移动设备上支撑多媒体等特色现在被广泛运用于网页app开发。
现阶段H5埋点的自由度较高,职业数据产品在同类高频的事务场景上规划的时间花费较多,埋点开发、埋点测试等事项耗时,且需重复劳动;同样的埋点数据剖析层面-根底剖析方针,留存方针,页面剖析等需求需多次开发模型,糟蹋名贵的人力资源。
H5通用剖析模型旨在经过规范化埋点规划计划,开发规划一套通用度高,扩展便利,需求响应敏捷的模型,削减职业数据产品和开发在相似需求上的人力投入,提高数据剖析功率。
二、剖析模型概述
2.1 术语解释
2.2 模型概述
针对事务开展的不同阶段,会有相应的数据剖析需求。如图(1),在事务初期,用户的拜访,留存状况等是阶段性剖析重点,事务产品运营能够根据剖析数据适时的调整页面布局,运营策略等;运用开展中后期可能会更多的重视订单、转化、途径等相关剖析方针。假如能在运用上线之初,快速的拿到中心剖析方针数据,对产品的推广,迭代无疑是收益良多。所以,本次模型构建从运用初期剖析最广泛的中心方针动身,落地运用概况、页面拜访、用户留存等维度全方位中心剖析方针体系。
图(1)运用生命周期内方针剖析状况
2.2.1 剖析模型主题
本次通用剖析模型围绕以下剖析主题构建。
-
**【根底剖析】:**从用户浏览次数,人均拜访页面数,人均运用时长,新老用户等根底方针展现用户拜访大盘数据。
-
**【页面剖析】:**面向具体页面,剖析用户拜访pv,uv,拜访时长等中心方针,有针对性的发现页面访量薄弱环节,为合理化页面办理供给数据支撑,帮忙产品司理经过信息重组,提高页面拜访量。
-
**【留存剖析】:**经过用户的留存,了解现在的产品现状(用户的哪些行为导致留存率的不同); 判别产品的改进有无效果(用户行为是否发生了改动导致留存率的提高);留存剖析反映了用户由初期的不安稳用户转化为活泼用户,安稳用户,忠诚用户的过程。
2.2.2 剖析方针界说
(以下示例中数据均为参阅数据,非实在数据)
**1、根底剖析:**拜访pv,uv等方针(全维度)
**2、页面剖析:**页面拜访相关pv,uv,时长等方针
注:用户对拜访页面进行命名,剖析渠道供给装备入口,便使用户对页面进行命名。
**3、留存剖析:**新用户留存,活泼用户留存 包括:N日内留存 和 第N日留存。
一般意义上的留存剖析指的是:用户在APP发生行为后,在固定的第N日继续拜访或运用APP的用户;包括活泼用户留存和新用户留存
为满意不同事务的剖析需求。此次留存模型包括 n日内留存剖析,即用户在APP发生行为后,在固定的第N日内继续拜访或运用APP的用户(日期范围留存)。
三、埋点计划
3.1 事务方针
-
收集用户的pv,uv数据,协助产品同学了解现在的产品现状,并不断改进产品;
-
主动收集,对pv,uv等这类埋点,事务无需再开发,翻开开关即可收集这类数据。
3.2 主动收集
3.2.1 什么是主动收集
主动收集是相对于前端开发者而言,意图是为了协助前端开发者提高数据收集功率。经过主动收集开关装备,无需在手动完结上报逻辑。运用时前端开发者经过引进h5sdk.js(也称jssdk.js),翻开主动收集开关,咱们就会在恰当的机遇,以恰当的规矩收集数据,并进行上报。开发者无需在重视收集代码内部逻辑,以此来减轻同类数据收集的开发作业量。
3.2.2 如何主动收集
依照给定的规矩进行页面事情EventListener,当用户活动触发对应的事情时,咱们会组装好数据,然后将组装好的数据经过https传入到后台。
3.2.3 主动收集的三大规矩场景
咱们的网站是一个SPA运用。SPA运用经过改动前端路由的改动,完结页面内组件的切换。组件的切换,对于一个非前端开发者来说,能够泛指页面的切换。所以咱们第一场景是要掩盖url改动的这类事情。在实践中,咱们发现,当咱们需求收集页面的用户逗留时长时,往往会不精确。为什么不精确?用户能够缩小化浏览器,也能够切换tab到其他网站,这个时分核算的用户时长是不精确的。因为用户尽管翻开了咱们网页,可是并没有聚集到咱们的网页。这种不应该算作用户逗留时长,因而对于这些行为,咱们又加上了失掉焦点,得到焦点,以及切换浏览器tab事情的EventListener,这两种场景。
综上三大场景总结如下:
-
页面切换时,进行收集,即url改动时触发的事情;
-
页面失掉焦点,得到焦点时,进行收集。即focus,blur事情;
-
页面经过浏览器tab切换脱离,切换回来时,进行收集,即visibilitychange事情;
3.2.3.1 三大规矩场景的界定
上文咱们现已在实践中总结出了主动收集的三大场景,在实际运用针对三大场景的运用咱们也总结出了一套界定计划。
(1)规矩一界定——怎样判别页面切换?
a、现在的网站要么是MPA,要么是SPA形式,或许两种形式混合,MPA主要是后台路由,SPA主要是前端路由(hash形式和history形式)。但无论是SPA还是MPA,当页面需求切换时,url必定会改动,根据此点,咱们判别当url改动时,用户必定切换了页面。此刻触发规矩一的事情,发生数据上报。
这儿需求留意2个问题:
-
**第1个问题:**url改动 = window.location.origin + window.location.pathname + window.location.hash 这三部分的任一部分改动,即为url改动,并不包括window.location.search这部分的改动;
-
**第2个问题:**在SPA中,假如一个页面内有多个tab,当切换tab时,开发者也改动他的url的window.location.pathname,此刻也会以为是页面切换,也会发生上报数据,如下这种状况。
图(2)
b、完好页面切换上报流程,由页面A切换到页面B时,总共上报4个埋点;
图(3)
c、关于路由的EventListener
现在的大多网站,大多是SPA运用,SPA的前端路由有hash形式和history形式这两种形式,当经过前端路由来页面切换时,肯定会触发hash形式或history相关的api。
因而,咱们只需求把一切触发事情的场景给全部进行EventListener即可。有如下2种路由的EventListener:window.hashchange事情——触发hash形式时、window.popstate事情、pushstate,replacestate自界说事情——触发history形式时。
这儿有2个问题需求重视:一是当某个SPA运用的路由事情,触发了history形式时,咱们应该移除hash形式的EventListener。二是pushstate,replacestate自界说事情,因为BOM并没有供给相关的api支撑EventListener,需求自行封装运用,如下code。
引进JSSDK
/**
* 拼接通用化上报参数
* @param {string} 重写路由事情类型
*/
function resetHistoryFun(type){
// 将原先的办法仿制出来
let originMethod = window.history[type]
// 当window.history[type]函数被履行时,这个return出来的函数就会被履行
return function(){
// 履行原先的办法
let rs = originMethod.apply(this, arguments)
// 然后自界说事情
let e = new Event(type.toLocaleLowerCase())
// 将原先函数的参数绑定到自界说的事情上去,原先的是没有的
e.arguments = arguments
// 然后用window.dispatchEvent()主动触发
window.dispatchEvent(e)
return rs;
}
}
window.history.pushState = resetHistoryFun('pushState') // 掩盖本来的pushState办法
window.history.replaceState = resetHistoryFun('replaceState') // 掩盖本来的replaceState办法
window.addEventListener('pushstate', reportBothEvent)
window.addEventListener('replacestate', reportBothEvent)
(2)规矩二界定——怎样判别页面失掉焦点,得到焦点?
失掉焦点,得到焦点。咱们主要进行如下这两个事情的EventListener:
引进JSSDK
window.addEventListener('focus', ()=>{
console.log('页面得到焦点')
});
window.addEventListener('blur', ()=>{
console.log('页面失掉焦点')
})
(3)规矩三界定——怎样判别浏览器tab切换脱离,切换回来?
tab切换脱离,切换回来。咱们主要进行如下这一个事情的EventListener:
引进JSSDK
document.addEventListener('visibilitychange', () => {
if(document.hidden) {
console.log('页面脱离')
} else {
console.log('页面进入')
}
})
**留意:**假如一个行为一起满意2个及2个以上的规矩时,只会取一个规矩上报数据。防止不重复上报数据。
3.3 埋点规划
3.3.1 埋点个数
为了得到pv和uv的相关数据,咱们规划了2个埋点,1个为页面进入时上报的埋点,别的1个为页面脱离时的埋点,上报的数据都是一对的,脱离-进入页面为一对,失掉焦点-得到焦点为一对,切换tab脱离当时页面-返回当时页面也为一对;
为什么要规划2个埋点?规划2个埋点,能掩盖全面上述咱们所说的3种规矩场景;其次,方面核算页面逗留时长;最后便是便利逻辑判别,防止重复上报;
3.3.2 参数的规划
依照不同的需求,参数的规划分为如下4类:
-
**pv,uv需求参数,开发者传入参数:**unique_id——标识用户仅有标识、topic_id——当时网站仅有标识、current_env——当时网站环境,默以为prod,可用户传入;
-
pv,uv需求参数,sdk内部获取参数:duration——页面逗留时长、last_page_url——上个页面url、page_url——当时页面url;
-
SDK需求的参数,协助判别事情触发类型,SDK内部获取参数:eventType
-
**用户其他需求补充的参数:**自界说参数
3.4 数据上报
数据上报方法是XMLHttpRequest、window.navigator.sendBeacon,根据h5sdk上报逻辑架构。
图(4)
3.5 兼容性和容错性
关于兼容性,依赖于window方针、不兼容IE6、IE7,IE8;
关于容错性,对通用化内部逻辑做了try catch的容错兼容,保证犯错时不影响事务主逻辑运转,一起上报一个犯错的事情类型,知道犯错的原因,以便提前做好对应的优化计划。
3.6 个人数据保护合规
为了保护好用户的个人数据及其隐私并满意法律法规要求,在埋点的规划、收集、运用等环节需求进行充分的隐私保护规划。例如,在埋点规划阶段,需求确认标识符的选择、埋点参数的最小必要、收集频率的最小必要等;在埋点的收集、运用阶段,需求保证相关处理行为的透明、可控,包括对用户进行奉告,获取用户的有用赞同,供给撤回赞同的渠道等等。
四、数仓计划
埋点计划现已具有,接下来的作业便是规划一套接入高效,拓展快捷的数仓剖析模型;为完结以上既定的剖析方针,模型规划过程中需求处理以下中心问题。
4.1 中心问题列表
4.2 模型分层标准
介绍模型规划前,先说下vivo 数仓模型分层基本准则,及本次模型分层思路,各层模型规划准则参照《vivo中台数仓建造办法论》,层级规划摘要如下:
4.3 模型层级架构
经过中心问题拆解发现,为完结通用剖析模型计划,需求从数据接入层收口,在数据接入时一致参数解析,一致字段命名,并设置相应的运用id字段,区别各个事务数据源;接着需求生成活泼数据明细表,可计算相应的根底剖析,页面剖析方针;一起为满意留存剖析的需求,咱们需求构建相应的活泼全量表,留存剖析主题表根据活泼增量表和活泼全量表生成,用户活泼信息经过打标签的方法标记。至此涉及三个主题剖析的模型规划结束。层级划分准则及规划逻辑模型明细,如:图(5)
图(5)
从分层架构图可看出H5通用剖析模型分为明细层(dw)、轻度汇总层(dma)、剖析主题表 (dmt) 和方针层(da); 其中轻度汇总层可作为中间数据供给职业剖析师及数据开发、事务产品等查询剖析运用;汇总层作为剖析渠道通用剖析模型报表数据源,导入mysql存储,前端根据mysql表完结数据展现,各个模型规划细则如下:
数据模型规划及规划的中心在于三点:确认appid和用户id映射联系,留存计划完结及留存记载入库bitmap方法读写。
1、确认appid和用户id映射联系-unique_id 相关规划
多事务id一致
## 明细层收口数据,一致id字段
SELECT xx
,xx1
,CASE WHEN appid IN(1) THEN 1
WHEN appid IN(2) THEN 2
WHEN appid IN(3) THEN 3
WHEN appid IN(4,5,6,...) THEN 4
ELSE 0 END AS id_flag
,CASE WHEN appid IN(1) THEN id1
WHEN appid IN(2) THEN id2
WHEN appid IN(3) THEN id3
WHEN appid IN(4,5,6,...) THEN IF(NVL(params['id1'],'')='',NVL(params['id2'],'NA'),params['id1'])
ELSE 'NA' END AS unique_id
,appid
FROM ods_table_name_XXX a -- 各个接入事务线数据源 ods
WHERE day='${today}'
AND hour = '${etl_hour}'
-- APPID 和 事情id 要匹配新增
AND appid in (1,2,3 ...)
AND 事情id in (XXX|167,XXX|168,...);
## id字段后续相关运用方法
## 增量相关全量,确认是否新用户
SELECT if(b.unique_id is null,1,0) AS is_new
FROM
(
SELECT *
FROM table_XXX_hi
WHERE day= '${today}'
AND hour = '${etl_hour}'
GROUP BY XX
) a
-- 取全量表仅有 unique_id 作为相关条件,判别新老用户
-- 新用户是相对于前史全量的
LEFT JOIN ( SELECT unique_id,appid
FROM
( SELECT unique_id
,appid
,row_number() over(partition by unique_id,appid order by 活泼日期 asc) as rn_0
FROM table_XXX_df
WHERE day='${etl_date}'
) a
WHERE rn_0 = 1
) b
ON a.unique_id = b.unique_id AND a.appid = b.appid;
2、留存计划完结及留存记载入库bitmap方法读写
留存计划
## 使用bitmap思维,留存标签满8位转化为16进制组合到retain_tag之前,这样能够使用很少的位数记载较长的活泼状况
## 示例代码如下
SELECT user_unique_id
,if(length(tmp_retain_tag) = 8,is_active,concat(is_active,tmp_retain_tag)) as tmp_retain_tag
-- 假如tmp_retain_tag长度为8的时分,将数据转化为十六进制添加到retain_tag前,并将本字段清空,从头开始计数
,if(length(tmp_retain_tag) = 8,concat(con_tmp_retain_tag,retain_tag),retain_tag) as retain_tag
,is_active
FROM
(
SELECT unique_id
-- 前一天的临时存储,与con_tmp_retain_tag保持一致
,tmp_retain_tag
-- 假如转换为十六进制后的长度不为2,则在左边添加0
,if(length(conv(tmp_retain_tag,2,16)) = 2,conv(tmp_retain_tag,2,16),concat('0',conv(tmp_retain_tag,2,16))) as con_tmp_retain_tag
-- 前史轨道
,retain_tag
,first_value(is_active) over(partition by unique_id,appid,topic_id order by first_active_day desc) as is_active
FROM
( SELECT unique_id
,topic_id
,appid
,first_active_day
,last_active_day
-- 留存标签
,'0' as is_active
,tmp_retain_tag -- 形如 11101010
,retain_tag -- 形如 A0E3
FROM table_active_XX_df -- 活泼全量表
WHERE day= '${last_etl_date}'
UNION ALL
SELECT unique_id
,topic_id
,appid
,day as first_active_day
,day as last_active_day
-- 留存标签
,'1' as is_active
,'' as tmp_retain_tag
,'' as retain_tag
FROM table_active_XX_hi -- 活泼明细表
WHERE day= '${etl_date}'
) a
) b
WHERE rn =1;
## 留存方针计算:## 以3日内及第3日留存为例
WITH tmp_table AS (
SELECT DAY
,unique_id
,appid
,初次活泼日期
,CONCAT(tmp_retain_tag,retain_tag) AS login_trace
FROM (
SELECT DAY
,unique_id
,tmp_retain_tag
,appid
,初次活泼日期
,IF(nvl(retain_tag,'') <> '',CONV(SUBSTR(retain_tag,1,8),16,2),'') AS retain_tag
-- 假如retain_tag为空时,直接取空值。假如长度超越8位数,取最后八位数;假如长度不超越8位数,取全部。假如是30日内新用户,长度不超越8位
FROM table_active_XX_df WHERE DAY = 计算日
) x1
)
## 以3日内及第3日留存为例:
SELECT -- 第N日留存方针:第N日来访
,SUM(IF(SUBSTR(login_trace,3,1) = '1',1,null)) AS retain_cnt_3th
-- N日内留存方针:N日内拜访过1次或N次
,SUM(IF(instr(SUBSTR(login_trace,2,2) ,'1')= 0,null,1)) AS retain_cnt_between_3th
FROM (
SELECT '计算日-2天' AS dt
,unique_id
,REVERSE(SUBSTR(login_trace,1,3)) AS login_trace
,appid
FROM tmp_table WHERE SUBSTR(login_trace,3,1) = '1' AND 初次活泼日期 = 计算日-2天
) X GROUP BY dt,appid;
4.4 模型数据流图
至此,模型的规划落地全部完结,模型包括埋点数据表2张,dw明细层模型1张,维表1张,dma轻度汇总主题层2张,dmt主题表2张,任务层深4层,模型层2层,模型数据接入0.5人日可完结。
数据流图如下:
图(6)
五、数据展现
模型数据展现可根据用户行为剖析渠道,数据方针存储运用 MySQL 数据库,数据展现逻辑完结如下:
图(7)
5.1 报表展现
报表装备完结后,各个剖析模块的前台展现示例如下:
图(8)运用概况报表
图(9)用户留存报表
图(10)页面剖析报表
六、未来展望
至此,H5通用分模型落地流程已介绍结束。本文主要是根据事务初期诉求,快速落地通用的、一致的数据处理计划,满意事务剖析人员在产品初期最火急的剖析需求。随着事务的不断开展迭代,运营产品的剖析方向也会不断的扩展和深化,一起不同的事务重视点不同,针对剖析模型的诉求也不尽相同。例如在事务中后期,简单的拜访留存剖析现已支撑不了更进一步的决策制定,此刻针对页面拜访的途径剖析模型;针对营销剖析的订单转化模型、归因剖析模型;针对页面跳转剖析的用户漏斗模型等需求会相应变多。
所以,为更好的支撑事务方针达到,H5通用剖析模型系列在后期会根据事务诉求落地相应的剖析模型,继续为产品运营供给高效安稳的数据处理计划。
相关文章:
-
用户行为剖析模型实践(一)—— 途径剖析模型
-
用户行为剖析模型实践(二)—— 漏斗剖析模型