AdSense 代码装了广告位空白

脚本加载了,但广告位空——slot 配置 / 页面资格 / 拦截器。

你已经把 <script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-..."><ins class="adsbygoogle"> 标签都贴上去了。DevTools Network 确认 adsbygoogle.js 返回 200。但刷新再刷新、等了几个小时,广告位还是空白。这是 AdSense 里最典型的”看着对、其实不对”的故障——基本上都能归到 6 种接线问题之一,跟代码本身关系不大。

诊断关键是 AdSense 脚本回写到 <ins> 标签上的 data-ad-status 属性。读懂这个,修复通常 5 分钟。

常见原因

按命中率从高到低。

1. (adsbygoogle = window.adsbygoogle || []).push({}) 没执行

脚本加载了,但激活 slot 的 push({}) 调用要么缺失,要么放在一个永远跑不到的地方(某个没触发的路由切换 hook、被 if 拦了、SSR vs hydration 时丢了)。

怎么判断:DevTools 控制台执行 window.adsbygoogle.loaded。如果是 undefinedfalse,push 就没跑。同时 <ins> 上完全没有 data-ad-status 属性(连 unfilled 都没有)。

2. slot 渲染时宽度为 0

<ins> 元素存在,但它的父容器是 display: none、当前断点宽度 0、或者在没展开的 tab/accordion 里。AdSense 对 0 宽度 slot 静默拒绝,位置就一直空着。

怎么判断:右键 → 检查 <ins> → Computed → width。是 0px 就是这条。常见于会塌掉的 flex 容器、width: max-content 的包裹。

3. 同时有多个 <script async ...adsbygoogle.js> 标签

如果你 layout 把 AdSense 脚本贴了两次(一次在 head 一次在组件里),脚本会加载两次,第二次有时绑不上,slot 半推半就。

怎么判断:控制台 Array.from(document.querySelectorAll('script[src*="adsbygoogle"]')).length。应该是 1。

4. <ins> 标签写错了

常见拼写错误:data-ad-clinetdata-ad-slt、漏 class="adsbygoogle"、漏 style="display:block",或者 React 把你写的 dataAdClient 转换成 camelCase 丢了 kebab-case。

怎么判断:查看源代码(不是 React render tree)。真实 HTML 必须包含 class="adsbygoogle"data-ad-client="ca-pub-..."

5. 页面达不到 AdSense 内容阈值

某些页面——只有 50 字的”Hello world”占位、只有一堆链接列表没有说明文字的分类页、搜索结果页——内容不够撑起广告。data-ad-status="unfilled" 会出现。

怎么判断:跟同一站上已知正常的文章对比。长文章填、薄页面不填,就是内容阈值问题。

6. 你的 IP 或测试会话被限流

你一直 F5 测广告,AdSense 可能会在当天对你的 IP 限流投放。用手机蜂窝、朋友电脑能看到广告,自己电脑看不到。

怎么判断:手机切到蜂窝(不同 IP)打开页面。那边能投,就是本地被限流。

最短修复路径

第 1 步:读渲染后 <ins>data-ad-status

控制台:

document.querySelectorAll('ins.adsbygoogle').forEach((el, i) =>
  console.log(i, el.getAttribute('data-ad-status'), el.offsetWidth));
状态宽度含义
undefined任意push 没跑(原因 #1 或 #4)
unfilled> 0push 跑了但拍卖没拿到广告(原因 #5 或 #6)
unfilled0宽度问题(原因 #2)
filled> 0正常——看不到就查浏览器广告拦截

第 2 步:手动触发 push 验证

控制台:

(window.adsbygoogle = window.adsbygoogle || []).push({});

如果 slot 现在填了之前没填,就是你的 push 代码没跑到。SPA / Next / Astro 项目里,把 push 放在:

<ins class="adsbygoogle" ...></ins>
<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>

紧跟在 <ins> 后面。SPA 路由切换:每次切换都重新 push。

第 3 步:修正标签

按这个模板原样贴,不要改属性名:

<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-XXXXXXXXXXXXXXXX"
     data-ad-slot="1234567890"
     data-ad-format="auto"
     data-full-width-responsive="true"></ins>

React / Astro 里用 dangerouslySetInnerHTML,或确保框架保留 kebab-case(Astro 默认保留;React 需要 data-ad-client 形式)。

第 4 步:删除重复的 script 标签

grep -rn "adsbygoogle.js" src/ public/

应该只出现一次(在某个 layout/template 文件里)。重复的删掉。

第 5 步:给 slot 强制最小宽度

.adsbygoogle {
  display: block;
  min-width: 250px;
  min-height: 100px;
}

不要在 display: none 的容器里塞广告。需要隐藏的话用 visibility: hidden

第 6 步:换个 IP 测

手机蜂窝、朋友的网、VPN。那边能投,AdSense 大概 24 小时会自动给你解封——别再 F5 自己的站测试了。

预防建议

  • 用单一的 <AdSlot> 组件 / partial 统一渲染。所有 slot 走它,不要复制粘贴。
  • AdSense 脚本只在一个地方加载——根 layout 或 document head。
  • 加 lint 校验每个 <ins class="adsbygoogle"> 都有对应的 push({}) 调用。
  • 全局样式里给 .adsbygooglemin-width: 250px
  • 测试时不要反复刷新自己的页面——用手机或别人的浏览器。

相关阅读

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