漏斗模型分析
一、理论部分:
漏斗模型在广告营销效果分析中,通常包括以下几个关键部分:
- 广告曝光:广告在媒体上被展示的次数。
- 广告点击:用户对广告产生兴趣,点击广告链接进入网站或应用。
- 网站访问:用户通过广告链接进入网站后,进行浏览和交互。
- 转化:用户在网站或应用中完成特定的目标,例如购买商品、注册账户等。
在每个阶段,都有相应的数据指标来衡量广告效果,例如曝光量、点击率、访问量、转化率等。通过漏斗模型,企业可以分析每个阶段的转化率,找出转化率低的原因,并采取相应的优化措施。
二、实际包含数据的案例:
游戏广告转化漏斗
1、转化路径:
展示→点击→跳转(落地页)→下载→激活→注册→付费
2、数据指标:
展示:曝光次数
点击:点击率
跳转(落地页):到达率
下载:下载率
激活:下载激活率
注册:激活注册率
付费;付费率
3、影响因素:
曝光次数:出价、定向、大盘流量、预算
点击率:素材、定向、文案、按钮、位置
到达率:网络加载、链接设置
下载率:文案引导、内容展示、按钮、链接设置
下载激活率:误触、网络、技术报错、虚假流量、拦截、归因
激活注册率:虚假流量、归因、技术报错、网络、素材与界面
付费率:游戏生态、运营活动、流量质量、广告转化预期
整体的设计大概分三阶段:配置、计算、存储。
(1)配置
此阶段主要是工程端的后台服务实现。用户在前端按照自身需求设置漏斗类型、漏斗步骤、筛选条件、时间区间和周期等配置。后台服务收到配置请求后,依据漏斗类型选择不同任务组装器进行任务的组装。
其中,漏斗类型是无序漏斗使用的Hive SQL 任务组装器,而更加复杂的有序漏斗可以使用 Spark任务组装器。组装后生成的任务包含了漏斗模型的计算逻辑,比如 Hive SQL或者 Spark 任务。
(2)计算
平台根据接收到的任务的类型,选择Hive或者 Spark引擎进行分析计算。计算结果同步到 MySQL 或者ClickHouse集群。
(3)存储
结果集持久化到数据库中,可通过后台服务展示给用户。
有序漏斗实现逻辑
一、获取规定时间区间内的数据集。
其中,day为数据上报的时间,userId为用户唯一标识,event为事件,event_time为事件发生时间。
二、按照漏斗步骤计算每行数据处于的漏斗步骤。
假设需要统计分析的漏斗步骤为:“曝光”->“点击”->“浏览”->“下载”。‘“曝光”标记为1,“点击”标记为2,“浏览”标记为3,“下载”标记为4,记录在event_step字段上。
三、对上述数据进行处理,得到每个用户在当天有序的事件上报列表。
将上述数据按照day,userId分组,按event_time顺序,分别求取event_step和event_time的有序集合,并根据 event_step获取漏斗触达的最大深度,记为level,如下:
四、计算每一步漏斗的人数。
按照day与level分组计算每一步漏斗的人数,也是是每个level的uv。
需要注意的是,因为计算的是每一步漏斗的人数,所以步骤与步骤之间人数是没有交集的,但事实上,根据有序漏斗的计算逻辑,触达漏斗后面的步骤,一会触达其前面的漏斗步骤。
所以,前面的步骤一定要加上其后所有步骤的的人数,才是该步真正的人数。如上面的例子,对于2021-05-01的数据,level=1的uv为1,level=2的uv为0,level=3的uv为1,所以level=1实际总人数为三步人数之和,也就是2。依次类推,由此可以得到所有步骤真正的总人数。
-
存在的问题与下一步优化的方向
**问题:**现阶段用户通过自定义的配置,生成相应的Spark或者Hive任务计算出模型的结果并生成报表,进而展示给用户。这样的流程在提供给用户灵活的配置和个性化的查询的同时,兼顾了节约存储资源。美中不足的是报表的生成过程,依然需要耗费一定的时间成本,尤其是有序漏斗采用了Spark计算,对于队列资源也会产生较大的消耗。这点在用户短时间创建大量的分析报表时,体现的尤为明显。
**优化方向:**将一定时期内的相关的数仓数据同步到ClickHouse,依托ClickHouse强大的即时计算和分析能力,为用户提供所查即所得的使用体验。用户可以根据自身业务需求选择即时查询或者离线报表。例如,比如需要大量组合各类条件进行对比分析的可以选择即时模块。需要长期观察的报表可以选择离线的例行报表。这样就达到的存储和查询效率的平衡。
ClickHouse 在模型的计算速率上较为理想,但是缺少自定义函数功能,有一些业务场景ClickHouse满足不了。
-- 首先构建一个ClickHouse表funnel_test,包含用户唯一标识userId,事件名称event,事件发生日期day。 -- ClickHouse按天计算用户数以及各层级的PV、UV SELECT day AS day, sum(level1_pv) AS sum_level1_pv, sum(level2_pv) AS sum_level2_pv, sum(level1_uv) as sum_level1_uv, sum(level2_uv) as sum_level2_uv from ( select day, userId, groupArray(event) as events, arrayCount(x-> x = '启动', events) as level1_pv, if(has(events, '启动'), arrayCount(x-> x = '首页', events), 0) as level2_pv, hasAll(events, ['启动']) as level1_uv, hasAll(events, ['启动','首页']) as level2_uv from ( SELECT toDate(day) as day, event, userId FROM funnel_test WHERE toDate(day) >= '2021-05-01' and toDate(day) <= '2021-05-06') group by day, userId ) group by day order by day;
and toDate(day) <= '2021-05-06') group by day, userId )
group by day
order by day;