AdSense 审核通过但广告不展示:最快修复法

代码贴了,文章页广告位却空白。先给最快修复法,再按命中率从高到低列出 7 个真实原因,每条都附精确排查步骤。

AdSense 状态写着 “Approved”,代码也贴了,文章页里该出现广告的位置就是一块空白。几乎所有人第一反应都是代码错了,但代码错的概率大约只占 20%。

最快修复法先说: 打开 AdSense,点 Sites,看你域名旁边的状态。如果显示的是 Getting ready 而不是 Ready,说明投放还在门禁阶段,这时候改代码毫无意义。如果已经是 Ready 但 slot 还是空的,就在 DevTools 里检查广告占位,读一下 <ins> 标签上的 data-ad-status 值。这两个检查能在两分钟内定位掉大多数情况。

真正的元凶按顺序排:AdSense 还在给站点或 slot 暖机、slot 拿不到可填充的展示、ads.txt 没被授权、或者页面缺少某个 Google 需要的信号。下面按”在真实场景里出错的顺序”逐条排查。

先读这两个状态信号

动手改之前先收集两个事实,它们能告诉你到底命中了下面 7 个原因里的哪一个。

信号 1 —— 站点状态(AdSense → Sites)。 截至 2026 年 6 月,站点会显示这四种状态之一:

状态含义怎么办
Ready站点已可投放往下做 slot 级别的检查
Getting ready还在审核(通常几天,最长 2-4 周)等。改代码没用
Needs attention有政策或技术问题挡住了投放打开站点,修掉列出的问题,再点 Request review
Requires review还没检查过,或站点转为不活跃Request review

信号 2 —— <ins> 标签上的 data-ad-status 打开页面,右键空白广告位,Inspect,找到 <ins class="adsbygoogle"> 元素。广告请求结束后,AdSense 会写入三种值之一(依据 AdSense 官方文档):

