xref: /expo/docs/providers/Analytics.tsx (revision 8fc828a4)
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