前言
在数据时代,广告的投放效果评估往往会产生很多的问题。而归因分析(Attribution Analysis)要解决的问题就是广告效果的产生,其功劳应该如何合理的分配给哪些渠道。如电商、游戏、零售...等各个行业中经常遇到。
为什么需要归因?
在用户全生命周期旅程中,用户所做的事情是碎片化的,对于业务来讲,每天都会面临大量的用户数据以及用户复杂的行为路径,用户在不同生命周期阶段会产生各种触点,涉及多种设备(智能手机、平板电脑、个人电脑等)、平台(手机vs桌面网页)和渠道(付费、电子邮件、社交等),这些外因对用户产生了怎样的影响,促使用户最终完成转化?而这个转化的背后,是源自于怎样的用户行为路径,业务往往很难知道,通常业务人员是凭借以往经验来进行策略的推测。随着互联网的发展,我们通过技术手段找到了将用户旅程串起来的办法,并依此形成多种不同方式的归因解决方案来去帮助业务完成归因。
归因分析(Attribution Analysis)要解决的问题就是广告效果的产生,其功劳应该如何合理的分配给哪些渠道。拓展下场景的话,归因分析用于分析待归因事件对目标类事件的发生的转化贡献。
什么是归因分析?
归因指的是通过某种方法,找到事物产生结果的原因,也可以理解为是寻找一种因果关系。
在互联网中,一般用来确定如何将用户转化功劳分配给转化路径中的各个触点。通俗的讲,就是当用户发生了某个转化行为时,归因分析可以帮你确定哪些因素对用户的转化行为产生了决定性作用。
归因,是一个过程,通过技术手段将用户全生命周期产生的触点串联起来,并进行追溯。常见的归因有渠道归因、网站归因、移动归因、用户归因、行为归因等。
常见归因分析类别?
末次归因模型
也称最后点击模型,这种归因模型将功劳100%分配给转化前的最后一个渠道,即不管用户发生了啥行为,只关注最后一次。这是最简单、直接,也是应用最为广泛的归因模型
##优点 首先它是最容易测量的归因模型,在分析方面不容易发生错误。另外由于大部分追踪的cookie存活期只有30-90天,对于顾客的行为路径、周期比较长的场景,在做归因分析的时候可能就会发生数据的丢失,而对于末次互动模型,这个数据跟踪周期就不是那么特别重要了 ##缺点 这种模型的弊端也是比较明显,比如客户是从收藏夹进入商品详情页然后形成了成交的,按照末次归因模型就会把100%的功劳都归功于收藏夹(直接流量)。但是真实的用户行为路径更接近于产生兴趣、信任、购买意向、信息对比等各种环节,这些都是其他渠道的功劳,在这个模型中则无法统计进来,而末次渠道的功劳评估会被大幅高估 ## 适用场景 短期的投放,转化路径少、周期短的业务快速提升效果,按照末次归因模型,能比较好了解到底是哪个渠道对于最终的转化有比较好的促进作用
末次渠道互动模型
末次渠道互动模型会将100%的功劳归于客户在转化前,最后一次点击的广告渠道。需要注意这里的”末次互动”是指任何你要测量的转化目标之前的最后一次互动,转化目标可能是销售线索、销售机会建立或者其他你可以自定义的目标。
##优点 这种模式的优点是通常跟各渠道的标准一致,如Facebook Insight使用末次Facebook互动模型,谷歌广告分析用的是末次谷歌广告互动模型等等 ##缺点 很明显当你在多渠道同时投放的时候,会发生一个客户在第一天点了Facebook的广告,然后在第二天又点击了谷歌广告,最后并发生了转化,那么在末次渠道模型中,Facebook和谷歌都会把这次转化的100%功劳分别归到自己的渠道上。这就导致各个部门的数据都看起来挺好的,各个渠道都高估了自己影响力,而实际效果则可能是折半,如果单独使用这些归因模型并且把他们整合到一个报告中,你可能会得到”翻倍甚至三倍”的转化数据 ##适用场景 单一渠道,或者已知某个渠道的价值特别大
首次归因模型
也称首次点击模型,这种归因模型将功劳100%分配给第一个触达渠道,即不管用户发生了啥行为,只关注第一次。如果,末次互动是认为,不管你之前有多少次互动,没有最后一次就没有成交。那么首次互动就是认为,没有我第一次的互动,你们剩下的渠道连互动都不会产生。换句话说,首次互动模型更加强调的是驱动用户认知的、位于转化漏斗最顶端的渠道
##优点 是一种容易实施的单触点模型,初次点击的归因会让你明确潜在消费者是怎样找到你的,且和最后点击一样,不需要大量的数据 ##缺点 受限于数据跟踪周期,对于用户路径长、周期长的用户行为可能无法采集真正的首次行为,且初次点击归因并不能够解释所有后续所发生的用户行为,对于后续的用户行为没有关注 ##适用场景 一般是需要进行拉新的时候,公司处于市场开拓的时候,这个时候我们关心把更多的用户先圈过来,那么用首次互动模型可以看出来哪些渠道对于业务拉新最有效。所以首次归因模型对于没什么品牌知名度、且重点在市场拓展,渠道优化的公司,比较适用
线性归因模型
线性归因是多触点归因模型中的一种,也是最简单的一种,他将功劳平均分配给用户路径中的每一个触点
##优点 它是一个多触点归因模型,可以将功劳划分给业务路径中每个不同阶段的营销渠道,不用考虑不同渠道的价值权重,大家一视同仁,计算也不复杂。另外,它的计算方法比较简单,计算过程中的价值系数调整也比较方便 ##缺点 很明显,线性平均划分的方法不适用于某些渠道价值特别突出的业务,对于价值比价高的渠道,可能会“被平均”,因为这种渠道是靠质量而不是数量赢得结果的。比如,一个客户在线下某处看到了你的广告,然后回家再用百度搜索,连续三天都通过百度进入了官网,并在第四天成交。那么按照线性归因模型,百度会分配到75%的权重,而线下某处的广告得到了25%的权重,这很显然并没有给到线下广告足够的权重 ##适用场景 根据线性归因模型的特点,它更适用于企业期望在整个销售周期内保持与客户的联系,并维持品牌认知度的公司。在这种情况下,各个渠道在客户的考虑过程中,都起到相同的促进作用
时间衰减归因模型
对于路径上的渠道,距离转化的时间越短的渠道,可以获得越多的功劳权重。时间衰减归因模型基于一种假设,他认为触点越接近转化,对转化的影响力就越大。这种模型基于一个指数衰减的概念,一般默认周期是7天。也就是说,以转化当天相比,转化前7天的渠道,能分配50%权重,前14天的渠道分25%的权重,以此类推
##优点 这个模型考虑了时间的作用,因为一般情况下也是时间越久对于用户的转化作用是越弱。相比线性归因模型的平均分权重的方式,时间衰减模型让不同渠道得到了不同的权重分配,当然前提是基于"触点离转化越近,对转化影响力就越大"的前提是准确的情况下,这种模型是相对较合理的 ##缺点 如果有的渠道天然处于转化链路的起点,那么对于这些渠道是不公正的,因为它们总是距离转化最远的那个,永远不会得到一个公平的权重 ##适用场景 和末次归因比较类似,适用于客户决策周期短、销售周期短、引导用户完成转化的场景的情况。比如,做短期的促销,就打了两天的广告,那么这两天的广告理应获得较高的权重
位置归因模型
基于位置的归因模型,也叫U型归因模型,它综合了首次归因、末次归因、线性归因,将第一次和最后一次触点各贡献40%,中间的所有触点平均剩下的20%贡献。
##优点 U型归因模型也是一种多触点归因模型,实质上是一种重视最初带来线索和最终促成成交渠道的模型,一般它会给首次和末次互动渠道各分配40%的权重,给中间的渠道分配20%的权重,也可以根据实际情况来调整这里的比例 ##缺点 该模型的缺点则是它不会考虑线索转化之后的触点的营销效果,而这也使得它成为销售线索报告或者只有销售线索阶段目标的营销组织的理想归因模型 ##适用场景 U型归因模型非常适合那些十分重视线索来源和促成销售渠道的公司。
自定义模型
你可以根据自己对于业务的理解,创建你自己的模型,让其具有更具体的业务性和目的性,并可将其来和其他默认模型做对比
##优点 在这种模式下,你可以使用线性归因、首次归因、末次归因、时间衰减归因,以及位置归因模型作为基准线,通过不断地测试,调整各个渠道的权重,最好的效果是,它可以个性化地评估当前的业务,并可以随着时间的推移进行优化 ##缺点 在没有先做一些测试之前不要直接使用自定义模型,不要仅靠经验判断哪些渠道的贡献可能更大,实际数据上的表现可能会有所差异,需要基于数据的测试来进行判断
归因时间段
在实现归因分析之前。先再理一下归因分析的几个要素:目标事件,待归因事件,归因模型以及归因时间段。在上边还未提到的是归因时间段,也就是说我们选择目标事件多久之前的待归因事件拿来分析贡献。这里的多久就是我们要限制的归因时间段或者叫窗口期。因为很久很久之前如果有发生过某个广告位浏览,对目标事件的影响其实是微乎其微的,用户一般可能早已忘记之前曾经浏览的内容,而且用户的决策周期和购买周期一般也不必是几个月,如果几个月都没有购买或者做某事,可能当时已经买过了,本次再次发生购买(目标事件),可能已经是新的需求了。一般窗口期定义多久呢。比如7天、30天、90天、180天等,主要是为了规避掉一些时间上的干扰因素,具体我们还是要根据业务场景和分析需求而定,用户大致会在多长时间内做决策。可以分析通过分析用户的需求间隔等等。
归因分析sql实现
在说到在有行为序列时,如何实现归因分析。我们还是默认会有一张用户行为日志表。注:这里的SQL实现,绝不代表任何数据产品的底层技术,纯属个人兴趣。
假设我们定义:目标转化事件为:订单结果, 待归因事件为:运营位点击,搜索结果点击 归因时间段:1天 归因模型:首次归因("没有理由选择首次,仅做举例演示")
在进行归因分析时,各归因模型通用的计算逻辑:
1.首先找到时间范围内的目标事件。然后找每个目标事件往前推窗口期内的待归因事件。 2.对每个目标事件窗口期内的待归因事件按照时间进行排序。 3.对目标事件窗口期内的待归因事件,按照不同的分析模型规则,设置权重。
首次归因
:按上述1,2步骤后找到每个目标事件窗口期内的待归因事件并根据时间升序排序,首个事件的作用最强。筛选出首个事件即为贡献最大的事件称为功劳事件,而后统计功劳事件的贡献次数,人数,贡献总和,即为不同待归因事件贡献情况。具体如下:
##首次归因 select c.e2,count(distinct c.u1) as renshu,count(c.u1) as gongxian_cishu,sum(mm) as gongxian_money from (select a.user_id as u1,a.time as t1,a.event as e1,a.mm, b.event as e2,b.time as t2,rank() over (partition by a.user_id,a.time order by a.user_id,b.time asc) as rk from (select user_id,event,date,time,total_price_of_commodity as mm from events where event='PayOrderDetail' and date>='2020-09-24' and date<='2020-09-30')a left join (select user_id,event,time from events where (event='BannerClick' or event='SearchResultClick') and date>='2020-09-22'and date<='2020-09-30')b on a.user_id=b.user_id and b.time>date_sub(a.time, interval 1 day) and b.time<=a.time)c where c.rk=1 group by c.e2
末次归因
:按上述1,2步骤后找到每个目标事件窗口期内的待归因事件并根据时间降序排序,首个事件的作用最强。筛选出首个事件即为贡献最大的事件称为功劳事件,而后统计功劳事件的贡献次数,人数,贡献总和,即为不同待归因事件贡献情况。具体如下:
##末次归因 select c.e2,count(distinct c.u1) as renshu,count(c.u1) as gongxian_cishu,sum(mm) as gongxian_money from (select a.user_id as u1,a.time as t1,a.event as e1,a.mm, b.event as e2,b.time as t2,rank() over (partition by a.user_id,a.time order by a.user_id,b.time desc) as rk from (select user_id,event,date,time,total_price_of_commodity as mm from events where event='PayOrderDetail' and date>='2020-09-24' and date<='2020-09-30')a left join (select user_id,event,time from events where (event='BannerClick' or event='SearchResultClick') and date>='2020-09-22'and date<='2020-09-30')b on a.user_id=b.user_id and b.time>date_sub(a.time, interval 1 day) and b.time<=a.time)c where c.rk=1 group by c.e2
线性归因
:当线性归因时,按上述1,2步骤后找到每个目标事件窗口期内的待归因事件并根据时间升序排序,计算链路上的总数量,并平均分配链路上每个事件的贡献比例,则同时可计算链路上每个事件平均贡献的总金额。最终统计所有目标事件的链路情况,可得可得不同待归因事件对目标事件的总体贡献情况,包括贡献人数,贡献次数,贡献金额。
##线性归因 select d.e2,count(distinct d.u1) as renshu,sum(d.quanzhong) as gongxian_cishu,sum(d.mm*quanzhong) as gongxian_money from (select c.u1,c.t1,c.e1,c.mm, c.e2,c.t2, 1/cn as quanzhong from (select a.user_id as u1,a.time as t1,a.event as e1,a.mm, b.event as e2,b.time as t2, count() over (partition by a.user_id,a.time) as cn, rank() over (partition by a.user_id,a.time order by a.user_id,b.time asc) as rk1, rank() over (partition by a.user_id,a.time order by a.user_id,b.time desc) as rk2 from (select user_id,event,date,time,total_price_of_commodity as mm from events where event='PayOrderDetail' and date>='2020-09-24' and date<='2020-09-30')a left join (select user_id,event,time from events where (event='BannerClick' or event='SearchResultClick') and date>='2020-09-22'and date<='2020-09-30')b on a.user_id=b.user_id and b.time>date_sub(a.time, interval 1 day) and b.time<=a.time )c )d group by d.e2
位置归因
:当位置归因时,首先找到每个待归因事件窗口期内的待归因事件并进行升序排序。然后对首尾事件各分配40%,计算链路上的总数量,并将剩余的20%平均分配给链路上其他位置每个事件。根据所有目标事件的链路情况,可得不同待归因事件对目标事件的总体贡献情况,包括贡献人数,贡献次数,贡献金额。代码如下:
##位置归因 select d.e2,count(distinct d.u1) as renshu, sum(d.quanzhong) as cishu,sum(d.mm*d.quanzhong) as gongxian_money from (select c.u1,c.t1,c.mm,c.e1,c.e2,c.t2, (case when cn=1 then 1 When cn=2 then 0.5 when cn>2 and (rk1=1 or rk2=1) then 0.4 when cn>2 and (rk1>1 and rk2>1) then 0.2/(cn-2) else 0 end )as quanzhong from (select a.user_id as u1,a.time as t1,a.event as e1,a.mm, b.event as e2,b.time as t2, count() over (partition by a.user_id,a.time) as cn, rank() over (partition by a.user_id,a.time order by a.user_id,b.time asc) as rk1, rank() over (partition by a.user_id,a.time order by a.user_id,b.time asc) as rk2 from (select user_id,event,date,time,total_price_of_commodity as mm from events where event='PayOrderDetail' and date>='2020-09-24' and date<='2020-09-30')a left join (select user_id,event,time from events where (event='BannerClick' or event='SearchResultClick') and date>='2020-09-22'and date<='2020-09-30')b on a.user_id=b.user_id and b.time>date_sub(a.time, interval 1 day) and b.time<=a.time)c )d group by d.e2
路径归因
:
店铺归因
通过寻找到店前的最后一步的路径来进行归因,从此来计算每个页面的贡献。计算过程中涉及直接引导和间接引导的链路区别。
场景一:归因路径:首页-频道页1-频道页2-频道页3-进店(首页、频道页1、频道页2是间接引导,频道页3是直接引导)
场景二:归因路径:首页-频道页1-频道页2-进店(首页、频道页1是间接引导,频道页2是直接引导,频道3没有引导)
订单归因
订单归因是基于到店归因的基础之上,寻找距离最终下单行为时间上最近的一次到店链路,作为该订单的归因链路。一个订单只有一条归因链路,一个直接引导页面,N个间接引导页面。
shopC的归因路径:直接引导订单归因入口为搜索,且链路上的页面都会匹配上order_id(搜索时间最接近下单行为时间)。
step1 抽取进店动作 step2 关联进店链路 step3 过滤循环链路 step4 取最新链路 step5 生成直接/间接引导标识 step6 生成店铺归因表 step7 生成订单归因表
step1 抽取进店动作
还记得咱们流量域有一张用户pv表:dwd_bdcz_log_app_pv_di,我们从这个表里面抽取进店记录
insert overwrite table dwd_bdcz_log_app_pv_di_01 partition(partition_date=20220101) select shop_id, uuion_id, session_id, page_id, visit_time from (select shop_id, uuion_id, session_id, page_id, visit_time, row_number() over(partition by shop_id,uuion_id,session_id,page_id order by visit_time asc) as visit_num from dwd_bdcz_log_app_pv_di where partition_date=20220101 and page_type='shop_pv' and event_type='page' ) shop_pv_detail where visit_num=1 -- 取当天第一次进店操作
step2 关联进店链路
将进店之前的页面访问都挂上进店标识,通过页面访问时间<进店时间来判断
insert overwrite table dwd_bdcz_log_app_pv_di_02 partition(partition_date=20220101) select shop_id, shop_page_id, shop_visit_time , uuion_id, session_id, page_id, visit_time, row_number() over(partition by shop_id,shop_page_id,uuion_id,session_id,page_id order by visit_time desc) as page_last_num from ( select shop_pv.shop_id, shop_pv.page_id as shop_page_id, pv_detail.visit_time as shop_visit_time , pv_detail.uuion_id, pv_detail.session_id, pv_detail.page_id, pv_detail.visit_time from (select * from dwd_bdcz_log_app_pv_di_01 where partition_date=20220101 ) shop_pv innser join (select * from dwd_bdcz_log_app_pv_di where partition_date=20220101 ) pv_detail on shop_pv.uuion_id = pv_detail.uuion_id and shop_pv.session_id = pv_detail.session_id and shop_pv.visit_time > pv_detail.visit_time -- 这个很关键1对多关联,把店铺行为挂到每一个之前的动作里面 union all -- 合并一份店铺本身的行为 select shop_id, page_id as shop_page_id, visit_time as shop_visit_time , uuion_id, session_id, page_id, visit_time from dwd_bdcz_log_app_pv_di_01 where partition_date=20220101 ) t
step3 过滤循环链路
最麻烦的地方来了,这个地方可能不太好理解,我们需要使用一个技巧,如果某个页面的操作时间是在另一个页面多次操作时间之间,那么这个页面记录就给剔除。这句话多读几遍哈。
insert overwrite table dwd_bdcz_log_app_pv_di_03 partition(partition_date=20220101) select shop_id, shop_page_id, shop_visit_time , uuion_id, session_id, page_id, visit_time, page_last_num, -- 下面这个排序很关键,是用来对页面去重的 row_number() over(partition by shop_id,shop_page_id,uuion_id,session_id,page_id order by visit_time asc) as page_first_num from (select * from dwd_bdcz_log_app_pv_di_02 where partition_date=20220101 ) shop_pv left join ( select shop_id, shop_page_id, shop_visit_time , uuion_id, session_id, page_id from (select shop_id, shop_page_id, shop_visit_time , uuion_id, session_id, page_id, visit_time from dwd_bdcz_log_app_pv_di_02 where partition_date=20220101 ) t1 inner join (select shop_id, shop_page_id, uuion_id, session_id, page_id, max(visit_time) as max_visit_time, min(visit_time) as min_visit_time, from dwd_bdcz_log_app_pv_di_02 where partition_date=20220101 group by shop_id,shop_page_id,uuion_id,page_id,session_id ) t2 on t1.shop_id = t2.shop_id and t1.shop_page_id = t2.shop_page_id and t1.uuion_id= t2.uuion_id and t1.session_id= t2.session_id where t1.visit_time < t2.max_visit_time and t1.visit_time > t2.min_visit_time --如果某个页面的操作时间是在另一个页面多次操作时间之间,那么这个页面记录就给剔除 ) filter_page -- 过滤循环页面 on shop_pv.shop_id = filter_page.shop_id and shop_pv.shop_page_id = filter_page.shop_page_id and shop_pv.uuion_id= filter_page.uuion_id and shop_pv.session_id= filter_page.session_id and shop_pv.visit_time = filter_page.visit_time where filter_page.page_id is null;
step4 取最新链路
这个比较简单,取每个页面的第一次访问作为路径
insert overwrite table dwd_bdcz_log_app_pv_di_04 partition(partition_date=20220101) select shop_id, shop_page_id, shop_visit_time , uuion_id, session_id, page_id, visit_time, page_last_num, -- 用户访问路径,用来计算引导标识 row_number() over(partition by shop_id,shop_page_id,uuion_id,session_idorder by visit_time desc) as visit_step from dwd_bdcz_log_app_pv_di_03 where partition_date=20220101 and page_first_num=1
step5 生成直接/间接引导标识
进入店铺页的最近一次页面是直接引导,其他是间接引导
insert overwrite table dwd_bdcz_log_app_pv_di_5 partition(partition_date=20220101) select shop_id, shop_page_id, shop_visit_time , uuion_id, session_id, page_id, visit_time, page_last_num, case when visit_step=1 then '店铺页' when visit_step=2 then '直接引导页' else '间接引导页' end as direct_type from dwd_bdcz_log_app_pv_di_04 where partition_date=20220101 and page_first_num
step6 生成店铺归因表
通过上面5步的操作之后我们已经得到了完整的进店归因链路数据了,但是我们实际场景中也比较关心某些模块和入口的归因,这时候需要我们关联入口维度表或者模块维度表来把这些东西打到明细数据里面去。
insert overwrite table dwd_bdcz_log_app_shop_pv_di partition(partition_date=20220101) select shop_id, shop_page_id, shop_visit_time , uuion_id, session_id, a.page_id, visit_time, page_last_num, direct_type, b.entry_id, b.entry_name, b.module_id, b.module_name, from dwd_bdcz_log_app_pv_di_5 a left join dim_log_page_info b on a.page_id = b.page_id where a.partition_date=20220101
这里简化了维度信息的获取,实时场景会比这里辅助一些,但是尽量不要使用硬编码的方式生成入口或者模块信息,尽量~
step7 生成订单归因表
店铺归因得到之后,我们只需要将订单表和店铺归因表关联就可以得到订单的归因数据
insert overwrite table dwd_bdcz_log_app_order_di partition(partition_date=20220101) select order_id, union_id, shop_id, session_id, shop_page_id, page_id from (select a.order_id, a.union_id, b.shop_id, b.session_id, b.shop_page_id, b.page_id, row_number() over(partition by order_id order by b.visit_time desc) as rank from (select * from dwd_bdcz_order_di where partition_date=20220101 ) a LEFT JOIN (select * from dwd_bdcz_log_app_shop_pv_di where partition_date=20220101 ) b on a.shop_id = b.shop_id and a.union_id = b.union_id and a.order_time > b.visit_time -- 进店之后的下单 ) result where rank=1
如何选择归因模型?
上面这么多种归因模型大概可以分成2类:
基于规则: 预先为渠道设置了固定的权重值,好处是计算简单、数据容易合并、渠道之间互不影响,当然你也可以根据实际需要去调整他们的权重配比 基于算法: 每个渠道的权重值不一样,会根据算法和时间,不同渠道的权重值会发生变化(数据驱动)
如何选择对应的归因模型呢?
在选择用何种归因模型之前,应该先想清楚业务模式: 如果是新品牌、新产品推广,企业应该给予能给我们带来更多新用户的渠道足够的权重,那么我们应该选择首次互动模型 如果是投放了单一的竞价渠道,那么我们应该选取末次互动归因模型或者渠道互动归因模型; 如果公司很在乎线索来源和促成销售渠道,那么我们应该选择U型归因模型 如果公司的渠道多、数据量大,并且由永久用户标识,基于算法的归因模型能够为营销分析提供巨大的帮助
资料来源
http://docs.zhugeio.com/advancedguide/attribution.html https://mp.weixin.qq.com/s/DVjPUo2ysC0JF7Xd28ji5A