广告归因-让你彻底弄归因架构实现

news2025/1/20 15:42:29
  • 这里会引用神策数据很多的介绍,然后进行总结

归因方法

  • 自归因
    • 渠道商帮我们做归因,有的是每个用户打开 app 都回传给渠道商,渠道商自己归因
    • 有的如华为是从应用商店安装时,应用商店把归因信息写入到 app, 然后首次安装启动时能从本地存储获取到归因数据
  • 曝光归因
    • 曝光归因由于有数据量极大、不会使用此项
  • 点击归因 (常用)
    • 所谓点击归因,就是点击广告之后首个转化,基本都是用这种方式归因

      归因模型

  • 末次归因模型 (常用,因为比较好实现)
    • 多个归因源事件时,认为最后一个归因源事件的功劳为 100%
  • 首次归因模型
    • 多个归因源事件时,认为第一个归因源事件的功劳为 100%。理由是第一个触点给用户建立了认知,与用户形成了连接。
  • 平均归因模型
    • 多个归因源事件时,认为每个归因源事件平均分配此次功劳。
  • 时间衰减归因模型
    • 加上了时间的影响因素,最后 1 次触达的贡献更高。
  • 位置归因模型
    • 多个归因源事件时,认为第一个归因源事件和最后一个归因源事件各占 40% 功劳,其余平分剩余的 20% 功劳。兼顾最初的线索和最终的决策。
  • 价值加权归因模型
    • 多个归因源事件时,对不同渠道的贡献价值进行加权,将转化功劳根据权重进行划分。

匹配方式

  • 精确匹配
    • OAIDOAID 全称是 Open Anonymous Device Identifier, 中文名是匿名设备标识符。 OAID 是一种非永久性设备标识符,最长 64 位,在系统首次启动的时候生成
    • AndroidIDANDROID_ID 是设备首次启动时由系统随机生成的一串 64 位的十六进制数字
    • IMEI: 国际移动设备识别码(International Mobile Equipment Identity,IMEI),即通常所说的手机序列号、手机 “串号”,用于在移动电话网络中识别每一部独立的手机等移动通信设备,相当于移动电话的身份证。
    • Mac: 手机的网卡地址
  • 模糊匹配
    • IP: 分配给用户上网使用的网际协议(全称 Internet Protocol, 简称 IP)的设备的数字标签
    • User_Agent: 一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等

      服务架构实现

  • 接下来会参考这个图来整体说明

根据上图,我们先给一个最基础的表结构,大家可以根据具体业务增减字段

# 应用表(apps)
id, appid(客户端使用), name, os, attribute_cycle_days(归因周期), attribute_white_list(JSON 白名单列表)
# 渠道表(channels)
id, name, template_query(此字段预先组装好格式)
# 监测链接表(links)
id, app_id, channel_id, channel_name(自定义渠道名), events(JSON 需要回传的事件, 方便后续动态增加回传事件), exp(有效期)
# 广告点击表:按天分表(click_logs)
id, appid, ad_name, [oaid, imei, android_id, mac, ip, ua](这些匹配方式看各自需要存储), exp, callback, data(JSON冗余字段), attributed_at(归因成功时间',')
# 归因成功日志表(这个表按各自日志需要设计)
# 回调日志表(这个表按各自日志需要设计)

根据时序图,来说明实际场景 (以下为伪代码,所有数据库查询自行做好缓存处理)

    1. 点击广告 (这一步是不需要我们处理的,用户点击广告的请求直达渠道商)
    1. 点击监测,渠道商会请求我们的监测链接
    • 监测链接说明
    • 由于每一家的参数不一样,我的建议是不要针对每一个渠道开发,而是应该适配一个通用的输入
    • 然后根据通用的输入,设计一个模板,这就是为什么要在渠道表加一个 template_query 字段的原因
    • 比如 oppo商店的格式是这样 ad_id=__ADID__&android_id=__ANDROIDID__&imei_md5=__IMEI__&oaid=__OAID__
    • 比如头条的格式是这样 ad_name=__AID_NAME__&android_md5=__ANDROIDID__&callback=__CALLBACK_PARAM__&idfa=__IDFA__&imei_md5=__IMEI__&ip=__IP__&mac_md5=__MAC1__&oaid=__OAID__&site=__CSITE__&ua=__UA__
    • 然后生成监测连接的时候,应该是生成像下面这样的
    • https://api.domain.com/api/v1/links/{id}/click_logs?ad_id=__ADID__&android_id=__ANDROIDID__&imei_md5=__IMEI__&oaid=__OAID__
    • 接口处理
    • 当请求到达 https://api.domain.com/api/v1/links/{id}/click_logs?ad_id=__ADID__&android_id=__ANDROIDID__&imei_md5=__IMEI__&oaid=__OAID__接口时
    • 参数中的宏会替换成实际点击用户的设备值,如:https://api.domain.com/api/v1/links/{id}/click_logs?ad_id=123456789&android_id=123456789&imei_md5=123456789&oaid=123456789
    • 接口伪代码:
