【问题标题】:How to set up Google Analytics through Google Tag Manager for Next-Js?如何通过 Google Tag Manager for Next-Js 设置 Google Analytics?
【发布时间】:2017-08-23 19:44:49
【问题描述】:

以前我使用 react-ga npm 模块在我的下一个 js 应用程序中插入谷歌分析。就像这样:

import ReactGA from 'react-ga'

export const initGA = () => {
  ReactGA.initialize('UA-*******-*', {
    titleCase: false
  })
}

export const logPageView = () => {
  if (window.location.href.split('?')[1]) {
    ReactGA.set({page: window.location.pathname + '?' + window.location.href.split('?')[1]})
    ReactGA.pageview(window.location.pathname + '?' + window.location.href.split('?')[1])
  } else {
    ReactGA.set({page: window.location.pathname})
    ReactGA.pageview(window.location.pathname)
  }
}

然后我在我的标题中调用 logPageView 函数(插入到我的应用程序的每个页面),如下所示:

  componentDidMount () {
    if (!window.GA_INITIALIZED) {
      initGA()
      window.GA_INITIALIZED = true
    }
    logPageView()
  }
  componentWillReceiveProps () {
    if (!window.GA_INITIALIZED) {
      initGA()
      window.GA_INITIALIZED = true
    }
    logPageView()
  }

现在我想使用 Google Tag Manager 来处理分析页面视图。我怎么能这样做?

