Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

next.js - How to add GTM in nextJS typescript (window.dataLayer is not a function)

I am implementing GTM on my website, but my NextJS project is in Typescript. I used the example of Github the example of Github, but this error appears: TypeError: window.dataLayer is not a function image

This is my gtm.js file:

export const GTM_ID = process.env.TAG_MANAGER

export const pageview = (url) => {
  window.dataLayer({
    event: 'pageview',
    page: url,
  })
}

Yes, the GTM is in js, but all my project is in ts/tsx

My _app.tsx and my _document.tsx are the same as the example of vercel, i created the component and the .env with the ID.

Everything is the same as the example that was supposed to work.

EDIT

i CHANGED SOMETHINGS

My _document.tsx:

import Document, { DocumentContext, DocumentInitialProps, Head, Html, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'
import favicon from '../assets/favicon.ico'
import { GA_TRACKING_ID } from '../lib/gtag'
import { GTM_ID } from '../lib/gtm'

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext): Promise<DocumentInitialProps> { //oda func async recebe promise
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }

  render(): JSX.Element {
    //change HTML lang
    return(
      <Html lang={"pt"}>
        <Head>
          <meta charSet="utf-8" />
          <link rel="preconnect" href="https://fonts.gstatic.com"></link>
          <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap" rel="stylesheet"></link>
          <link rel="icon" href={favicon} />
          <meta name="theme-color" content="#448757" />
          <link rel="apple-touch-icon" href={favicon}></link>

          {/* Global Site Tag (gtag.js) - Google Analytics */}
          <script
            async
            src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`}
          />
          <script
            dangerouslySetInnerHTML={{
              __html: `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
            gtag('config', '${GA_TRACKING_ID}', {
              page_path: window.location.pathname,
            });
          `,
            }}
          />

          {/* Google Tag Manager - Global base code */}
          <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_ID}');
              `,
            }}
          />

        </Head>
        <body>
          <noscript>
            <iframe
              src={`https://www.googletagmanager.com/ns.html?id=${GTM_ID}`}
              height="0"
              width="0"
              style={{ display: 'none', visibility: 'hidden' }}
            />
          </noscript>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

My _app.tsx:

import { AppProps } from 'next/app'
import GlobalStyles  from '../styles/GlobalStyles'
import dynamic from 'next/dynamic'
import { traducao } from '../translate/index'
import { useRouter, Router } from "next/router"
import * as gtag from '../lib/gtag'
import { GTMPageView } from '../lib/gtm'
import React, { useEffect } from 'react';

const MyApp: React.FC<AppProps> = ({ Component, pageProps }) => {
  //Gtag
  const router = useRouter()
    useEffect(() => {
      const handleRouteChange = (url) => {
        gtag.pageview(url)
      }

      router.events.on('routeChangeComplete', handleRouteChange)
        return () => {
          router.events.off('routeChangeComplete', handleRouteChange)
      }
    }, [router.events])


    // Initiate GTM
    useEffect(() => {
      const handleRouteChange = (url: string) => GTMPageView(url);
      Router.events.on('routeChangeComplete', handleRouteChange);
      return () => {
          Router.events.off('routeChangeComplete', handleRouteChange);
      };
    }, []);
  return (
    <>
      <Component {...pageProps}/>
      <GlobalStyles />
    </>
  )
}

export default MyApp

My new gtm.ts:

export const GTM_ID = process.env.NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID


export const GTMPageView = (url: string) => {
  interface PageEventProps {
      event: string;
      page: string;
  }

  const pageEvent: PageEventProps = {
      event: 'pageview',
      page: url,
  };
  //@ts-ignore
  window && window.dataLayer && window.dataLayer.push(pageEvent);
  return pageEvent;
};

WORKED WELL

But I don't know if it works in GTM, because my site is still under development (localhost)...

The window.datalayer script error gone, but know this is my lighthouse:

image

Best practices Google lighthouse error


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...