广告系统设计与规划

广告系统设计与规划
MeteorCat这篇专题也是总结工作这么多年的对于广告投放业务的积累, 也是方便后来的开发人员做借鉴处理
首选需要明确目前国内提到的 广告 业务实际上有两种概念(很多人都被混淆起来)
-
Marketing(投放买量): 广点通/巨量等广告平台业务, 主要负责投放平台的广告获取点击和流量转化, 本质是买量获客 -
Advertising(广告变现): 硬核渠道等广告展示业务, 利用应用内部的广告位展示获取对应收入, 本质是通过曝光流量变现
| 维度 | 投放买量 | 广告变现 |
|---|---|---|
| 资金流向 | 作为公司主体(我们)付费给广告平台(广点通/巨量) | 不同平台下的广告主付费, 公司主体(我们)拉取点击转化用户来赚取广告分成 |
| 服务对象 | 拉新/促活/付费转化 | 商业化的流量变现 |
| 核心指标 | 消耗/曝光/点击/CTR/CPC/激活成本/ROI | 广告填充率/eCPM/广告展示量/广告收入/LTV |
| 对接对象 | 广告投放平台API | 广告聚合/渠道SDK |
| 参考平台 | 广点通/巨量/GoogleAds等广告平台 | Vivo/Huawei/XiaoMi等应用商店(硬核渠道) |
所以在很多情况下, 需要结合情况分清楚提问的人嘴里关于 广告 的概念是哪方面, 才能结合整体思路去处理
日常开发之中, 投放买量和广告变现也不建议直接作为后台入口归类, 主要问题有以下方面
-
资金流向相反, 结算和对账逻辑完全独立(投放是要买平台量, 变现是需要结算收入)
-
统计指标不同, 两者核心的统计指标完全不一样, 不建议归类在相同入口处理
另外需要区分游戏联运聚合关系, 很多这类系统开发很喜欢将游戏聚合联运系统和广告平台耦合在一起, 方便把联运系统当中游戏应用作为主体分配
之前接触过部分项目, 把联运游戏内部的游戏应用复用成广告主体对象, 后续要做单独主体抽离出来作为对外开放广告平台时代码逻辑全粘合而无法抽离
无论 广告变现 还是 投放买量, 都遵循以下生命周期(也可以称为 归因链路)
广告展示 → 用户观看 → 点击触发 → 安装下载 → 激活设备 → 账号生成 → 玩家付费(广告变现不需要)
只是两者的最终诉求是不一样:
-
投放买量需要从点击/安装/激活到付费全程参与归因核算(玩家付费是核心终点指标) -
广告变现需要链路仅前半段作为收益结算依据, 末端付费环节不参与广告收益计算(只关注有效点击从而调整广告位下发策略)
这里主要讲解 广告变现 部分功能, 需要说明这部分涉及到 客户端/服务端 部分, 并且还涉及到 应用分包 和 链路追踪
客户端对接
首先服务端将会提供客户端以下接口, 方便做前置对接
-
广告初始化: 当用户首次启动之后, 客户端搜集客户端信息(主要是IMEI信息), 服务端接受首次启动则代表
激活链路 -
广告上报事件: 用于广告事件埋点上报, 方便确认广告API初始化是否有异常, 主要提交广告的
状态/错误码/错误信息/IMEI来分析情况 -
广告下发配置: 对应广告展示位和概率配置, 部分广告展示需要针对地区和用户做动态调整热门策略(识别IP为部分城市提高广告概率)
广告初始化
一般的初始化相对来说需要提交和下发的东西比较多点, 并且切前后台不需要重复发起请求, 只需要 进程冷启动 的时候请求来做设备信息收集
| 字段 | 类型 | 说明 |
|---|---|---|
imei |
string | 设备唯一标识码, 原来 imei 已经淘汰, 现在只是沿用该名称作为唯一标识 |
source |
string | 第三方来源SDK标识, 比如 vivo/huawei/honer 等通用渠道标识 |
version |
string | 应用版本号, 用来出现错误分析是否为版本兼容问题 |
channel |
string | 子渠道标识, 用于细分自身平台的应用分包渠道标识(需要在后台做应用按反编译来注入渠道标识重新打包), 也是归因核心字段 |
os |
string | 系统: Window/Android/iOS/HarmonyOS/WeChat |
device |
string | 手机机型, 一般客户端都有接口获取具体内容, 比如 iPhone17 等设备型号 |
network |
string | 网络类型: wifi/4g/5g 等 |
session |
string | 应用会话标识, 需要客户端在进程启动(进程完全杀死后重新打开时候也需要), 生成 UUID 等代表当前启动会话任务唯一性(本地内存生成而不需要持久化保存), 切后台/切前台/弹窗/页面跳转不重新生成而去复用当前会话 id |
响应的话不需要带什么数据, 只需要客户端确定提交成即可, 大部分情况只需要 HTTP_STATUS = 200 就代表没问题, 不过这里推荐响应以下结构
1 | { |
这里其实还有个决策点, 就是 初始化直接是要直接下发广告策略, 还是抽离另外接口请求获取广告策略?, 考虑的点有如下方面
-
初始化下发广告展示策略: 可以节约请求成本(HTTP请求只有一次), 有效降低接口并发(但响应太多会导致网路不好时候卡顿)
-
广告策略采用单独接口: 职责抽离(初始化应该做初始化的事情), 可以利用部分手段从服务端动态通知重新拉取广告策略(灵活调整)
广告埋点上报
一般事件的上报结构比较简单, 大部分情况只需要将以下内容上报给服务端
| 字段名 | 类型 | 说明 |
|---|---|---|
event |
number | 广告事件枚举, 用于确认埋点行为, 比如初始化/加载/曝光/点击/奖励发放/失败/关闭等事件情况 |
imei |
string | 设备唯一标识码, 原来 imei 已经淘汰, 现在只是沿用该名称作为唯一标识 |
source |
string | 第三方来源SDK标识, 比如 vivo/huawei/honer 等通用渠道标识 |
version |
string | 应用版本号, 用来出现错误分析是否为版本兼容问题 |
channel |
string | 子渠道标识, 用于细分自身平台的应用分包渠道标识(需要在后台做应用按反编译来注入渠道标识重新打包), 也是归因核心字段 |
slot_id |
string | 广告的位置ID, 区分广告展示类型, 比如开屏/Bannner/插屏/原生/激励广告等 |
os |
string | 系统: Window/Android/iOS/HarmonyOS/WeChat |
device |
string | 手机机型, 一般客户端都有接口获取具体内容, 比如 iPhone17 等设备型号 |
state |
number | 细分场景的事件调用状态, 比如正常应该是完整正常展示广告, 还有展示中途被用户切后台中断/页面渲染失败黑屏等意外情况 |
error |
number | 第三方广告SDK调用错误码, 跟随第三方SDK错误码返回上报 |
message |
string | 第三方SDK调用异常附加的消息 |
session |
string | 应用会话标识, 需要客户端在进程启动(进程完全杀死后重新打开时候也需要), 生成 UUID 等代表当前启动会话任务唯一性(本地内存生成而不需要持久化保存), 切后台/切前台/弹窗/页面跳转不重新生成而去复用当前会话 id |
依靠这份上报数据就能实现以下归因功能
-
排查异常: 依靠
source + slot_id + error + message + version锁定应用版本和异常广告 -
还原操作:依靠
imei + session + timestamp的多条信息就可以模拟用户在同一次启动触发流程 -
精细统计: 依靠
channel + slot_id + event就能计算曝光/点击/填充率/eCPM等核心指标 -
行为分析: 依靠
state统计广告中途退出和播放不完整等流失场景从而做优化
响应的话不需要带什么数据, 只需要客户端确定提交成即可, 大部分情况只需要 HTTP_STATUS = 200 就代表没问题, 所以简单点即可
1 | { |
广告下发配置
用来下发第三方广告策略配置, 提供广告的开关设置/展示概率/厂商渠道优先级/单会话限流/地域倍率等规则, 具体请求参数如下
| 字段名 | 类型 | 说明 |
|---|---|---|
imei |
string | 设备唯一标识码, 原来 imei 已经淘汰, 现在只是沿用该名称作为唯一标识 |
source |
string | 第三方来源SDK标识, 比如 vivo/huawei/honer 等通用渠道标识 |
version |
string | 应用版本号, 用来出现错误分析是否为版本兼容问题 |
channel |
string | 子渠道标识, 用于细分自身平台的应用分包渠道标识(需要在后台做应用按反编译来注入渠道标识重新打包), 也是归因核心字段 |
os |
string | 系统: Window/Android/iOS/HarmonyOS/WeChat |
device |
string | 手机机型, 一般客户端都有接口获取具体内容, 比如 iPhone17 等设备型号 |
network |
string | 网络类型: wifi/4g/5g 等 |
session |
string | 应用会话标识, 需要客户端在进程启动(进程完全杀死后重新打开时候也需要), 生成 UUID 等代表当前启动会话任务唯一性(本地内存生成而不需要持久化保存), 切后台/切前台/弹窗/页面跳转不重新生成而去复用当前会话 id |
这里响应的数据结构就需要着重来说明, 这里推荐采用以下数据格式
1 | { |
这里广告展示的核心字段就是 rate 和 prob, 按照规则抽取指定广告展示? 其实公式很简单:
1 | 最终展示概率 = prob * rate |
计算结果会出现两种情况:
-
计算值 ≤ 1.0: 直接使用该数值作为随机判定阈值 -
计算值 > 1.0: 统一按 1.0 处理 = 100% 必触发展示
假定 prob=0.9, rate=1.3, value=1.17, 代表该广告只要没有到达 session_max(广告弹出上限), 本次 session 是必定弹出的广告
一般 rate > 1.0 基本是热门地区, 所以广告展示可以相对多触发展示下(要留意过多弹窗导致被拉黑甚至封号)
而对于冷门地区则需要多加次随机浮点数过程来处理
1 | 假设: 广告位基础 prob=0.9, 服务端通过IP识别的倍率 rate=0.4 |
这里就是服务端和客户端的大致对接流程规则, 之后就是服务端需要设计和开发业务功能
服务端设计
对于服务端来说肩负的任务可能比较多, 因为会涉及以下方面处理
-
管理后台
-
渠道打包
-
CDN部署
而应用表需要单独设计规划, 将母包所需的打包对应参数记录在一起, 母包就是对接自有SDK方便反编译重新打包的 APK, 首先设计数据应用表
1 | # 首先是通用的单一用数据应用表 |



