如何在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> ); }
关键注意点
- 唯一ID必须加:不管用哪种方法,都要给脚本加唯一ID,防止Remix在服务端渲染和客户端hydration时重复注入脚本,这是广告显示1秒就消失的核心原因之一。
- 初始化时机要对:如果你的广告单元需要手动初始化,一定要等脚本加载完成后再调用
adsbygoogle.push({}),不然脚本没就绪,广告肯定出不来。 - Hydration匹配:Remix的SSR和客户端hydration要保持DOM一致,所以通过ID检查脚本是否存在是必须的,避免客户端重复创建脚本导致冲突。
内容的提问来源于stack exchange,提问作者WildThing
相关产品推荐
相关产品推荐