【问题讨论】:

    标签: google-tag-manager nextjs


    【解决方案1】:

    为了使用谷歌标签管理器,您应该在每个页面上注入您的标签管理器脚本。因为_document.js 是每个页面的包装器,您应该将GTM 脚本添加到head 部分的_document.js,如下所示:

    <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='+i+dl;f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','GTM-*****');`,
      }}>
      </script>
      ...
    </Head>
    

    现在您已准备好在您的 next-js 应用中使用 Google 跟踪代码管理器。您应该只继续从您的 GTM 仪表板处理综合浏览量和其他与分析相关的内容。

    要为单页应用程序(如 nextjs)设置谷歌分析页面浏览,您可以按照these 步骤操作。

    【讨论】:

    • "dangerouslySetInnerHTML" 看起来很危险!可以让您面临跨站脚本 (XSS) 攻击。
    • @MuhammadRiyaz 只要您确定脚本是安全的并且在这种情况下它是安全的,这并不危险
    • 如果有人设法操纵了 dangerouslySetInnerHTML 中的任何内容,那么你遇到的问题比谷歌分析要大得多。
    • 您也可以在该文本中添加.replace(/\n\s*/g, "") 以删除换行符
    【解决方案2】:

    不需要任何特殊的库,这里的一些答案看起来不完整。只需将脚本添加到&lt;Head&gt; 并将noscript 添加到_document.js 中的&lt;body&gt;

    import Head from 'next/document'  
    
    <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='+i+dl;f.parentNode.insertBefore(j,f);
              })(window,document,'script','dataLayer','GTM-XXXXXX');`}} />
    </Head>
        
    <body style={{ margin: 0 }}>
       <noscript dangerouslySetInnerHTML={{ __html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXX"
            height="0" width="0" style="display:none;visibility:hidden"></iframe>`,
          }}
        />
        <Main />
        <NextScript />
    </body>
    

    【讨论】:

    • 你可能想从next/document而不是next/head导入Head组件。 IE。 import { Head } from 'next/document'。根据 nextjs documentation 的说法,它们并不相同,next/document 的代码更适合所有页面通用的代码。
    • 这应该是公认的答案,因为这将允许 nextjs 返回 HTML 中的代码。 react-gtm-module 将在运行时使用 JavaScript 注入它,因此它不会按预期工作
    【解决方案3】:

    我找到了一种更好的实现方式。我们可以使用react-gtm-module 库。

    正如 Ryan Elainska 在他们的博客中提到的,Google Tag Manager in Next.js 在我的 NextJS 安装的 _app.js 文件中:

    import App, { Container } from 'next/app'
    import React from 'react'
    import './app.css'
    import TagManager from 'react-gtm'
    
    const tagManagerArgs = {
      id: 'GTM-XXXXXXX'
    }
    
    class MyApp extends App {
      componentDidMount () {
        TagManager.initialize(tagManagerArgs)
      }
    
      render () {
        const { Component, pageProps } = this.props
        return (
          <Container>
            <Component {...pageProps} />
          </Container>
        )
      }
    }
    
    export default MyApp
    

    【讨论】:

    • 感谢 _app.js 解决方案。至于代码,'react-gtm' 应该是'react-gtm-module'。在此处转发的原始源博客中是错误的。
    • 和tagManagerArgs = { id: 'GTM-XXXXXXX' } 应该是tagManagerArgs = { gtmId: 'GTM-XXXXXXX' }
    • 这个库对我不起作用,它总是返回 404
    【解决方案4】:

    由于您使用的是 nextJS,因此无需添加来自 Google Analytics 的纯 javascript,您只需要 GA 跟踪 id。

    然后你创建 util 函数:

    export const event = ({ action, category, label, value }) => {
      window.gtag('event', action, {
        event_category: category,
        event_label: label,
        value: value
      })
    }
    

    并将其添加到您的 _document.js 中:

    <script
      dangerouslySetInnerHTML={{
      __html: `
      window.dataLayer = window.dataLayer || [];
      function gtag(){dataLayer.push(arguments);}
      gtag('js', new Date());
      gtag('config', '${GA_TRACKING_ID}');
    `}}
    />
    

    之后,您只需在页面/组件中导入 util 函数并调用:

    gtag.event({
      action: 'submit_form',
      category: 'Contact',
      label: this.state.message
    })
    

    参考:example of NextJS with GA

    【讨论】:

    • 谢谢。这是一个很好的选择。
    【解决方案5】:

    我使用react-gtm-module 并在_app.js 内部componentDidMount 中配置

     componentDidMount() {
        const tagManagerArgs = {
          gtmId = 'GTM-00001'
        }
    
        TagManager.initialize(tagManagerArgs);
      }
    

    这是我在 2020 年 2 月 11 日更新的解决方案

    【讨论】:

      【解决方案6】:

      我在 next.js 应用程序中使用 redux。

      如果你使用 redux,这是一个很好的解决方案:redux-beacon + react-gtm-module。

      这里是初始化代码。此代码可以通过 _app.js 中的钩子或 componentDidMount 触发,如果您使用的是 redux,则可以通过 redux 操作触发。

      const dataLayer = { ...your dataLayer config... }
      const tagManagerArgs = {
        gtmId: process.env.GTM_ID,
        auth: process.env.GTM_AUTH,
        preview: process.env.GTM_PREVIEW,
        dataLayer
      }
      TagManager.initialize(tagManagerArgs)
      

      下面是使用 eventMap 创建的中间件。

      import { EventsMapper, createMiddleware } from 'redux-beacon'
      import GoogleTagManager from '@redux-beacon/google-tag-manager'
      
      const gtm = GoogleTagManager()
      
      export const eventsMap: EventsMapper = action => {
        switch (action.type) {
          default:
            return []
        }
      }
      
      
      export const gtmMiddleware = createMiddleware(eventsMap, gtm)
      

      【讨论】:

        【解决方案7】:

        旧帖子,但我最近在此处写了有关此内容并详细介绍了 2 个解决方案:https://morganfeeney.com/how-to/integrate-google-tag-manager-with-next-js。

        在 Next.js v11.0.0 之前,最简单的方法是使用自定义 _document。

        在自定义 _document 中添加这样的 GTM 脚本:https://nextjs.org/docs/advanced-features/custom-document

        import Head from 'next/document';
        ...
        
        <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='+i+dl;f.parentNode.insertBefore(j,f);
              })(window,document,'script','dataLayer','GTM-XXXX');`,
            }}
          />
        </Head>
        
        <body>
          <Main />
          <NextScript />
          <noscript
            dangerouslySetInnerHTML={{
              __html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXX" height="0" width="0" style="display: none; visibility: hidden;" />`,
            }}
          />
        </body>
        

        但是如何跟踪页面浏览量?

        window.onLoad 在使用客户端路由进行导航时不会触发,因此即使您添加了脚本,它也不会按照您的预期进行。

        我的首选方法是使用这样的函数:

        export const gtmVirtualPageView = (rest) => {
          window.dataLayer?.push({
            event: 'VirtualPageView',
            ...rest,
          });
        };
        

        然后在 _app.tsx 中添加如下配置:

        import '../styles/globals.css';
        import { useEffect } from 'react';
        import { useRouter } from 'next/router'
        import { gtmVirtualPageView } from '../lib/gtm';
        
        function MyApp({ Component, pageProps }) {
          const router = useRouter()
        
          useEffect(() => {
            const mainDataLayer = {
              pageTypeName: pageProps.page || null,
              url: router.pathname,
            };
        
            window.onload = () => window.dataLayer?.push({...mainDataLayer});
        
            gtmVirtualPageView(mainDataLayer);
        
          }, [pageProps])
        
          return <Component {...pageProps} />
        }
        
        export default MyApp
        

        这允许通过pageProps 将数据传递到dataLayer。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-08-31
          • 1970-01-01
          • 1970-01-01
          • 2021-12-03
          • 1970-01-01
          • 2016-12-30
          • 2015-04-30
          • 1970-01-01
          相关资源
          最近更新 更多