Nuxt 3 博客广告曝光突然腰斩:我用可视检测和路由清理修好广告位
广告收益突然掉了一半,不是流量没了,而是广告没被真正看见。我用 IntersectionObserver 和路由切换钩子重做曝光逻辑,解决懒加载不触发和重复初始化。

作者
ZHOUYI
那天后台一看,博客广告曝光少了将近一半,点击也跟着掉。第一反应是流量出问题,但 PV 和来源渠道都没大变。继续看页面行为才发现:不少广告位虽然挂载了,却没有进入真实视口,或者路由切换后旧逻辑没清理,导致广告没有初始化、曝光没上报。这类问题不会报错,只会默默少钱,特别阴。
先确认广告是不是真的可见
以前我会在 onMounted 里直接初始化广告,但博客列表有懒加载、图片占位、长文折叠,mounted 只代表 DOM 存在,不代表用户看得见。尤其移动端广告位常在正文中段,如果页面打开时它还在屏幕外,过早初始化可能拿不到正确尺寸。更稳的做法是用 IntersectionObserver 监听广告容器,进入视口后再加载广告脚本,并把曝光事件记一次。
function useAdVisibility(el, onVisible) {
if (!el || typeof IntersectionObserver === 'undefined') return
const io = new IntersectionObserver((entries) => {
if (entries[0]?.isIntersecting) {
onVisible()
io.unobserve(el)
}
}, { rootMargin: '120px' })
io.observe(el)
return () => io.disconnect()
}路由切换钩子要兜底:断开观察、清掉实例
Nuxt 3 客户端导航时,有些组件会被复用,或者旧页面的定时器、观察器没及时销毁。结果下一页广告位可能拿到旧容器、旧实例,出现两种怪事:要么曝光重复上报,要么脚本初始化冲突后静默失败。我会在 onBeforeRouteLeave 和组件卸载前断开 observer,并把广告实例置空;如果广告组件跟随路由变化,就给它绑定路由路径作为 key,让 Vue 明确重建,而不是带着旧状态继续跑。
- 广告容器给固定高度或最小高度,避免加载后跳动,也让 IntersectionObserver 有稳定目标。
- 同一路由内只初始化一次,可用 isReady 标记,或把 route.path 作为组件 key。
- SSR 阶段别访问 window 和广告 SDK,可视检测统一放 onMounted 后执行。
- 曝光打点加去重,按广告位、页面路径和会话维度记录,防止快速滚动和路由返回重复计数。
最后修好的不是广告,是生命周期
改完后曝光曲线回到正常,我也踏实了。这个坑提醒我:广告位不是插进页面就完事,它和用户可见性、路由生命周期、资源加载时机都绑在一起。把“何时可见、何时初始化、何时清理”说清楚,收益数据才可信,后续做 A/B 或优化也才有依据。