You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SSR Remix Run网站中正确加载Google AdSense异步脚本

在Remix SSR应用中正确加载Google AdSense异步脚本的解决方案

问题背景

我已经搞定了网站的ads.txt、robots.txt和动态sitemap.xml配置,网站也通过了Google AdSense的 monetization审核,理论上只要在head里加指定的链接和脚本就能显示广告。Remix里加链接标签很简单,但加载AdSense的异步脚本时卡壳了。

需要添加的脚本是:

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

目前的状况是:控制台显示脚本已经加上了,但就是不执行;Google账号没问题,肯定是脚本加载方式不对。偶尔清缓存刷新后,首页广告只显示1秒就消失,应该是SSR环境下脚本加载逻辑出问题了。试过这几个方法都没用:

  • dangerouslySetInnerHTML
  • 用useEffect在组件挂载后加脚本
  • 把async换成defer

可行解决方案

方案1:用Remix根路由的ScriptsFunction

在根路由root.tsx里通过ScriptsFunction来添加脚本,同时给脚本加唯一ID防止重复加载:

import type { ScriptsFunction } from "@remix-run/react";
import { Outlet, Scripts } from "@remix-run/react";

export const scripts: ScriptsFunction = () => {
  return [
    {
      async: true,
      src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-xxxxxxxxxxxxxxx",
      crossOrigin: "anonymous",
      id: "adsbygoogle-script",
    },
  ];
};

export default function Root() {
  return (
    <html lang="zh-CN">
      <head>
        {/* 你的meta标签、其他链接标签 */}
      </head>
      <body>
        <Outlet />
        <Scripts />
      </body>
    </html>
  );
}

方案2:客户端组件安全加载脚本(解决Hydration冲突)

如果方案1还是有问题,就写个专门的客户端组件,用useEffect处理,确保脚本只加载一次:

import { useEffect } from "react";

export function AdSenseLoader() {
  useEffect(() => {
    const scriptId = "adsbygoogle-script";
    // 检查脚本是否已存在,避免重复注入
    if (document.getElementById(scriptId)) return;

    const script = document.createElement("script");
    script.id = scriptId;
    script.async = true;
    script.src = "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-xxxxxxxxxxxxxxx";
    script.crossOrigin = "anonymous";

    // 脚本加载完成后可以初始化广告
    script.onload = () => {
      // 如果有需要,这里执行adsbygoogle.push({})来初始化广告单元
    };

    document.head.appendChild(script);

    // 组件卸载时移除脚本
    return () => script.remove();
  }, []);

  return null;
}

然后在根组件里引入这个Loader:

import { Outlet, Scripts } from "@remix-run/react";
import { AdSenseLoader } from "./components/AdSenseLoader";

export default function Root() {
  return (
    <html lang="zh-CN">
      <head>
        {/* 其他head内容 */}
      </head>
      <body>
        <AdSenseLoader />
        <Outlet />
        <Scripts />
      </body>
    </html>
  );
}

关键注意点

  1. 唯一ID必须加:不管用哪种方法,都要给脚本加唯一ID,防止Remix在服务端渲染和客户端hydration时重复注入脚本,这是广告显示1秒就消失的核心原因之一。
  2. 初始化时机要对:如果你的广告单元需要手动初始化,一定要等脚本加载完成后再调用adsbygoogle.push({}),不然脚本没就绪,广告肯定出不来。
  3. Hydration匹配:Remix的SSR和客户端hydration要保持DOM一致,所以通过ID检查脚本是否存在是必须的,避免客户端重复创建脚本导致冲突。

内容的提问来源于stack exchange,提问作者WildThing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 11:20:24