Nextjs 网站接入 Adsense 并手动放置广告

English

上一篇文章我们讲到了接入 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>
);

仍需完善

目前通过手动放置广告,添加了横幅广告和侧边竖向广告,体验感觉还是一般,可能还不如自动广告放置的合理。但是自动广告还是没有生效,不排除可能是我的网站访问人数太少;也可能就是对于页内跳转的支持不好,只能手动放置广告。

如果你知道更好的方法,欢迎评论区告诉我,如果愿意的话也可以访问我的网站帮我增加流量,谢谢!

加载中...
📊 加载中...
感谢Jimmy | 隐私政策 | 赞赏支持
Liu 的 AI 助手