做Android变现的,迟早都得面对一个问题:单靠自己那一个广告网络,收益天花板太明显了。同一批用户,在不同广告主眼里价值是完全不一样的,有的渠道只愿意给你0.5美元eCPM,换一个渠道可能就是2美元。这意味着什么?你只接一家SDK,等于把用户价值里最肥的那块肉白白扔掉了。AdMob聚合变现体系解决的核心问题,就是用一个统一入口把多家广告网络串起来,让它们互相竞价、按规则补位,最后在同一个广告位上拿到最优收益。
这篇文章我打算从体系设计、核心机制、Android工程接入、线上问题排查到变现调优,把我自己这些年做聚合变现的实操经验完整梳理一遍。不管你是刚接广告的小白,还是已经被eCPM折磨了一段时日的开发者,这篇应该都能给你省下不少摸索的弯路。
1. 变现体系整体规划:为什么广告聚合是 Android 开发者的必修课
1.1 单一广告网络的天花板与聚合的意义
很多刚入行的朋友会有一个错觉:广告变现嘛,找个大平台接上,然后躺着看后台数字涨就行。真要是这么简单,就不会有"变现经理"这个岗位了。单一广告网络的问题在于,它的请求量、出价策略、广告主预算都是内部闭环的。打个比方,你手里有一批18到25岁、偏爱游戏类的用户,Unity Ads那边可能出价很高,但AdMob这边因为广告主结构不同,只给到一个基础价。如果你只接AdMob,这部分溢价你永远吃不到。
聚合的意义就是打破这个闭环。一个广告位发一次请求,聚合层同时问好几家广告网络:你出多少钱?谁出得高谁展示。这带来的不只是eCPM提升,还有填充率提升——AdMob没广告的时候,AppLovin可能正好有空位能接住,用户不至于看到一个空白位。
1.2 AdMob聚合体系的核心组成
一套完整的AdMob聚合体系,说白了由这几个部分组成:
- AdMob聚合SDK(即
play-services-ads,也就是Google Mobile Ads SDK) - 各广告网络自己的SDK(AppLovin、Mintegral、Unity Ads、ironSource等等,按你的需求选择)
- 这些广告网络对应的Adapter(适配器,负责把广告网络SDK桥接到AdMob聚合层)
- AdMob后台的中介(Mediation)配置:创建中介组、添加广告源、设置竞价或瀑布流
- 收益报表与监控:AdMob后台的报告、eCPM数据、实时出价统计
这里面最容易被人忽略的是Adapter。很多人以为把两家广告网络SDK都加进工程就算聚合完成了,结果后台配置死活不生效,或者一启动就崩溃,十有八九就是Adapter的版本没对齐。
1.3 方案选型:AdMob Mediation vs 自研聚合 vs 第三方聚合
在定方案的时候,很多团队纠结过:是自己写一套聚合,还是用AdMob自带的中介,还是接第三方聚合平台?我的建议很清楚——没有特殊需求,直接用AdMob Mediation。
自研聚合听起来很美,无非是发多个SDK的请求,取回调快的。但真做起来,你要处理各家SDK的初始化、生命周期、超时、广告对象缓存、崩溃隔离,工作量堪比在现有SDK体系上再开发一个系统。除非你是百万日活以上的产品,专门养了一个变现团队,否则这个投入产出比极低。
第三方聚合平台(比如曾经的MAX、ironSource这类)确实在功能上很能打,但它们等于在你和AdMob之间多了一层中间商,而且它们多多少少有自己的广告网络要推,在公平性上天然打折扣。AdMob Mediation的好处是,它本身就是Google的变现产品,在自家SDK上跑聚合,稳定性和透明度都更有保障,市面上主流广告网络也都支持。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心机制拆解:Waterfall、Open Bidding 与 eCPM
2.1 eCPM 与填充率:变现的两个基本盘
聊聚合必须先把两个词吃透:eCPM和填充率。eCPM全称是Effective Cost Per Mille,指每千次展示的有效收益,计算公式是:eCPM =(预估收益 / 展示次数)× 1000。注意,这个值是动态的,取决于广告主对当前用户、当前广告位、当前时段的出价,不是广告网络死定一个数给你。
填充率(Fill Rate)则是有广告返回的次数占总请求次数的比例。填充率低,你连展示机会都没有,eCPM再高也是空谈。这两个指标一个管赚多少,一个管能不能赚,聚合的价值就是在两者之间找到平衡:通过多家网络补位把填充率拉满,通过竞价把eCPM拉到当前用户能拿到的最高档。所以你在看聚合配置的时候,永远不要单看某一家的单价,要看整体组合后的混合eCPM和整体填充率。
2.2 Waterfall 的排序逻辑和它的硬伤
Waterfall是早期聚合的经典方案,也叫瀑布流。它的逻辑很简单:预先给各个广告源排好序,价值高的放上面,价值低的放下面。请求来的时候,先问最上面的广告源,没广告就往下滑一层,直到有广告返回。
听起来挺合理,但它有几个硬伤。第一,排序是静态的,你上周看到的eCPM和这周可能完全不一样,广告主预算一波动,原来排第一的可能这周已经掉到第三了,而你还在按旧顺序发请求,白白浪费了高价值机会。第二,每一层网络都有响应时间,从上往下逐层请求,等最终拿到广告,用户可能已经退出页面了,这直接拉低展示率。第三,配置维护成本很高,新接入一个广告网络,你得手动插到瀑布流的某个层级里,还得反复测试它真实的eCPM排位。
在实际操作中,我见过太多开发者把瀑布流配得很长,四五层以上,每次请求都要等好几个网络的超时时间,用户体验牺牲了不少,填充率确实高了,但展示率惨不忍睹,收益反而没上去。这是典型的"看似安全、实际亏损"方案。
2.3 Open Bidding 为什么是当前聚合的最优解
Open Bidding(公开竞价,AdMob里面叫"中介组"里的竞价广告源)就比较聪明了:一个广告请求进来,系统同时把所有支持竞价的广告网络都叫过来出价(Bidding),谁给的钱多谁展示,全部过程同步进行,不用一层一层挨个等。
这样一来,eCPM是真的被市场竞价拉起来的,而不是靠你手动排出来的;等待时间也大幅缩短,因为各网络同时响应,取最优价格的同时也保留了所有网络的候选;而且因为广告源之间互相竞争,广告网络为了拿到流量会不断提高出价,长期看对开发者是收益最大化的。
现在AdMob聚合的推荐做法就是Bidding为主、Waterfall兜底。你把能开Bidding的广告源都开成Bidding,实在支持不了的网络或者填充不稳定的,才放到Waterfall做补余。比如一个插屏广告位,我用两三个Bidding源做主战场,再用一个Waterfall源做保底,这样既保证充分竞争,又保证没广告的时候不至于空着一张脸。
2.4 广告源的选择与版本匹配原则
广告源不是接得越多越好。每接一个广告网络,你的App就多一个SDK依赖,包体积、初始化耗时、崩溃概率都会上升。我的经验是:先选两到三个和你用户画像匹配、eCPM高的Bidding源,再加一个到两个填充稳定的Waterfall源就够了。
这里有个关键点:任何广告网络SDK都有一个对应AdMob的Adapter版本,这个版本号和广告网络SDK自身的版本号通常是绑定的。你在 build.gradle 里写Adapter依赖的时候,它会在编译期拉取对应的广告网络SDK。一定要去AdMob官方文档查最新的版本兼容表,随意混搭会发生一些很诡异的崩溃,比如某个类方法在新SDK里被移除了,你以为是自己的代码问题,折腾半天才发现是Adapter版本太旧,和最新SDK不兼容。
3. Android 工程接入 AdMob 聚合的完整实操
3.1 准备工作:账号、应用与广告单元
开始写代码钱,先把账号和后台这摊事理清楚。注册AdMob账号,把App加入到AdMob后台,拿到一个唯一的App ID。然后在后台创建广告单元(Ad Unit),注意:每个广告格式(横幅、插屏、激励视频、开屏、原生)最好都建独立的广告单元,不要图省事一个广告位复用所有场景。为什么?因为后台报告是按广告单元维度统计的,所有场景混用一个ID,你根本分不清哪个入口收益高、哪个入口要优化,后期调优无从下手。
广告单元ID长这样:ca-app-pub-xxx/yyy。App ID则是另一个,记得在 AndroidManifest.xml 里配置:
xml复制<manifest>
<application>
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy" />
</application>
</manifest>
这个配置漏了的话,SDK初始化会直接报错退出,很坑,别问我怎么知道的。
3.2 在 Android Studio 中接入广告 SDK 与适配器依赖
在项目的 build.gradle(模块级别)里添加依赖。以我常用的一套为例:
gradle复制dependencies {
implementation 'com.google.android.gms:play-services-ads:23.2.0'
// 各个广告网络对应的 AdMob Adapter
implementation 'com.google.ads.mediation:applovin:12.4.1.0'
implementation 'com.google.ads.mediation:mintegral:16.7.11.0'
implementation 'com.google.ads.mediation:unity:4.11.1.0'
}
注意,这里的Adapter版本号就是上面说的那个匹配表,写的时候去官方文档确认一遍,别凭感觉填。Adapter会自动带上对应的广告网络SDK依赖,你不需要再手动写一份AppLovin SDK的依赖。如果你真手动写了,反而会搞出重复依赖冲突,有些网络SDK之间还会因为同名类库(尤其是共享的某些工具库)直接编译失败。
另外在 proguard-rules.pro 里面,最好按官方文档把各个广告网络需要的keep规则贴一下。不贴的后果是,release包在广告请求时直接静默失败,而debug包一切正常,排查起来让人抓狂。
3.3 SDK 初始化与广告加载
初始化放在Application里做,注意要异步回调,不要阻塞主线程:
java复制public class DemoApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
MobileAds.initialize(this, new OnInitializationCompleteListener() {
@Override
public void onInitializationComplete(InitializationStatus initializationStatus) {
// 这里可以拿到各个广告网络的初始化状态
}
});
}
}
初始化完成之后,就可以加载广告了。以激励视频为例:
java复制public class RewardedAdManager {
private RewardedAd mRewardedAd;
public void loadAd(Context context, String adUnitId) {
RewardedAd.load(context, adUnitId,
new AdRequest.Builder().build(),
new RewardedAdLoadCallback() {
@Override
public void onAdFailedToLoad(LoadAdError error) {
// 拿到 error 后要打日志,这里是排查问题的一手信息
}
@Override
public void onAdLoaded(RewardedAd rewardedAd) {
mRewardedAd = rewardedAd;
}
});
}
}
插屏和开屏的加载流程类似,都是先 load 再 show。注意一点:广告对象加载成功后,一定要控制展示超时。开屏广告尤其明显,用户从后台切回App的时候,如果开屏广告加载耗时超过3秒还没好,直接放弃展示,让用户直接进入主页面,否则用户等得不耐烦,流失率会升得很明显。
3.4 在 AdMob 后台完成聚合配置
代码侧的依赖接好之后,大头其实在AdMob后台。进入AdMob后台,找到"中介"标签页,创建一个中介组。这里选广告格式和广告单元,然后把各个广告源加进来。
后台配置的两种方式:公开竞价(Open Bidding) 和 瀑布流(Waterfall)。你要做的是先检查自己集成的广告网络是否支持竞价,支持的都加到Bidding组里;不支持的,创建瀑布流分组,按eCPM预估从高到低排序。
配置Bidding广告源时,一般只需要填一个你在该广告网络后台创建的应用ID和广告位ID。配置Waterfall广告源时,除了ID之外,还有几个字段要注意:一个是"广告源状态"(启用、暂停),还有一个是"底价(Floor Price)"。底价这个字段特别容易踩坑——你填了底价,如果该网络出价低于底价,它就会直接放弃填充;底价设得太高,填充率暴跌;设得太低,低质量的广告源把你高价位的Bidding结果给顶替掉,造成劣币驱逐良币。
后台保存生效通常需要几分钟,不要刚点完保存就立刻测,您等个五到十分钟再测,效果会稳一些。
3.5 测试广告与测试设备设置
测试这一环坚决不能省。AdMob对测试要求很严格,如果你在测试阶段就疯狂用真实广告请求,轻则账号被警告,重则被判定为无效流量,冻结收益。正确做法是在测试设备上开启测试模式。
两个方式:一是用AdMob提供的测试广告单元ID,这个直接在官方文档查,二是在代码里注册测试设备:
java复制List<String> testDeviceIds = Arrays.asList("YOUR_TEST_DEVICE_ID");
RequestConfiguration configuration =
new RequestConfiguration.Builder().setTestDeviceIds(testDeviceIds).build();
MobileAds.setRequestConfiguration(configuration);
测试设备ID哪来的?第一次发出真实请求时,logcat里会打印一行包含 Use RequestConfiguration.Builder.setTestDeviceIds 的日志,里面有当前设备的ID,复制过来就行。这样你在测试设备上请求到的都是测试广告,既不影响账号安全,也能完整地验证从聚合层到各网络Adapater的回调链路通没通。
4. 线上踩坑实录:常见问题与排查方法
4.1 判断聚合配置是否正常的三个指标
接入聚合之后,最怕的是自己看着后台觉得一切正常,实际上聚合根本没生效,所有广告都是AdMob自家在分发。要判断聚合是否真正跑了起来,第一看后台的"中介"报告,里面会有各个广告源的展示占比;第二看logcat里是否有Adapter相关的日志,比如AppLovin、Mintegral的Adapter成功初始化、广告加载成功的tag;第三看实际线上收益和eCPM是否有明显跃升。如果这三个指标里一个波动都没有,大概率你的配置还停留在"只是接入了SDK,没配聚合"的阶段。
这里多说一个容易被忽略的点:AdMob后台报告有延迟,通常今天的数据明天才完整呈现。不要因为上线当天报告里没有广告源数据就急着改配置,等24小时再看,这是我见过无数新人踩过的坑。
4.2 无填充、低填充的排查思路
广告一直加载不出来,或者某家网络一直显示0填充,我先说结论:八成是配置问题,不是市场问题。具体排查顺序按照下面这个路径来,能帮你少走很多弯路。
第一,检查广告网络后台的应用ID和广告位ID填没填对。别笑,这个问题在我接手过的项目里出现频率极高,很多广告网络的后台ID分为应用级和广告位级,位置都不同,很容易复制错或者复制串。第二,检查该网络SDK和Adapter的初始化状态。在 MobileAds.initialize 回调里打印 InitializationStatus,看对应网络是 READY 还是 ERROR,如果是ERROR,通常是SDK key没配置或者网络依赖缺失。第三,检查该网络后台是否创建了正确的广告位,很多广告网络(比如某些视频平台)的插屏广告位和激励视频广告位是分开的,你绑定错了格式,也是一直无填充。第四,查看logcat里有没有超时日志。某些网络因为你测试设备不在它的后台白名单,会直接拒绝请求,这个在后台的测试模式配置里解。
如果以上全部正常,再看是不是广告位设置里开了"儿童应用"等访客限制,一旦开了儿童导向设置,广告请求校验会非常严格,填充率自然受影响。
4.3 eCPM 波动与竞价失败的常见原因
不少朋友上线聚合后,发现eCPM比以前还低了,第一反应是"聚合骗人",其实未必。eCPM波动有几个常见原因:流量结构变了,比如这个月在某地区投放了大量买量,而该地区广告主出价本来就低,整体eCPM自然被拉下来;广告格式混在一起看,激励视频和插屏的eCPM差好几倍,你把它俩汇到一个报表里看平均,数字就失真了;节假日和广告主预算周期也有影响,每年有些季度是广告淡季,出价普遍走低。
竞价失败这块,如果某个Bidding广告源在报告中长期"无出价"或者"出价过低",你要么是没在该网络后台开启某地区的广告投放,要么是该网络的广告位和你的广告格式不搭,要么是后台对该网络设置的底价过高把它吓跑了。建议是先去掉该广告源的所有底价限制,让它裸跑几天看真实出价,再决定要不要加底价。
4.4 用 Logcat 与 API 快速定位聚合问题
真到了聚合加载不了、crash、或者展示回调不触发的场景,不要慌着反复查代码,先把问题半径缩小。开启 AdMob 的详细日志方式如下:
bash复制adb shell setprop log.tag.Google VERBOSE
adb shell setprop log.tag.Ads VERBOSE
adb shell setprop log.tag.GMA VERBOSE
然后在logcat里过滤关键字 Ads 和 GMA,能看到每个广告网络的加载状态、出价信息、失败原因。比如你看到 No ad config 或者 App ID not found,说明别查Adapter了,去看 AndroidManifest 里的 APPLICATION_ID 配没配。看到 Mediation No Fill from network,说明这个网络确实在某次请求里没返回广告,接下来再去查它的后台配置。
如果全链路日志都正常、但展示回调就是不触发,那十有八九是广告对象过期问题——AdMob返回的广告对象是有有效时长的,过了时间调用show会直接失败。解决办法是加载成功后按广告生命周期管理好,不要存全局变量一存就是一个小时,展示前做个时间戳校验,超时就重新加载。
5. 变现调优的几个关键操作
5.1 曝光频次控制:宁可少赚,不能把用户赶跑
很多新手接入聚合后疯狂展示广告,关键是连着弹好几个插屏给同一个用户,短期内收益可能好看,但用户留存掉得飞快,最终伤害的还是长期LTV。AdMob后台自带频次上限设置,可以按"每次展示间隔"和"每小时/每天展示次数"来控。我一般建议:插屏广告同一用户每小时最多展示1到2次,激励视频不要强制弹出,开屏广告展示失败不要憋着补展示。
另外,付费用户通通屏蔽广告是基本操作。你可以通过服务端接口下发开关,后端标记用户付费后,客户端直接不初始化或者不请求广告,省得用户一边付钱一边看广告,最后直接卸载。
5.2 广告位拆分的实战技巧
广告位拆分是整个变现体系里性价比最高、门槛最低的优化手段。同一个插屏广告,你在通关弹窗里和设置页面弹窗里,用户的付费意愿和广告价值是完全不同的。我的做法是:不同入口分别创建广告单元ID,这样在AdMob报告里就能看到每个入口的eCPM。过一段时间你会发现,有些入口的eCPM稳定高出一截,那就把优质入口的底价往上提一提;eCPM低的入口,就查一下是用户群体偏窄还是加载时机不好。
拆分的时候不要只按入口拆,还可以按用户画像拆。比如新用户和活跃老用户用不同广告位,新用户可以多看几次广告,因为他的留存不确定性高,短期的广告收益可能比指望他长期留存更划算;老用户则减少干扰,守护他的稳定性。这个策略需要在你自己的服务端做流量分组,AdMob后台建好多个广告单元,然后客户端根据后端下发的组别加载对应广告单元ID。
5.3 远程配置与 A/B 测试驱动的调优
调优不是拍脑袋,我强烈建议结合Remote Config做A/B测试。比如激励视频的奖励翻倍、插屏展示频率、开屏是否需要跳过按钮,这些都可以通过远程配置动态下发,然后按用户群组拆分验证。AdMob后台本身也有实验功能,但变不了你的产品逻辑,真正要联动产品策略的时候,还是得用Firebase Remote Config。
举个我实际跑过的例子:某游戏产品原本插屏广告在通关确认框弹出后立刻展示,转化收益不错但玩家流失率也高。我们通过Remote Config分了三组:A组保持现状,B组延后6秒展示,C组延后10秒展示。跑了一周之后,C组虽然eCPM略低,但次留和总收入都高于其他组。这些优化往往不会在纯广告后台里被发现,但效果比你在聚合里调十个底价参数都明显。
5.4 长期监控与收益报告解读
聚合上线后,每周固定时间看一次收益报告,记下几个核心数字:各广告位收入、eCPM、展示次数、填充率、各广告源的展示占比。连续看几周你就能摸清自己产品的变现基线,之后哪天哪个数字突然不对,你能立刻反应过来是流量问题还是广告源问题。
AdMob后台的"收益"页面可以按广告单元、国家/地区、广告源聚合,建议把不同维度都看一遍。收益下降的时候先定位是哪个地区跌了,还是哪个广告源没展示了,然后再针对性处理,不要一上来就胡乱加广告源或者调底价。记住一个原则:数据先定位,操作后验证,至少跟踪一周效果再下结论。
我在实际维护这套AdMob聚合变现体系的过程中,最大的体会是:聚合只是把"多卖几家的权利"交到你手里,真正让收益跑起来的,还是后台配置、数据分析和产品节奏这三件事的配合。每次调完底价或者广告源,至少观察三天再做下一步动作,别被单日波动牵着鼻子走。最后再分享一个小技巧:每次修改后台配置之前,先把当前各广告源的展示占比和eCPM截图留档,改完一周后拿出来对比,这样你才知道每一次调整到底改对了没有。
