主题
AdMix 策略配置格式说明
文档版本 v1.0.0
本页对应 SDK 1.0.0,与离线包内 docs/03-配置格式说明.md 是同一份内容。其他版本见文档中心。
本文面向运营 / 商务人员。调整广告位价格、平台顺序、开关某个广告源, 都只需修改这份 JSON 文件,不需要开发介入,也不需要 App 发版。
一、配置放在哪
有两种方式,可同时使用:
| 方式 | 位置 | 生效时机 | 说明 |
|---|---|---|---|
| 本地兜底 | App 内 assets/admix_config.json | 随版本 | 保证远端拉不到时仍能出广告 |
| 远端下发 | 平台管理后台发布 | 下次启动 | 改完不用发版 |
⚠️ 本地兜底那份只兜广告位策略,不带各平台的 appId。 appId 每个开发者都不一样,一旦随包发布,每接一个开发者就要重新打一个包。 代价是:用户装机后第一次打开 App 时,如果配置服务连一次都没拉通,这一次没有广告; 拉通过一次之后就会被记在本地,之后即使断网也照常出广告。
远端配置由 SDK 按 App 初始化时传入的 AppID 自动从平台服务拉取,开发同学不需要配置任何地址。
远端拉取失败会自动沿用本地配置,不会导致广告中断。
关于远端配置的生效方式,有三点值得知道:
- 删掉的东西会真的消失。 从远端配置里删掉一个广告位或一个广告源, App 下次启动后就不会再请求它。(此前有个缺陷:删掉的广告位端上还留着旧副本、 会继续请求已下线的广告位,现已修复。)
- 上次拉到的配置会被记住。 App 会把最近一次成功拉到的远端配置存在本地, 下次启动直接用它,而不是退回安装包里那份旧的。所以改完配置发布后, 用户下一次启动就是新配置,不会有"头几秒还在用老配置"的空窗。
- 没改动就不重复下载。 每次启动会问一次"配置有没有变",没变就不下载, 只有真的改过才会拉全量。改配置的频率不用担心流量问题。
一·五、adns:告诉 App 有哪几家广告平台可用
配置里除了广告位(units),还有一个 adns 列表,登记每家广告平台的 appId:
json
"adns": [
{ "adn": "csj", "app_id": "<穿山甲 appId>" },
{ "adn": "gdt", "app_id": "<优量汇 appId>" }
]| 字段 | 含义 |
|---|---|
adn | 平台标识,csj = 穿山甲,gdt = 优量汇。必须与下面 slots 里用的写法一致 |
app_id | 该开发者在这家平台后台创建应用后拿到的 appId。每个开发者、每个 App 都不一样 |
为什么它要走下发、而不是让开发者自己填进 App:每个开发者在穿山甲、优量汇后台 都是独立创建的应用,appId 各不相同。写进 App 意味着每接一个开发者都要重新出一个接入包, 接入成本没有下限。放在配置里,接入包只有一个,换谁接都不用改。
三条必须记住的规则:
adns里没登记的平台,App 一律不会用。 哪怕某个广告位的slots里写了"adn": "gdt",只要adns里没有gdt的 appId, 这一层会被直接跳过(日志里会打「服务端未下发该 ADN 的 appId」)。- 停用一家平台时,appId 和它名下的全部代码位要一起摘掉。 只删 appId 不删
slots,那些层就变成了永远跳过的空转; 只删slots不删 appId,App 会白白多记一个用不上的 appId。 配置后台在生成下发内容时已经保证了这一点,手工改 JSON 时要自己注意。 - App 是「用到哪家才启动哪家」的。 下发了穿山甲和优量汇两家,不等于开 App 就把两家都跑起来。 某家平台要等到用户第一次打开配了它的广告位时才真正启动 —— 如果某个 App 的广告位里根本没配优量汇,优量汇的 SDK 在这台手机上就从未运行过、 一条设备信息也没采集。这在应用商店的隐私审核里是加分项。
一·六、下发内容会按「这个 App 到底集成了哪几家」自动裁剪
SDK 拉配置时会告诉服务端两件事:自己是哪个版本、这个包里实际带了哪几家平台的适配器。 服务端据此把 App 里没有的那几家从下发内容里摘掉。
为什么要这么做:SDK 是按需裁剪的 —— 接入方可以只引穿山甲、不引优量汇。 这种包拿到「两家都有」的配置时,优量汇那一层会被静默跳过(不报错、日志里也只有一行 debug)。 表面上看一切正常,实际每次请求少一家竞争、填充率变低,而后台完全看不出来。 平台接第三家之后这个偏差会更大。
对运营的影响:
- 后台配的东西不用改。 配置照常按「这个应用计划接哪几家」来配,裁剪是下发那一刻的事
- 同一份配置,不同 App 拿到的内容可能不一样。 只接了穿山甲的那个 App 拿到的
adns里只有穿山甲 - 裁掉了谁在后台看得见:接入清单和缺口看板的「端上 SDK」一栏会写「已裁掉 优量汇」。 发现某个应用的填充率比别人低时,先看这一栏
- 老版本 SDK(不上报这两项的)按全量下发,行为与改造前一致;后台会标「未上报能力(旧版)」。 这类应用要真正解决填充率问题,只能让开发者升级 SDK 重新出包
另有一条相关约定:后台「平台设置 → 广告平台管理」里每家可以填「最低 SDK 版本」。 某家平台是某个 SDK 版本之后才支持的话,填上它,低于这个版本的 App 就不会收到这家的配置 —— 收到了也没用,只是每次请求白等一个超时。
二、完整示例
json
{
"version": 1,
"adns": [
{ "adn": "csj", "app_id": "<穿山甲 appId>" },
{ "adn": "gdt", "app_id": "<优量汇 appId>" }
],
"units": [
{
"unit_id": "reward_main",
"ad_type": "reward",
"total_timeout_ms": 8000,
"bidding_timeout_ms": 3000,
"use_ad_on_timeout": true,
"slots": [
{ "adn": "gdt", "slot_id": "1234567890", "bidding": true, "timeout_ms": 3000 },
{ "adn": "csj", "slot_id": "<GroMore 广告位 ID>", "price": 1500, "timeout_ms": 5000 },
{ "adn": "gdt", "slot_id": "0987654321", "price": 300, "timeout_ms": 5000 }
]
}
]
}三、字段说明
广告位(units 数组的每一项)
| 字段 | 含义 | 建议值 |
|---|---|---|
unit_id | 聚合广告位 ID,由我方自定义,需与代码中一致 | 与开发约定后不要再改 |
ad_type | splash / reward / banner | — |
total_timeout_ms | 整体超时。超过即判定无填充 | 开屏 3000–3500,激励 8000,Banner 5000 |
bidding_timeout_ms | 竞价阶段等待时长 | 开屏 2000,其余 2000–3000 |
refresh_interval_sec | 仅 Banner 有效,自动刷新间隔(秒)。0 = 不刷新 | 30–60 |
use_ad_on_timeout | 等待超时的那一刻,如果广告已经拿到了,还要不要用它 | 一般不用填,默认值就是对的 |
cache_size | 缓存池容量,0 = 不缓存。不填时开屏 / 激励 1、Banner 0 | 开屏 1–2;激励视频 1;Banner 一般不开(只对首屏有用) |
auto_refill | 缓存被取走或过期后是否自动补一条。不填 = false | 开屏 true,激励视频 false |
refill_min_interval_sec | 两次自动补位请求的最短间隔(秒),失败时翻倍退避、封顶 10 分钟。不填 = 30 | 30–60 |
preload_timeout_ms | 预加载 / 补位这类「结果进缓存池」的调度的整体超时,不小于 total_timeout_ms。不填 = 10000 | 一般不用填 |
expire_ms | 素材有效期(毫秒),代码位上也可单独配。不填或填 0 = 30 分钟 | 一般不用填;只能调短不要调长,超过平台实际有效期展示出来是空白 |
⚠️ 开屏卡在 App 启动路径上,超时设置过长会明显拖慢启动速度,不建议超过 3.5 秒。
use_ad_on_timeout:超时那一刻已经拿到的广告,用还是不用
等待的过程中经常会出现这种情况:出价低的那家已经把广告给过来了,出价更高的那家还在等回音, 一直等到 total_timeout_ms 用完。这时手里其实是有一条广告的。
| 值 | 含义 | 结果 |
|---|---|---|
true | 用掉它 | 广告照常展示,多一次收入,但出现得比预期晚 |
false | 丢掉它 | 当作这次没有广告 |
不填的时候,系统按广告类型自动选:
| 广告类型 | 默认 | 为什么 |
|---|---|---|
开屏 splash | false | 开屏超时后 App 已经跳进主页了,这时再把广告放出来,用户会看到一张广告突然盖在主页上。这是事故,比少一次曝光严重得多 |
激励视频 reward | true | 用户是主动点了「看视频领奖励」才等的,晚一两秒出来也比告诉他「没有广告」强 |
Banner banner | true | Banner 常驻在页面上,晚一点挂上去用户基本无感 |
什么时候才需要手动填这个字段:
- 开屏页面做了「广告没来也一直等着不跳转」的特殊处理 → 可以给开屏填
true - 激励视频的业务流程对时间特别敏感(比如超时后马上直接发奖了)→ 给激励填
false
不确定就别填。填错的代价是不对称的:填成 true 最多是广告出现得晚一点, 填成 false 是白白丢掉一次已经到手的填充。
缓存池在 App 进程内存里,进程被杀后清空,冷启动的第一条开屏仍是实时请求;详见《接入文档》「预加载与缓存」。
广告源(slots 数组的每一项)
| 字段 | 含义 | 说明 |
|---|---|---|
adn | 平台标识:csj(穿山甲 GroMore 聚合通道)/ gdt(优量汇) | — |
slot_id | csj 填 GroMore 广告位 ID;gdt 填优量汇代码位 ID | 见下方注意事项 |
bidding | true = 实时竞价位,false = 瀑布层 | 竞价位需向平台商务申请白名单。csj 恒填 false,它的竞价在 GroMore 内部完成 |
price | 仅瀑布层有效,预估底价,单位:分 | 1500 = 15 元 eCPM。竞价位不下发此字段,价格用 ADN 实时出价 |
timeout_ms | 该广告源单独的超时 | 应小于 total_timeout_ms |
width_dp / height_dp | 仅 Banner 需要,尺寸 | 须与平台后台创建代码位时的规格一致 |
四、调度规则(理解这个才知道怎么配价格)
- 先并行请求所有
bidding: true的广告源,等待bidding_timeout_ms - 取其中实时价格最高的一个
- 再按
price从高到低遍历瀑布层:- 若竞价价格 ≥ 当前层的
price→ 直接用竞价结果,后面的层不再请求 - 否则请求当前层,成功则与竞价结果比价取高者,失败则继续往下探
- 若竞价价格 ≥ 当前层的
- 向参与竞价的平台回传竞胜 / 竞败结果(
csj不参与这一步,它的竞价在 GroMore 内部完成)。竞胜方收到的「最高竞败价」包含被它比下去的瀑布层价格
实际含义:
price填得越高,该层越优先被请求,但填虚高会导致竞价结果被无谓跳过,反而损失收益price应参照该代码位近 7 日的真实 eCPM 填写,并定期校准csj层与优量汇竞价位比价时用的就是这个price(GroMore 在加载完成时拿不到真实 eCPM,展示时才有)。实测 GroMore 真实 eCPM 为 100 分时,price填 2000 会让出价 120–520 分的优量汇被全部比下去- 瀑布层数不宜过多,每多一层失败就多一次请求耗时,影响填充速度
五、常见调整场景
某平台收益变好,想让它多拿量 → 调高该 slot 的 price
某代码位审核中 / 想临时下线 → 把该 slot 从 slots 数组里删掉即可
填充率偏低 → 在瀑布最底层加一个低价兜底 slot(price 填 100–300)
开屏拖慢启动 → 调小 total_timeout_ms 和 bidding_timeout_ms
激励视频「超时无填充」偏多,但报表显示广告其实回来了 → 确认该广告位没有把 use_ad_on_timeout 写成 false(激励视频不填时默认就是 true,属于正常)
Banner 刷新太频繁 → 调大 refresh_interval_sec
六、穿山甲侧必读:GroMore 广告位怎么配
穿山甲已把「基础变现」并入 GroMore 并停止受理基础变现的开通申请,账号里创建的代码位 「是否用于 GroMore」一律是「是」,只在聚合场景下才返回广告。所以 csj 这一路走的是 GroMore 聚合通道,配置里的 slot_id 填的是 GroMore 广告位 ID, 不是瀑布流里那些穿山甲代码位 ID。两者长得很像,填错的表现见下表。
6.1 ⚠️ 后台必须配两步,缺一不可
| 步骤 | 在哪儿做 | 产出 |
|---|---|---|
| ① 创建广告位 | GroMore → 应用管理 → 新建广告位 | 一个广告位 ID(10 开头)→ 这个才填进配置的 slot_id |
| ② 配置瀑布流 | GroMore → 瀑布流管理 → 给该广告位添加代码位 | 广告位下面挂上具体的 ADN 代码位与价格 |
只做第一步不做第二步,会直接无填充。 这是最容易漏的一环 —— 广告位建出来了、ID 也是对的,请求照样一条广告都不返回, SDK 只能拿到
20005 广告位下全部代码位均请求失败,字面上完全看不出是"瀑布流是空的"。 新建广告位后请务必到「瀑布流管理」里确认底下挂了代码位。
当前策略:瀑布流里只配穿山甲一家,不加其他 ADN。这样行为最接近直连、最可控; 将来要加快手 / 百度 / Sigmob,除了后台加代码位,App 侧还必须同时集成对应的 ADN SDK 和适配器 aar,并在隐私政策里补充披露 —— 这不是纯后台操作,加之前先跟开发确认。
6.2 填错 ID 会看到什么
| 现象 | 原因 |
|---|---|
20001 reason:234 聚合代码位只能在聚合场景使用 | SDK 没跑在聚合模式下,属开发侧问题 |
20005 广告位下全部代码位均请求失败,明细为空 | 广告位建了,瀑布流没配代码位 |
20005,明细里带着各家的失败原因 | 瀑布流配好了,只是这次确实没有广告 |
40006 广告位ID不合法 | 多见于 Banner 尺寸与后台广告位规格不一致 |
6.3 其他
Banner 尺寸要对得上。 width_dp / height_dp 必须与 GroMore 后台创建广告位时选的规格一致, 否则报 40006 广告位ID不合法,或者拿到一条比例怪异的素材。
GroMore 后台的 Banner 自动刷新请关掉。 刷新统一由本 SDK 按 refresh_interval_sec 驱动, 两边都开会重复计费曝光、也会打乱聚合比价。
价格以 GroMore 实际返回的成交价为准。 csj 这一路的 price 只用于决定这一层在瀑布里的 排序位置;真正参与比价的是 GroMore 返回的实际价格,取不到时才回落到 price。
六·五、配置字段的兼容约定
给接手这份配置的人交代三条,避免以后踩坑:
- 字段只增不删。 SDK 对不认识的字段一律忽略,所以加字段对老版本 App 是安全的; 但删字段、或改一个字段的含义不是 —— 老版本会取到默认值而不报任何错, 表现是「某个广告位行为不对」,极难查。
- 需要新版 SDK 才支持的能力,由服务端按版本决定下发不下发,不要靠 App 自己判断。 现在落地的是「每家广告平台可以填最低 SDK 版本」(见一·六)。
- 版本号只有一个来源:SDK 工程的
version.gradle。它同时出现在埋点、配置请求、 后台「SDK 版本」表里,三处必须完全一致,否则后台看到的版本分布对不上号。 破坏性改动(老版本拿到新配置后行为会错)要升主版本号并写进更新日志。
七、通用注意事项
price 单位是分,不是元。 填 15 表示 0.15 元 eCPM,常见的配置错误。
改完配置建议先在测试环境验证。 配置文件格式错误时 SDK 会回退到本地兜底配置, 虽然不会崩溃,但新配置不会生效,且这种失败是静默的。