文章

埋点之非入口页路径透传方案

1. 简介

区别于入口页方案,非入口页算是链路追踪的升级版本,从单一节点的递进推演,直接升级为连续五个节点的统一获取的形式。

2. 透传方案

对于日渐增加的分析需求,和用户数据量的倍增,需要更快一步的支持用户的行为追踪,老一套的埋点数据分析方案,已经不能够满足需求了。

  1. 透传方案新

    • 透传APP生命流程周期内连续五个页面的事件sequence(页面view事件和页面间跳转的click事件)
    • 当多于5个页面时,先进先出原则,保留五个页面
    • 当前页面为回退时,透传数据向前回退两个页面及页面的click事件
  2. sequence相关

    取消to_page参数,from_page 改为from_seq(上个页面view或有跳转页面的click)

  3. from_seq和seq_list只记录在,页面view事件和页面间跳转的click事件中

  4. h5的相关也是需要native来记录

  5. sequence递增(wap不需要做到)

  6. seq_list内数据按用户操作的交互顺序排序

3. 后端接口

4. 数据结构

统计内层数据需要增加两个字端

字段名类型是否必须默认值备注
ypmMap<string, string>空字符串上一个页面访问或是带跳转带点击事件的{se,en,pn,pm,ad,mi} -> {sequence,event_name,page_name,parameters,abtest_dis,mi}
ypm_listList<Map<string, string»空数组ypm_list可取值范围为APP的一个生命周期内1. 透传APP的生命周期内前五个页面中的事件(页面view事件和页面间跳转的click事件)的{sequence,event_name,page_name,parameters,abtest_dis,mi}—这里的前五个页面中的事件指:五个view事件+自身页面带跳转的click事件(没有click记空-1代替)2. 当ypm_list多于5个页面时,先进先出,保留五个页面事件3. 当前页面为回退时,透传数据向前回退两个view事件(view页面和页面跳转的click事件)4. 如果两个页面之间没有click事件的链接跳转,需要在两个view事件之间插入空,定位值-1 为空

ypm的主要使用目的是用来取缔to_page和from_page,形成对路径的链接串;

ypm_list即为透传数据字端,目前是五级透传。

修改之后的内层事件埋点字段如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
{
  "event_action": "view",
  "event_name": "view_newitem",
  "frompage": "yanxuan://commoditydetails?source_tracker_type=1&commodityid=100100",
  "is_return": 1,
  "locpage": "yanxuan://homepage_newarrival",
  "log_source": "app",
  "page_name": "newitem",
  "parameters": {
    "from": 2,
    "name": "测试"
    "extra": {
        "resource": {
            "taskId": "44352561",
            "materialId": "49011191",
            "taskType": 1,
            "resourcesId": 1,
            "crmUserGroupId": "0",
            "crmUserGroupName": "无分组",
            "materialName": "女式咖啡碳+5℃保暖内衣(上衣/裤子)",
            "itemId": "1164006",
            "materialType": "商品id",
            "itemIdList": [
                "1164006"
            ],
            " itemFrom,": "1-运营指定 2-算法推荐",
            "rcmdsort": "算法排序标识boolean值, 首焦模块中可标识是否候选队列推荐素材",
            "recommend": "算法推荐队列数据"
        },
        "modelType": 1,
        "abtest_dis":'10_11|12_13' #实验ID_方案ID(rdc或者rcmd来源的多个实验  "|" 分隔)
    }
  },
  "sequence": "v_1_1550734611837",
  "sessionid": "416f72acc696ccd92cae7ddf3ef51c71530243064347",
  "timestamp_a": 1530243349740,
  "abtest_info": "",
  "abtest_dis": "实验a_分组2|实验b_分组3",
  "mi": "",
  "ypm": {
      "sequence":"v_1_1550734611835",
      "page_name":"newitem",
      "event_name": "view_newitem",
      "parameters":"",
      "abtest_dis":"实验a_分组2|实验b_分组3",
      "mi":""
   },
  "ypm_list": [{
      "sequence":"v_1_1550734611835",
      "page_name":"index",
      "event_name": "view_index",
      "parameters":"",
      "abtest_dis":"实验a_分组2|实验b_分组3",
      "mi":""
      },{
      "sequence":"v_1_1550734611835",
      "page_name":"index",
      "event_name": "click_index_new",
      "parameters":"",
      "abtest_dis":"实验a_分组2|实验b_分组3",
      "mi":""
      },{
      "sequence":"v_1_1550734611835",
      "page_name":"newitem",
      "event_name": "view_newitem",
      "parameters":"",
      "abtest_dis":"实验a_分组2|实验b_分组3",
      "mi":""
      },{
      "sequence":"v_1_1550734611835",
      "page_name":"newitem",
      "event_name": "click_newitem_allitem",
      "parameters": { "itemid": 100100 },
      "abtest_dis":"实验a_分组2|实验b_分组3",
      "mi":""
      },{
      "sequence":"-1",
      "page_name":"",
      "event_name":"",
      "parameters":"",
      "abtest_dis":"实验a_分组2|实验b_分组3",
      "mi":""
        }
   ],
  "mark" : {
	"page": "index",
	"module": {
		"name":"click_index_lightsale",
		"parameters":{
			"sequen":1,
			"itemId":1098323
		},
        "abtest_dis":"实验a_分组2|实验b_分组3",
        "mi":""
	}
   }
}

