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
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:
Best practices Google lighthouse error