// 统一的请求结构
class AdClickRequest { public $oaid;
 public $imei;
 public $imei_md5;
 public $andoird_md5;
 public $ad_name;
 public $callback;
 // xxx 更多字段
}

const FIELDS = ['oaid', 'imei', 'imei_md5', 'xxx'];
function clickLogs($id)
{
 // 1. 根据不同框架, 把数据解析到统一请求上
 $req = new AdClickRequest(); // 2. 查询监测链接表
 $link = "select * from links where id = {$id}"; // $id
 if (is_null($link)) { return 'FAIL'; } // 3. 写入点击日志表, 点击量大走队列插入
 $logModel = "insert into click_logs(`oaid`, `imei`, `events`, `exp`, 'xxx更多字段') values({$req->oaid}, {$req->imei}, {$link->events}, {$link->exp}, 'xxx更多字段')";
 // 4. 写入 redis $pipe = \Redis::pipeline();
 $value = $logModel . '.' . $logModel->id;
 foreach (FIELDS as $key) { $redisKey = sprintf('attributes:%d_%s', $link->app_id, $req->{$key});
 $pipe->set($redisKey, $value, $logModel->exp*60*60*24);
 } $pipe->exec();
     return 'OK';
}
    1. 用户首次打开 app 上报接口
class AppReportRequest { public $deviceKey;
 public $oaid;
 public $imei;
 public $mac;
 // xxx 更多字段
}
const FIELDS = ['oaid', 'imei', 'imei_md5', 'xxx'];function appReport($appId)
{
 // 0. 如果是 deepLink 拉起, 最好加一个延迟 10s 的队列归因, 防止`app`请求先于渠道商监测链接请求
 // 1. 根据不同框架, 把数据解析到统一请求上
 $req = new AppReportRequest(); // 2. 查询 app $app = "select * apps where id={$appId}";
 // 3. 查询 redis $pipe = \Redis::pipeline();
 $keys = []; foreach (FIELDS as $key) { $redisKey = sprintf('attributes:%d_%s', $app->app_id, $req->{$key});
 $keys[] = $redisKey; $pipe->get($redisKey);
 } // result 为一个数组, 如果匹配到了里面就是日志表的表名和主键
 $result = $pipe->exec();
 $value = collect($result)->filter()->first();
 if (is_null($value)) { return '归因失败';
 }
 $logModel = "select * from click_logs{$value->table} where id = {$value->id}";

 // 接下来可以用队列事件解耦之后的流程
 \Redis::set("attribute_devices:{$appId}_{$req->deviceKey}", $logModel, 60*60*24*7);
 // 存储归因成功日志表
 // 修改点击日志状态等等
 // 删除所有归因的 $keys, 防止重复归因
 // 根据 $app->attribute_cycle_days 设置归因周期

 return 'SUCCESS';}
  • 4.5.6. 这三步根据具体业务来实现即可

    1. 客户端事件回传
function appCallback($appId, $deviceKey)
{
 $logModel = \Redis::get("attribute_devices:{$appId}_{$deviceKey}");
 if (is_null($logModel)) { return 'FAIL'; } // 通过 $logModel->attributed_at 判断次留是否有效, 判断是否七日内付费    

 // 处理回传的逻辑
 return 'SUCCESS';}

客户端架构

  • 客户端应该尽量不要发起没必要的请求,减少服务器的压力
  • 比如播放回传的时候,不要每次都回传,应该用一下伪代码实现
