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