1import { NextWebVitalsMetric } from 'next/app'; 2import { useRouter } from 'next/router'; 3import Script from 'next/script'; 4import React, { PropsWithChildren, useEffect } from 'react'; 5 6/** The global analytics measurement ID */ 7const MEASUREMENT_ID = 'UA-107832480-3'; 8 9type AnalyticsProps = PropsWithChildren<object>; 10 11/** 12 * @see https://nextjs.org/docs/messages/next-script-for-ga 13 * @see https://nextjs.org/docs/basic-features/script#lazyonload 14 */ 15export function AnalyticsProvider(props: AnalyticsProps) { 16 const { events } = useRouter(); 17 18 useEffect(function didMount() { 19 events.on('routeChangeComplete', reportPageView); 20 return function didUnmount() { 21 events.off('routeChangeComplete', reportPageView); 22 }; 23 }, []); 24 25 return ( 26 <> 27 <Script 28 strategy="lazyOnload" 29 src={`https://www.googletagmanager.com/gtag/js?id=${MEASUREMENT_ID}`} 30 /> 31 <Script strategy="lazyOnload">{` 32 window.dataLayer = window.dataLayer || []; 33 function gtag(){dataLayer.push(arguments);} 34 gtag('js', new Date()); 35 gtag('config', '${MEASUREMENT_ID}', { 'transport_type': 'beacon', 'anonymize_ip': true }); 36 `}</Script> 37 {props.children} 38 </> 39 ); 40} 41 42export function reportPageView(url: string) { 43 window?.gtag?.('config', MEASUREMENT_ID, { 44 page_path: url, 45 transport_type: 'beacon', 46 anonymize_ip: true, 47 }); 48} 49 50export function reportWebVitals({ id, name, label, value }: NextWebVitalsMetric) { 51 window?.gtag?.('event', name, { 52 event_category: label === 'web-vital' ? 'Web Vitals' : 'Next.js custom metric', 53 // Google Analytics metrics must be integers, so the value is rounded. 54 // For CLS the value is first multiplied by 1000 for greater precision 55 // (note: increase the multiplier for greater precision if needed). 56 value: Math.round(name === 'CLS' ? value * 1000 : value), 57 // The `id` value will be unique to the current page load. When sending 58 // multiple values from the same page (e.g. for CLS), Google Analytics can 59 // compute a total by grouping on this ID (note: requires `eventLabel` to 60 // be a dimension in your report). 61 event_label: id, 62 // Use a non-interaction event to avoid affecting bounce rate. 63 non_interaction: true, 64 anonymize_ip: true, 65 }); 66} 67