Next.js中用Script组件在_head_插入Zoho跟踪代码遇阻求助
问题解答
1. 能否在_document.tsx的Head中添加Zoho跟踪代码?
可以,但你当前的写法存在问题——Next.js的<Script>组件在_document.tsx的<Head>中使用时,内联脚本的执行逻辑会受限。因为_document是服务端渲染的顶层文档组件,<Script>在这里的行为和普通页面组件里不一样,尤其是内联代码的加载时机与执行上下文,这也是你的代码被忽略但无报错的原因。
修复方案:改用原生<script>标签(在_document.tsx中)
在_document.tsx的<Head>里直接使用原生<script>标签替代<Script>组件,服务端生成HTML时会正确注入这段代码:
import Document, { Html, Head, Main, NextScript, DocumentContext, DocumentInitialProps, } from "next/document"; class MyDocument extends Document { static async getInitialProps( ctx: DocumentContext ): Promise<DocumentInitialProps> { const initialProps = await Document.getInitialProps(ctx); return { ...initialProps }; } render() { return ( <Html lang="en"> <Head> {/* 原有meta与link标签保持不变 */} <meta charSet="utf-8" /> <link href="https://fonts.googleapis.com/css?family=PT+Sans&display=optional" rel="stylesheet" /> <meta name="msapplication-TileColor" content="#596285" /> <meta name="msapplication-config" content="/favicon/browserconfig.xml" /> <meta name="theme-color" content="#ffffff" /> {/* Zoho营销自动化代码:改用原生script标签注入 */} <script id="zoho-ma" dangerouslySetInnerHTML={{ __html: ` var w = window; var p = w.location.protocol; if (p.indexOf("http") < 0) { p = "http" + ":"; } var d = document; var f = d.getElementsByTagName("script")[0], s = d.createElement("script"); s.type = "text/javascript"; s.async = false; if (s.readyState) { s.onreadystatechange = function () { if (s.readyState == "loaded" || s.readyState == "complete") { s.onreadystatechange = null; try { loadwaprops( "myid#", "myid#", "myid#", "myid#", "0.0" ); } catch (e) {} } }; } else { s.onload = function () { try { loadwaprops( "myid#", "myid#", "myid#", "myid#", "0.0" ); } catch (e) {} }; } s.src = p + "//ma.zoho.com/hub/js/WebsiteAutomation.js"; f.parentNode.insertBefore(s, f); ` }} /> </Head> <body> <Main /> <NextScript /> <div id="notifications"></div> </body> </Html> ); } } export default MyDocument;
注:这里使用dangerouslySetInnerHTML是因为Next.js在_document中不允许直接在<script>标签内编写内联代码,必须通过该属性注入。
2. 是否更适合拆分为独立组件?
如果你的应用需要动态控制跟踪代码的加载(比如根据环境、用户权限决定是否加载),或者需要在部分页面禁用该代码,那么拆成独立组件更合适;如果只是全局所有页面都需要加载,直接在_document.tsx中用原生脚本的方案更简洁。
独立组件方案(适配Pages Router)
创建components/ZohoTracking.tsx:
import Script from "next/script"; export default function ZohoTracking() { return ( <Script id="zoho-ma" strategy="beforeInteractive"> {` var w = window; var p = w.location.protocol; if (p.indexOf("http") < 0) { p = "http" + ":"; } var d = document; var f = d.getElementsByTagName("script")[0], s = d.createElement("script"); s.type = "text/javascript"; s.async = false; if (s.readyState) { s.onreadystatechange = function () { if (s.readyState == "loaded" || s.readyState == "complete") { s.onreadystatechange = null; try { loadwaprops( "myid#", "myid#", "myid#", "myid#", "0.0" ); } catch (e) {} } }; } else { s.onload = function () { try { loadwaprops( "myid#", "myid#", "myid#", "myid#", "0.0" ); } catch (e) {} }; } s.src = p + "//ma.zoho.com/hub/js/WebsiteAutomation.js"; f.parentNode.insertBefore(s, f); `} </Script> ); }
然后在_app.tsx中全局引入:
import type { AppProps } from "next/app"; import ZohoTracking from "../components/ZohoTracking"; function MyApp({ Component, pageProps }: AppProps) { return ( <> <ZohoTracking /> <Component {...pageProps} /> </> ); } export default MyApp;
这里使用strategy="beforeInteractive"确保脚本在页面交互前加载,和_document中的加载时机一致,同时<Script>组件在_app.tsx中的执行逻辑符合预期。
关键注意事项
_document.tsx中优先用原生<script>处理全局跟踪代码,避免<Script>组件的上下文限制;- 若使用独立组件,需放在
_app.tsx而非_document.tsx中,_app是页面级顶层组件,<Script>组件在这里的行为更可控; - 记得将
loadwaprops中的myid#替换为你的实际Zoho营销自动化ID。
内容的提问来源于stack exchange,提问作者HamletHub
相关产品推荐
相关产品推荐