data-ad-status含义接着看哪
filled拿到了广告且正在展示还是看不到:浏览器广告拦截、CSP 或 iframe sandbox 把它藏了
unfilled没拿到广告,单元为空库存(#5)、CMP/同意(#7)、暖机(#1)或 invalid traffic 静默关停(#6)
unfill-optimized没拿到广告,AdSense 把 slot 收起来了unfilled 一样——是填充问题,不是代码问题

如果根本没有 data-ad-status 这个属性,说明脚本就没在这个 slot 上跑:单元在 display:none 的块里、adsbygoogle.push() 没触发、或者 loader 脚本缺失。直接跳到原因 #3 和 #4。

常见原因

按命中率从高到低。

1. 通过审核后的最初 24-72 小时——站点或 slot 还在暖机

审核通过后,AdSense 需要一段时间才会在新站点或新建 ad unit 上开始投放。后台可能写着 “Approved”,但 Sites 状态仍是 Getting ready;即便翻成 Ready,新 slot 也可能在拍卖系统开始填充库存的一两天里一直 unfilled

怎么判断:通过审核(或新建单元)不到约 72 小时、data-ad-status="unfilled"、且 Sites 状态是 Getting ready 或刚转 Ready。这就是暖机,等。

2. ads.txt 缺失或未被授权

如果 https://yourdomain.com/ads.txt 不存在、或里面没有你的 publisher ID,AdSense 会拒绝该站点的广告请求。Sites 页面会在 ads.txt 列直接给出状态:AuthorizedUnauthorizedNot found

怎么判断

curl -s "https://yourdomain.com/ads.txt"

应该看到恰好一行 Google 记录(末尾的 f08c47fec0942fa0 是 Google 固定的认证/TAG ID,原样照抄):

google.com, pub-XXXXXXXXXXXXXXXX, DIRECT, f08c47fec0942fa0

pub- ID 必须跟你 AdSense 账号完全一致。文件缺、ID 错、字段多/乱 = Unauthorized = 不投。注意:低流量站点上,AdSense 爬虫重读 ads.txt 可能要几天,最长一个月。想加速就到 Sites,点进站点,用 Check for updates

3. ad slot 没有可填充的宽度

AdSense responsive 单元要求父容器在脚本执行之前就有非 0 的宽度。如果 <ins> 被塞进 display:none 的块、宽度为 0 的侧栏、收起的移动端抽屉里,单元就会返回 unfilled。大多数展示格式的 AdSense 最小可渲染宽度是 250px。

怎么判断:DevTools 选中 <ins class="adsbygoogle">,看计算样式里的宽度。如果是 0px(或桌面展示位低于约 250px),就找父容器加个真实宽度。

4. ad slot ID 拼错,或 loader / push 根本没跑

两个相关的代码问题。一是复制粘贴错误:data-ad-slot="1234567890" 跟你在 AdSense → Ads → By ad unit 里创建的任何单元都对不上,AdSense 不报错,就是静默不投。二是页面缺了 loader 脚本或 push() 调用,脚本根本没跑(这时压根不会出现 data-ad-status)。

怎么判断:先确认 <head> 里有且只有一次 loader(带你的 client ID):

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXXXXXXXXXXXXX" crossorigin="anonymous"></script>

再去 AdSense → Ads → By ad unit 列出所有单元,把代码里每个 data-ad-slot 跟它对照。任何对不上都不投。

5. 页面主题暂时没有广告主

“信用卡”页面的广告主需求远多于”古董打字机修复”。极冷门主题、或低 CPM 地区的页面,某段时间内可能真的没有可填充竞价,表现为只有冷门页 unfilled

怎么判断:把同一份代码贴到首页(主题更宽)。如果首页填充、冷门文章不填,是库存问题不是代码问题。再到 AdSense → ReportsCoverage 指标——健康站点在 90%+ 附近;特定页面 coverage 偏低就坐实了填充问题。

6. AdSense 检测到 “invalid traffic” 已经静默关停

如果你一直刷自己的页面、点自己的广告、或者有 bot 流量,AdSense 为了保护广告主会悄悄限流或关停投放——情况严重前往往不会发邮件。

怎么判断:到 AdSense → Brand safety → Policy center 看有没有 invalid traffic 提示。哪怕没有正式警告,可疑流量模式也会让填充率默默下降。永远别点或刷自己线上的广告。

7. 页面被同意门禁拦了(EEA / UK / 瑞士)

向 EEA、英国、瑞士的用户投放个性化广告,必须使用经 Google 认证、且接入 IAB TCF 的同意管理平台(CMP)——EEA 和英国自 2024 年 1 月 16 日起,瑞士自 2024 年 7 月 31 日起。如果用户还没做同意选择、或你的 CMP 未获认证,AdSense 最多投非个性化/受限广告,某些配置下连一条都不投。

怎么判断:无痕模式打开页面,在同意弹窗里接受所有 cookie。广告出现了就是 CMP 门禁在拦。确认你的 CMP 在 Google 认证列表里,再决定对未同意者的默认策略:投非个性化广告,还是完全不投。

最短修复路径

第 1 步:确认上面那两个状态信号

如果 Sites 状态不是 Ready,或 data-ad-statusunfilled/unfill-optimized,那是投放/填充问题,不是代码问题。如果压根没有 data-ad-status,才是代码问题,继续往下。

第 2 步:验证 ads.txt 已被授权

curl -s "https://yourdomain.com/ads.txt"
diff <(curl -s "https://yourdomain.com/ads.txt") <(echo "google.com, pub-YOURID, DIRECT, f08c47fec0942fa0")

为空或不一致就在站点根目录建/修。Astro、Next.js、Vercel 都放在 public/ads.txt。然后从 Sites → (你的站点)→ Check for updates 触发重爬,给几天让状态翻成 Authorized

第 3 步:确认 ad unit 存在且 slot ID 对得上

AdSense → Ads → By ad unit 复制每个 slot ID,在代码里搜:

grep -rn "data-ad-slot" src/

每个值都要能对上一个 AdSense 单元。没用的代码片段删掉。

第 4 步:给 slot 一个可填充的宽度

如果 slot 在某些断点会塌掉的 flex / grid 里:

.ad-slot {
  display: block;
  min-width: 250px;   /* AdSense 最小可渲染宽度 */
  min-height: 100px;
}

或者把 <ins> 套一个 width: 100%; min-height: 250px 的 div。

第 5 步:测同意路径

无痕打开 → CMP 选拒绝 → 看广告还出不出。一个都不出,说明 CMP 把未同意者全拦了。先确认你用的是 Google 认证的 CMP,再把未同意者的默认设为允许非个性化广告。代码层兜底可在 loader 跑之前请求非个性化广告:

<script>
  (adsbygoogle = window.adsbygoogle || []).requestNonPersonalizedAds = 1;
</script>

第 6 步:确认确实修好了

对账不是即时的。改完代码或 ads.txt 后,在无痕(关掉广告拦截)里重新打开线上页面,再看 data-ad-status:要的是 filled。然后看 Reports → Coverage 在接下来 24-48 小时里爬向约 90%。没等满 48 小时别急着下”还是坏的”这个结论。

预防建议

  • CI 里加 ads.txt 校验:curl -sf yourdomain.com/ads.txt | grep -q "$PUB_ID"
  • 构建期校验所有 data-ad-slot 值都在已知列表里。
  • 不要把广告 slot 塞进会被条件隐藏的容器;占位永远渲染,只用 data-ad-status="unfilled" 的 CSS 规则让空单元收起,而不是隐藏整个容器。
  • 永远别刷或点自己线上的广告——会触发 invalid traffic 标记。
  • 用 Google 认证的 CMP,让 EEA/UK/瑞士流量至少还能拿到非个性化广告。

常见问题

账号显示已通过,但 Sites 还是 “Getting ready”,是出问题了吗? 不是。“Getting ready” 表示按站点的审核还在跑,通常几天清掉,也可能要 2-4 周。改代码加速不了;翻成 Ready 之前都不会投放。

配置都对,为什么还是 data-ad-status="unfilled" unfilled 表示这次请求拍卖没返回广告——暖机、冷门/低 CPM 页此刻没竞价、同意门禁、或 invalid traffic 关停。这是填充问题,不是代码 bug。拿这个页和首页比一比主题,再看 Coverage 报告。

AdSense 读取新建或修改后的 ads.txt 要多久? 大多数站点几天,低流量站点最长一个月。从 Sites → (你的站点)→ Check for updates 强制重爬,等状态变成 Authorized

首页有广告,某篇文章没有,为什么? 基本是库存(#5)或那篇页面布局特有的宽度/可见性问题(#3)。首页主题更宽,吸引更多竞价;冷门文章此刻可能一条竞价都没有。确认 slot 计算宽度非 0,并查那个页面的 coverage。

没广告的时候该把空框隐藏吗? 该,但要小心。用 ins.adsbygoogle[data-ad-status="unfilled"]{display:none !important;} 让空框收起。注意它抓不到 unfill-optimized 的单元;而且千万别在 slot 请求之前就给它 display:none——那正是导致 unfilled 的原因。

就为了投广告,我真得加同意横幅吗? 只要你有任何来自 EEA、英国、瑞士的流量,就得:投放个性化广告强制要求使用接入 IAB TCF 的 Google 认证 CMP(EEA 和英国自 2024 年 1 月 16 日起,瑞士自 2024 年 7 月 31 日起)。没有的话,这部分流量可能一条广告都拿不到。

相关阅读

外部参考:AdSense:查看站点状态AdSense:data-ad-status 参数Google 同意管理要求(EEA/UK/瑞士)

标签: #AdSense #变现 #排查 #排查