How to load GTM with NextJS Script component? - next.js

I recently came across the script component in NextJS (https://nextjs.org/docs/basic-features/script)
I wanted to know if it's possible to load Google tag manager using this component.

You can add the following <Script> tags within your _app.tsx file.
// pages/_app.tsx
export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
const getLayout = Component.getLayout ?? ((page) => page)
return getLayout(
<>
<Script id="google-site-tag"
strategy='lazyOnload'
src={`https://www.googletagmanager.com/gtag/js?id=${GOOGLE_TAG_ID}`}
/>
<Script id="google-analytics" strategy='lazyOnload'>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GOOGLE_TAG_ID}');
`}
</Script>
<Component {...pageProps} />
</>
)
}

Related

why is my google analytics not working after deployment on nextjs? [duplicate]

This question already has an answer here:
How to properly set environment variables in Next.js app deployed to Vercel?
(1 answer)
Closed 7 months ago.
just set up google analytics to my site. It was working locally until I converted the api key to an .env.local file. I then added the environment variable on vercel and deployed it and now it just says no data available. Not sure, what happened. Can somebody take a look at my code?
import '../styles/globals.css'
import 'bootstrap/dist/css/bootstrap.css';
import Script from 'next/script'
function MyApp({ Component, pageProps }) {
import('bootstrap/dist/css/bootstrap.css');
return (
<>
<Script
strategy="lazyOnload"
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_GOOGLE}`}/>
<Script strategy="lazyOnload">
{`
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${process.env.NEXT_GOOGLE}');
`}
</Script>
<Component {...pageProps} />
</>
)
}
export default MyApp
fixed this.
was missing the PUBLIC prefix.
should have been NEXT_PUBLIC_GOOGLE

Next.js - How to make sure <title> is set by the time the history change event fires?

In my Next.js app, I'm setting the <title> tag for individual pages using the recommended method:
import Head from 'next/head'
export default () => <>
<Head><title>My page title</title></Head>
</>
Here's the problem: when the history change event fires, the value of document.title doesn't always match the current URL.
You can test it yourself:
Router.events.on("routeChangeComplete", () => {
if ('browser' in process) {
console.log('--------');
console.log(window.location.href);
console.log(document.title);
}
});
Navigating between pages, you should observe that URL & title are often mismatched. The value of URL is always right, but the value of title is all over the place. It can have:
the right value
the value it had on the previous page
no value at all
This is an issue when using analytics, specifically GTM - Google Tag Manager, which uses the current URL & page title to uniquely identify visited pages.
I've had this issue with Next.js 7, and upgrading to 8 hasn't fixed it.
Do you know of any way to solve this problem? Maybe delaying the history change event until the first render of a component under /pages/?
Thanks!
This is a small hack. setTimeout(()=>{console.log(document.title)}, 0)
I found a work-around by intercepting events sent to window.dataLayer.push and adding a one-second delay in case the event is gtm.historyChange.
Here's my GtagScript component that I'm adding to <Head> under _document.js:
export const GtagScript = () => {
function intercept() {
const scriptTag = document.querySelector('#gtm-js');
if (scriptTag !== null)
scriptTag.addEventListener('load', () => {
window.dataLayer.pushOrig = window.dataLayer.push;
window.dataLayer.push = (e) => {
if (e.event === 'gtm.historyChange') {
setTimeout(function () {
window.dataLayer.pushOrig(e);
console.log(`URL: ${window.location.href} Title: ${document.title}`);
}, 1000);
} else {
window.dataLayer.pushOrig(e);
}
};
});
}
return <>
<script
id="gtm-js"
async
src={`https://www.googletagmanager.com/gtm.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}');
${intercept.toString()}
intercept();`
}}
/>
</>
};
I'll wait a while to see if an official fix comes from the ZEIT team. My solution doesn't actually answer the question. It doesn't set <title>, it just defers the event, which isn't optimal.
You can use setInterval
const firstPageViewEvent = setInterval(() => {
if (document.title) {
// send pageview event
clearInterval(firstPageViewEvent);
}
}, 200);

Cross Domain Tracking with Global Site Tag - What goes where?

Having some issues with the implementation of cross domain tracking with the Gtag.js. I'm trying to do CDT for a restaurant website which has an external booking system with a 5 different URLs (1 for each restaurant booking system). I'm using the same GA property, but have failed to figure out if the Gtag.js is set up correctly. Here's what I have on the restaurant business domain:
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXX-
1">
</script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-XXXXXXX-1', {
'linker': {
'domains' [
'https://restaurant.bookingpage1.com',
'https://restaurant.bookingpage2.com',
'https://restaurant.bookingpage3.com',
'https://restaurant.bookingpage4.com',
'https://restaurant.bookingpage5.com']
}
});
</script>
Then, on the restaurant.bookingpage1-5, I should implement:
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-
XXXXXXX-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-XXXXXXX-1', {
'linker': {
'accept_incoming': true
}
});
</script>
Afterwards, I implemented the restaurant main domain as a referral exclusion in Analytics.
Can anyone see if this is correctly set up?
You missed the colon after domains
gtag('config', 'UA-XXXXXXX-1', {
'linker': {
'domains' [

Injecting Google Analytics dynamically

I'm trying to inject Google Analytics on acceptance of cookies due to GDPR. I've embedded most of the GA code in a function enableGoogleAnalytics() as seen below.
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXX-X"></script>
<script>
function enableGoogleAnalytics() {
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments)};
gtag('js', new Date());
gtag('config', 'UA-XXXXX-X');
}
</script>
Should I be injecting the first line dynamically (shown below) as well? If so, is there are a straightforward way?
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXX-X"></script>
Thanks,

How to configure a site to automatically link domains

Source:
https://developers.google.com/analytics/devguides/collection/gtagjs/cross-domain#configuring_a_site_to_accept_linker_parameters
Reference:
If the destination domain has been configured to automatically link domains, it will accept linker parameters by default.
I assume there is an HTML based solution for me to implement configuring a destination domain to automatically link domains.
How can I do this?
We have been using this approach. I'm not sure if it is correct, but it is an answer.
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-XXXXXXXX"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-66686611-1', {
'linker': {
'domains': ['every.com','domain.com','that.com','I.com','will.com','link.com','to.com','or.com','from.com'],
'accept_incoming': true,
'decorate_forms': true
},
});
</script>

Resources