上一篇文章我们讲到了接入 adsense 遇到的第一个问题:adsense无法预览,紧接着我就遇到了第二个问题:自动广告没有生效。
我的网站是 nextjs 制作的纯静态页面,我在广告审核通过之后就放置了 adsense 代码在 head 标签中,然后配置了自动广告,打开了几种广告类型,包括:侧边栏广告、穿插广告、页内广告,结果只有穿插广告生效了,其他广告类型均没有生效。
<html lang="en">
<head>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-id" crossOrigin="anonymous"></script>
</head>
</html>
原因思考
而且由于穿插广告是有触发限制的,我设置的只有半个小时才能触发一次,所以在我访问网站的过程中,很长时间没有任何一个广告出现。
这个现象有点奇怪,如果我配置有问题,那应该连穿插广告都不该有。那为什么只有穿插广告生效呢?AI 给出了一个答案,可能是因为我的网站是纯静态页面,而且跳转使用的是 Link 标签,相当于页内跳转,可能对于 adsense 来说这样的跳转不算是进入新页面,adsense js 代码可能没有正确刷新。
一开始我有点不相信这个原因,因为 nextjs 并非 SPA 单页面程序,即使使用了 Link 标签,也只是体验上类似 SPA 页面。毕竟静态导出后每一个页面都是有单独的 html 文件。 而且 adsense 已经发展这么长时间了,应该可以兼容这种主流的网站类型吧?
尝试解决
然后我主动观察了路由跳转过程,发现确实没有加载 js 代码;而在 hugo 网站上,每一次跳转都重新加载了 js 代码。觉得可能还真是这个原因,在谷歌搜索后确实有不少遇到相同问题的,提出一个解决方案是在路由跳转后手动刷新 js 代码:
// pages/_app.js
import { useEffect } from 'react';
import { useRouter } from 'next/router';
function MyApp({ Component, pageProps }) {
const router = useRouter();
useEffect(() => {
const handleRouteChange = () => {
try {
// 确保 adsbygoogle 数组存在
if (window.adsbygoogle && window.adsbygoogle.push) {
console.log('AdSense: Triggering push after route change');
// 触发 AdSense 重新扫描页面并加载广告
(window.adsbygoogle = window.adsbygoogle || []).push({});
}
} catch (e) {
console.error('Error pushing to adsbygoogle:', e);
}
};
// 监听路由变化结束事件
router.events.on('routeChangeComplete', handleRouteChange);
// 组件卸载时取消监听
return () => {
router.events.off('routeChangeComplete', handleRouteChange);
};
}, [router.events]);
return <Component {...pageProps} />;
}
export default MyApp;
这个代码是我随便找的,思路都是一样的,就是主动调用 adsbygoogle.push(),我测试了一下好像没有生效,因为每次跳转页面都会报错提示不要push已经存在的元素。
Link标签改为a标签
当然还有最简单的方法,就是将 Link 标签改为 a 标签,这样路由跳转时相当于刷新了页面,就会触发js代码,从而实现广告的加载。不过这种方法不推荐,因为体验下降了不少,跳转不再丝滑快速了
// before
<Link
key={item.name}
href={item.href}
className={`group flex items-center px-3 py-1.5 sm:py-2 text-sm font-medium rounded-lg transition-colors ${
isActive
? 'bg-blue-100 text-blue-700'
: 'text-gray-700 hover:bg-gray-100 hover:text-gray-900'
}`}
onClick={() => setSidebarOpen(false)}
>
<span className="mr-3 text-lg">{item.icon}</span>
{item.name}
</Link>
// after
<a
key={item.name}
href={item.href}
className={`group flex items-center px-3 py-1.5 sm:py-2 text-sm font-medium rounded-lg transition-colors ${
isActive
? 'bg-blue-100 text-blue-700'
: 'text-gray-700 hover:bg-gray-100 hover:text-gray-900'
}`}
onClick={() => setSidebarOpen(false)}
>
<span className="mr-3 text-lg">{item.icon}</span>
{item.name}
</a>
手动放置广告
尝试以上方法都没能解决问题,没办法只能再次手动放置广告了,首先去 adsense 后台创建新的广告单元,我选择的是展示广告,任何地方都可以放置,然后复制代码。这里面ad-client是你的发布商id,ad-slot是广告单元id
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-id"
data-ad-slot="slot-id"
data-ad-format="auto"
data-full-width-responsive="true"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script>
接下来创建一个广告组件components/Adsense.tsx,这段代码是AI写的,没什么质量可言但可以运行。修改 data-ad-client,然后在AdsenseUnits添加广告单元
"use client";
import { useEffect } from "react";
// 声明window对象的adsbygoogle属性类型
declare global {
interface Window {
adsbygoogle: Array<Record<string, unknown>>;
}
}
interface AdsenseProps {
/**
* 广告单元ID (data-ad-slot)
*/
adSlot: string;
/**
* 广告格式 (auto, rectangle, horizontal, vertical)
*/
adFormat?: string;
/**
* 是否全宽响应式
*/
fullWidthResponsive?: boolean;
/**
* 自定义CSS类名
*/
className?: string;
/**
* 自定义样式
*/
style?: React.CSSProperties;
/**
* 广告容器类名
*/
containerClassName?: string;
/**
* 广告容器样式
*/
containerStyle?: React.CSSProperties;
/**
* 是否启用移动端特殊处理
*/
mobileOptimized?: boolean;
}
/**
* 可复用的Google AdSense广告组件
* 支持多种广告格式和响应式设计
*/
export default function Adsense({
adSlot,
adFormat = "auto",
fullWidthResponsive = true,
className = "",
style = {},
containerClassName = "",
containerStyle = {},
mobileOptimized = true,
}: AdsenseProps) {
useEffect(() => {
// 加载AdSense广告
const loadAdSense = () => {
try {
if (typeof window !== 'undefined' && window.adsbygoogle) {
(window.adsbygoogle = window.adsbygoogle || []).push({});
}
} catch (error) {
console.error('AdSense error:', error);
}
};
// 延迟加载广告,确保DOM已渲染
const timer = setTimeout(loadAdSense, 100);
return () => clearTimeout(timer);
}, [adSlot]);
return (
<div
className={`ad-container ${containerClassName}`}
style={containerStyle}
>
<ins
className={`adsbygoogle ${className}`}
style={{
display: 'block',
...style,
}}
data-ad-client="ca-pub-id"
data-ad-slot={adSlot}
data-ad-format={adFormat}
data-full-width-responsive={fullWidthResponsive.toString()}
/>
{mobileOptimized && (
<style jsx>{`
.ad-container {
max-width: 100%;
overflow: hidden;
box-sizing: border-box;
}
.adsbygoogle {
max-width: 100%;
overflow: hidden;
box-sizing: border-box;
}
@media (max-width: 640px) {
.ad-container {
width: 100%;
}
.adsbygoogle {
width: 100%;
}
}
`}</style>
)}
</div>
);
}
/**
* 预定义的广告单元配置
*/
export const AdsenseUnits = {
// HEADER: "your-header-ad-slot",
// FOOTER: "your-footer-ad-slot",
} as const;
接下来在需要显示的广告页面中引入该组件并传入广告单元的ID即可,我把广告放在了评论区上方
import Adsense, { AdsenseUnits } from './Adsense';
return (
<div className={`mt-6 sm:mt-8 ${className}`}>
<Adsense
adSlot={AdsenseUnits.WALINE_TOP}
adFormat="auto"
fullWidthResponsive={true}
mobileOptimized={true}
containerClassName="mb-6 sm:mt-8 -mx-4 sm:mx-0"
/>
<div className="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
<div ref={commentRef} className="waline-container" />
</div>
</div>
);
仍需完善
目前通过手动放置广告,添加了横幅广告和侧边竖向广告,体验感觉还是一般,可能还不如自动广告放置的合理。但是自动广告还是没有生效,不排除可能是我的网站访问人数太少;也可能就是对于页内跳转的支持不好,只能手动放置广告。
如果你知道更好的方法,欢迎评论区告诉我,如果愿意的话也可以访问我的网站帮我增加流量,谢谢!