如何将 Google Tag Manager 添加到 NextJS 网站中。

9

这个答案这篇文章中,我已经添加了一个<Script>来将Google Tag Manager添加到我的NextJS网站中:

components/layout.tsx:

 import React from "react";
 import Head from "next/head";
 import Script from 'next/script'

 <!-- skip some code -->

 <Head>
    <link rel="preconnect" href="https://cdn.sanity.io/" />
    <link rel="dns-prefetch" href="https://cdn.sanity.io//" />
  </Head>
  <Script id="google-tag-manager" strategy="afterInteractive">
    {
      (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
      new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
      j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
      'https://www.googletagmanager.com/gtm.js?id=%27+i+dl;f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','GTM-xxxx');
    }
  </Script>

然而,该脚本在前端不存在。

components/layout.tsx 是我网站上唯一带有 <Head><head> 的文件。

Google Tag Manager <noscript> 存在于前端,在 app/layout.tsx: 中使用。

 <body className="antialiased text-gray-800 dark:bg-black dark:text-gray-400">
    <noscript
      dangerouslySetInnerHTML={{
        __html: <iframe src="https://www.googletagmanager.com/ns.html?id=xxxx" height="0" width="0" style="display: none; visibility: hidden;" />,
      }}
    />

所以我知道我已经保存了所有更改。

感谢您的帮助。

更新

我是NextJS的新手,所有这些代码都来自于一个NextJS / Sanity模板,它在本地和Vercel暂存站点上都可以正常工作。

我的唯一问题是在发布到我的域之前无法正确加载Google Tag Manager。

项目中没有_app.js

/app/(website)/layout.tsx

import "@/styles/tailwind.css";
import { Providers } from "./providers";
import { cx } from "@/utils/all";
import { Inter, Lora } from "next/font/google";

const inter = Inter({
  subsets: ["latin"],
  variable: "--font-inter"
});

const lora = Lora({
  subsets: ["latin"],
  variable: "--font-lora"
});