5. 流程图

用户交互流程图

入口页透传方式

用户操作行为链:

V1->C3->V2->V3->C8->V4->C12->V5->C13->V6->C16->V7->V6(返)->V5(返)->V4(返)->C10->V5

以上面的操作行为为例子:

from_seq即为当前节点的上一个事件,例如V3访问事件的from_seq即为上个节点V2。

对于透传,引入一个新的概念,页面层级属性,(见下表的灰色部分,V2页面的层级属性为V1、C3) seq_list的取值见下表

  1. V1:
  2. C3: V1
  3. V2: V1、C3
  4. V3: V1、C3、V2、-1
  5. C8: V1、C3、V2、-1、V3
  6. V4: V1、C3、V2、-1、V3、C8
  7. C12: V1、C3、V2、-1、V3、C8、V4
  8. V5: V1、C3、V2、-1、V3、C8、V4、C12
  9. C13: V1、C3、V2、-1、V3、C8、V4、C12、V5
  10. V6: V1、C3、V2、-1、V3、C8、V4、C12、V5、C13
  11. C16: V2、-1、V3、C8、V4、C12、V5、C13、V6
  12. V7: V2、-1、V3、C8、V4、C12、V5、C13、V6、C16
  13. V6(返):V1、C3、V2、-1、V3、C8、V4、C12、V5、C13
  14. V5(返):V1、C3、V2、-1、V3、C8、V4、C12
  15. V4(返):V1、C3、V2、-1、V3、C8
  16. C10: V1、C3、V2、-1、V3、C8、V4(返)
  17. V5: V1、C3、V2、-1、V3、C8、V4(返)、C10

备注:

加粗代表的是页面的访问,每个页面存储自己的ypm_list

仔细看,其实取值关系对应如下

13-10 14-8 15-6

意思是取的是同一个页面上面的层级属性

实现流程细节图

非入口实现细节

实现策略备注:

  1. ypm只记录在访问事件和带跳转带点击事件中,同现有的frompage存储一样,使用全局变量的形式来存储维护一个ypm的值或对象。
  2. 每个页面保存自己的层级路径
  3. 每个页面的层级属性的生命周期是页面级别,跟随页面的生命周期走
  4. 回退或是跳转到原有界面,取当前界面的层级属性为seq_list即可
  5. 没有点击的页面跳转,记为空点击,用-1表示
  6. h5的ypm_list也需要我们来统一记录

目前碰到的问题

2019.02.21 修改sequence结构

sequence对相同的event_time去重之后,仍有大量的重复数据

对2019.02.21号数据进行排查

iOS端(错误重复数据:3671;用户数:1291)

Android端(错误重复数据:13418;用户数:1101)

各端抽样十条数据出来对用户重复数据前后的行为进行排查得出:

iOS为写入sequence的keychain失败,导致下一次启动app 使用的序列号还是同上一次一样导致的。

Android是因为用户清空了sequence配置文件或是写入文件失败导致的,sequence计数重复

解决方案:经过讨论之后,废弃sequence强制递增的逻辑,只需保证其全局唯一性即可。

现wap的sequence为:v_f6fb9e10c2,c_93b655dbca,o_5cabf2f9b2

其中打头分别是v-view,c-click,o-other

后面为sessionid的32位任意值md5之后取的前十位数字,因url长度限制,不能过长,遂取前十位。

因现有APP端的sequence存在重复,和业务方需要统一三端格式,所以暂定格式拼接同现有wap:

可选方案如下:

  1. [vco]_[现有sequence内存级别递增逻辑]_[timestemp],例如:v_1_1550734611837,o_100_1550716542894
  2. [vco]_[md5(uuid+timestemp+username)],例如:uuid:03e65aa50b664852d2cc05e19f43d,timestemp:1550734611837,username:qiujunyun@163.com,最后即为:v_079a5eda2945a73f86d1f0b4f4f37d9a
  3. wap的截取规则,同第二步,但是md5后取前十位,如:v_079a5eda29
最后敲定选择方案1:[vco]_[现有sequence内存级别递增逻辑]_[timestemp],如v_1_1550734611837

影响范围:sequence修改之后,相应的seq_list和from_seq也需要修改。

2019.6.21 重新命名seq_list from_seq

因需要整改严选的位置模型YPM 需要对seq_list中的数据进行修改

seq_list和from_seq进行内容丰富并修改名字为:

seq_list –> ypm_list

from_seq –> ypm

==(备注:不保留字段seq_list和from_seq)==

内容改为json对象:

sequence 序列号

page_name 页面名

[见修改后的数据结构](

本文由作者按照 CC BY 4.0 进行授权