// 假设这个是客户端的方法, 在需要打点的地方每次都调用这个方法
function eventReport(event) {
 // 从本地存储获取数据, 一定要存成 json 格式, 继续反序列化
 var data = storage.get('attribute_events');
 // 如果已经上报过了, 不要上报
 if (data[event]) {
 return; }
 // 上报接口
 var res = api.post('/api/v1/event_callback', '参数');
 if (res.code !== 200 || ! res.data.status) {
 return; }

  data[event] = true;
  storage.set('attribute_events', data);
}

// 归因上报的接口,
function attributeReport() {
 // 请求接口
 var res = api.post('/api/v1/attributes', '参数')
 if (res.code !== 200 || ! res.data.status) {
 return; }
 // 把整个事件缓存删除掉,这样子才能继续上报
  storage.delete('attribute_events');
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/161359.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【信息学CSP-J近16年历年真题64题】真题练习与解析 第12题之加工零件

加工零件 描述 凯凯的工厂正在有条不紊地生产一种神奇的零件,神奇的零件的生产过程自然也很神奇。工厂里有 𝑛 位工人,工人们从 1~𝑛编号。某些工人之间存在双向的零件传送带。保证每两名工人之间最多只存在一条传送带。 如果 𝑥 号工人想生产一个被加工到第 𝐿(…

回溯法--旅行售货员问题--排列树

回溯法有点类似于暴力枚举的搜索过程,回溯法的基本思想是按照深度优先搜索的策略,从根节点出发深度搜索解空间树,当搜索到某一节点时,如果该节点可能包含问题的解,则继续向下搜索;反之回溯到其祖先节点&…

【学习笔记】【Pytorch】六、nn.Module的使用

【学习笔记】【Pytorch】六、nn.Module的使用学习地址主要内容一、torch.nn模块概述二、nn.Module类的使用1.使用说明2.代码实现学习地址 PyTorch深度学习快速入门教程【小土堆】. 主要内容 一、torch.nn模块概述 概述:帮助程序员方便执行与神经网络相关的行为。…

微信小程序——WXSS模板样式,rpx,样式导入,全局样式和局部样式,全局配置-window

一.WXSS模板样式1.什么是 wxss WXSS ( WeiXin Style Sheets )是一套样式语言,用于美化 WXML 的组件样式,类似于网页开发中的CSS。2. WXSS 和 CSS 的关系WXSS 具有 CSS 大部分特性,同时, WXSS 还对 CSS 进行了扩充以及修…

73. 风格迁移以及代码实现

摄影爱好者也许接触过滤波器。它能改变照片的颜色风格,从而使风景照更加锐利或者令人像更加美白。但一个滤波器通常只能改变照片的某个方面。如果要照片达到理想中的风格,可能需要尝试大量不同的组合。这个过程的复杂程度不亚于模型调参。 本节将介绍如…

数据导入导出(POI以及easyExcel)

一.概念: 1.场景需求 将一些数据库信息导出为Excel表格 将Excel表格数据导入数据库 大量数据的导入导出操作 常⽤的解决⽅案为:Apache POI与阿⾥巴巴easyExcel2.Apache POI介绍 Apache POI 是基于Office Open XML 标准(OOXML)和M…

96、【树与二叉树】leetcode ——404. 左叶子之和:递归法[先序+后序]+迭代法[先序+层次](C++版本)

题目描述 原题链接:404. 左叶子之和 解题思路 一、递归法 (1)设置一个布尔变量判定(先序遍历) 左孩子一定在每个子树的最左侧,因此设置一个局部参数flag,当每次遍历的是左子树时&#xff0c…

记录一次Oracle Linux7上安装RDBMS 11.2.0.4的问题

参考文档: 文档1 OHASD fails to start on SuSE 11 SP2 on IBM: Linux on System z (Doc ID 1476511.1) As part of the root.sh, roothas.pl or rootcrs.pl is called and an entry is placed in /etc/inittab h1:35:respawn:/etc/init.d/init.ohasd run >/de…

cmake入门之二:调用外部共享库和头文件

cmake入门之二:调用外部共享库和头文件1.创建外部共享库1.1 创建相关文件或文件夹1.1.1 ext目录下的CMakeLists.txt1.1.2 ext目录lib文件夹下1.1.2.1 hello.h1.1.2.2 hello.c1.1.2.3 CMakeLists.txt1.2 编译、安装2.创建当前项目2.1 创建相关文件或文件夹2.1.1 proj…

为什么这么努力,还是赚不到钱?你不能不知道赚钱的三个模型

大部分人赚钱,都是通过能力努力运气,这种需要付出自己的大量时间和精力,并且赚到的钱也是有上限的。小部分人赚钱是通过,个人IP的商业模式来赚钱,并且跟我们传统的生意不一样的是,这个亏钱是有下限的&#…

OpenHarmony轻量级设备xts认证大致流程

因为最近公司在做openharmony开发板xts认证,这里对认证过程和过程中遇到的坑做下记录,也给大家探探路。 1. 开发板适配 OpenHarmony轻量系统的移植比较简单,代码中解耦做得非常好。从代码的设计理念上来看,移植主要是3部分的内容…

.vscode/extensions.json和setting.json 是项目用到的插件推荐列表和设置

文章目录前言一、extensions.json安装推荐插件编辑推荐插件二、setting.json总结前言 在前端项目,文件目录中存在.vscode文件夹,文件夹下一般存在两个文件extensions.json和setting.json。作用是保持所有开发者安装了相同的插件和相同的配置&#xff0c…

访问学者J1签证通常准备那些材料?

访问学者J1签证通常准备那些材料?知识人网小编马上整理一下分享出来作为参考:材料准备1、VISA部分:护照,护照照片,160确认页,签证费收据两联都带,DS2019,D7002,sevis费收…

Linux应用基础——监控与管理进程

目录 一、进程 1.定义 2.组成 3.进程环境包括 4.进程的生命周期 二、描述进程状态 三、相关命令 1.top命令 2.ps命令 二、中断进程 1.基本进程管理信号 2.每个信号的默认操作 3.相关命令 (1)kill命令 (2)killall命…

助力不文明行文识别,基于YOLOv7融合RepVGG的遛狗牵绳行为检测识别分析系统

不知道大家平时在路上走的时候或者在小区的时候有没有遇上过遛狗不牵绳子的行为,我在实际生活里面可是没少遇到过,有时候特别大的一只狗就这么冲过来,主人却还无动于衷,揍他的心都有了,这种行为的确是很不文明&#xf…

Java项目:仓库管理系统设计和实现(java+ssm+springboot+layui)

源码获取:博客首页 "资源" 里下载! 主要功能模块 1.用户模块管理:用户登录、用户注册、用户的查询、添加、删除操作、 2.客户信息管理:.客户列表的展示、添加、修改、删除操作、 3.供应商管理:供应商详情…

Android MVVM之ViewModel的详解与使用

一、介绍 ViewModel 类是一种业务逻辑或屏幕级状态容器。它用于将状态公开给界面,以及封装相关的业务逻辑。 它的主要优点是,它可以缓存状态,并可在配置更改后持久保留相应状态。这意味着在 activity 之间导航时或进行配置更改后(…

【UE4 第一人称射击游戏】45-使用线追踪进行破坏

上一篇:【UE4 第一人称射击游戏】44-瞄准时的武器线追踪步骤:打开“Weapon_Base”删除打印节点添加如下节点,表示追踪线命中目标时执行的逻辑对上面逻辑的解释:首先追踪线命中目标后,显示红色的那个准心然后让目标的健…

阿里云 - MaxCompute研究

一、官方介绍MaxCompute是适用于数据分析场景的企业级SaaS(Software as a Service)模式云数据仓库,提供离线和流式数据的接入,支持大规模数据计算及查询加速能力。MaxCompute适用于100 GB以上规模的存储及计算需求,最大…

全国青少年软件编程(Scratch)等级考试一级考试真题2022年12月——持续更新.....

1.小明想在开始表演之前向大家问好并做自我介绍,应运行下列哪个程序?( ) A. B. C. D. 正确答案:D 答案解析: 外观积木配合显示时间,才能看清楚内容。 2.舞台有两个不同的背景,小猫角色的哪个积木能够切换舞台背景?( ) A.<