export default function RootLayout({
  children
}: {
  children: React.ReactNode;
}) {
  return (
    <html
      lang="en"
      suppressHydrationWarning
      className={cx(inter.variable, lora.variable)}>
       <body className="antialiased text-gray-800 dark:bg-black dark:text-gray-400" >
        <noscript
          dangerouslySetInnerHTML={{
            __html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-xxxx" height="0" width="0" style="display: none; visibility: hidden;" />`,
          }}
        />
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

这是 /app/(website)/providers.tsx 文件:

"use client";

import { ThemeProvider } from "next-themes";

    export function Providers({ children }) {
      return (
        <ThemeProvider attribute="class" defaultTheme="light">
          {children}
        </ThemeProvider>
      );
    }

如果我在VSCode中搜索RootLayout,没有任何调用它的内容,所以我有点困惑哪个是主文件。

如果您想要访问Github存储库,我可以提供它。


1
你应该看一下这个:https://github.com/XD2Sketch/next-google-tag-manager - Kevin Goedecke
1
你应该看看这个:https://github.com/XD2Sketch/next-google-tag-manager - undefined
7个回答

8
在位于/pages目录下的_document.js文件中添加以下代码。如果没有任何_document.js文件,请创建它。
现在将Google Tag Manager的功能添加为:
import Document, { Html, Head, Main, NextScript } from "next/document";

function MyDocument() {
  return (
    <Html>
      <Head>
        <script
          dangerouslySetInnerHTML={{
            __html: `
              (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
              new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
              j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
              'https://www.googletagmanager.com/gtm.js?id=%27+i+dl;f.parentNode.insertBefore(j,f);
              })(window,document,'script','dataLayer','GOOGLE_TAG_MANAGER_ID');
            `,
          }}
        />
      </Head>
      <body>
        <noscript
          dangerouslySetInnerHTML={{
            __html: `
              <iframe src="https://www.googletagmanager.com/ns.html?id=GTM-xxxx"
              height="0" width="0" style="display:none;visibility:hidden"></iframe>
            `,
          }}
        />
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

export default MyDocument;

现在您可以检查功能是否正常工作,请让我知道如果它没有工作。我一定会帮忙的。


NextJS/Sanity模板中没有包含_document.js文件,我不想通过创建它来使事情变得复杂或破坏原有的结构。Yilmaz的回答解决了我的问题。 - Steve

4

快来看看新的NextJs第三方组件

在观看了NextJS Conf2023之后,他们发布了@next/third-parties,因为过去几个月有人报告说他们按照Google Analytics文档的指导进行操作后,Lighhouse的性能出现了问题。

按照NextJs的文档指南进行操作后,我成功地在NextJs 14上完全设置了Google Analytics。

1. 要在所有路由上加载Google Tag Manager,请直接在根布局中包含该组件:

app/layout.tsx

import { GoogleTagManager } from '@next/third-parties/google'

export default function RootLayout({children}: {children: React.ReactNode}) {
    return (
        <html lang="en">
            <body>{children}</body>
            <GoogleTagManager gtmId="GTM-XYZ" />
        </html>
     )
}

2. 要为单个路由加载Google Tag Manager,请在您的页面文件中包含该组件。

app/page.js

import { GoogleTagManager } from '@next/third-parties/google'

export default function Page() {
    return <GoogleTagManager gtmId="GTM-XYZ" />
}

注意: 这是官方的NextJs文档。

在一个 NextJS 14 项目上尝试了一下,遇到了导入错误。这个 GitHub 问题展示了这个问题(它已经自动关闭了,但仍然存在):https://github.com/vercel/next.js/issues/58458 - undefined

3

来自如何在Next.js 13应用程序路由器中设置Google标签管理器的答案

// create a client component
"use client"
// you are using id=GTM-xxxx. no need for gtmId
import { gtmId, pageview } from "lib/gtm"
import { usePathname, useSearchParams } from "next/navigation"
import Script from "next/script"
import { useEffect } from "react"

export default function Analytics() {
  const pathname = usePathname()
  const searchParams = useSearchParams()

  useEffect(() => {
    if (pathname) {
      pageview(pathname)
    }
  }, [pathname, searchParams])

  if (process.env.NEXT_PUBLIC_VERCEL_ENV !== "production") {
    return null
  }

  return (
    <>
      <noscript>
        <iframe
          src={`https://www.googletagmanager.com/ns.html?id=GTM-xxxx`}
          height="0"
          width="0"
          style={{ display: "none", visibility: "hidden" }}
        />
      </noscript>
      <Script
        id="gtm-script"
        strategy="afterInteractive"
        dangerouslySetInnerHTML={{
          __html: `
    (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
    new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
    j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
    'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
    })(window,document,'script','dataLayer', "GTM-xxxx");
  `,
        }}
      />
    </>
  )
}

在你的RootLayout组件中导入此代码


在上面的代码中将 gtmId 替换为 GTM_ID,并使用这个 gtm.js - Steve

2

确保你在_app.js文件中实际使用了你的布局:

// _app.js
import '../styles/globals.css';
import Layout from './layout';

function MyApp({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  );
}

export default MyApp;

在你的layout.tsx文件中,你可以按照以下方式加载脚本:
// layout.js
import Head from 'next/head';

export default function Layout({ children }) {
  return (
    <>
      <Head>
        <link rel="preconnect" href="https://cdn.sanity.io/" />
        <link rel="dns-prefetch" href="https://cdn.sanity.io//" />
      </Head>
      <script
        id="google-tag-manager"
        dangerouslySetInnerHTML={{
          __html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id=%27+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-xxxx');`,
        }}
      />
      <main>{children}</main>
    </>
  );
}

请注意,我没有使用Next Script组件,因为文档似乎没有提到如何在该组件中使用子元素。 这里是在Stackblitz上的完整工作示例。 另外,请确保您没有启用任何浏览器扩展程序,以删除与跟踪相关的脚本。您可以在不同的浏览器或隐身模式下进行测试。

谢谢你的回答。我在我的问题中添加了一个更新,提供了更多细节(项目中没有 _app.js)。此外,我无法在 layout.tsx 中的 <script id="google-tag-manager" 中看到您的更改。 - Steve

1
在使用应用程序文件夹(而不是页面文件夹)时,向Nextjs 13+中添加Google标签的简单方法是:
在代码库中的任何位置创建一个新的组件,用于存储Google标签脚本(例如components/GoogleAnalytics.tsx)。
import Script from "next/script";

export const GoogleAnalyticsTracking = () => {
  return (
    <>
      {/* Global site tag (gtag.js) - Google Analytics */}
      <Script src="https://www.googletagmanager.com/gtag/js?id=G-GOOGLEID" />
      <Script id="google-analytics" strategy="afterInteractive">
        {`
          window.dataLayer = window.dataLayer || [];
          function gtag(){window.dataLayer.push(arguments);}
          gtag('js', new Date());

          gtag('config', 'G-GOOGLEID');
        `}
      </Script>
    </>
 );
}

然后,在你的 app/layout.tsx 文件中,只需像这样导入组件:
import './globals.css'
import type { Metadata } from 'next'
import { GoogleAnalyticsTracking } from '@/components/GoogleAnalytics'

export const metadata: Metadata = {
  title: 'Your app name',
  description: 'App description'
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <GoogleAnalyticsTracking />
      <body>{children}</body>
    </html>
  )
}

在我的设置中,我使用Nextjs与CSR(客户端渲染),通过在package.json中使用"build": "next build && next export"。 这个解决方案受到了这篇文章的启发: 在Next.js的头部插入脚本使用Script组件

1
@magicul/next-google-tag-manager这个Node包可能已经消除了你自己构建的需求。

app/layout.tsx

import GoogleTagManager from '@magicul/next-google-tag-manager';
const RootLayout = ({ children }) => (
  <html lang="en">
    <body>
      <GoogleTagManager id="GTM-XXXXX" />
      {children}
    </body>
  </html>
);

这绝对是最简单的解决方案。 - undefined

0
下一个13个应用程序目录解决方案 经过几天的阅读和阅读许多文章后,我分享了我的解决方案(我提到在使用这个解决方案之前,我在生产中遇到了next__error,这让我感到沮丧,因为我在layout.jsx中直接使用了标签,出于某些原因) 并提到我使用了GtmHandler包来解决这个问题,但你也可以手动在这里完成。
让我们开始,在组件目录中创建实例

app/components/GTMHandler.jsx

"use client"

import GoogleTagManager from "@magicul/next-google-tag-manager"
import { Suspense } from "react"

const GTMHandler = ({ id }) => {
// id is passed from parent
    return (
        <Suspense>
            <GoogleTagManager id={id} />
        </Suspense>
    )
}

export default GTMHandler

然后在layout.jsx中使用它。app/layout.jsx。

import GTMHandler from "../components/GTMHandler";


export default async function RootLayout({ children }) {
let id = "YOUR__ID"
  return (
    <html lang="fa" dir="rtl">
      <head>
        <meta name="robots" content="noindex,nofollow" />
          <GTMHandler id={id} />
      </head>
      <body>{children}</body>
    </html>
  );
}

Suspense HOC导致我的应用在生产环境中不会崩溃,并且能正常运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接