Skip to content

Commit ab22281

Browse files
authored
Merge pull request #161 from dassiorleando/feat/googleAnalytics
Allowed Google Analytics tracking
2 parents 479a9ee + bf1b555 commit ab22281

File tree

5 files changed

+86
-0
lines changed

5 files changed

+86
-0
lines changed

‎README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ Play with the [Demo](https://next.jamify.org/) to get a first impression.
9393
<li>Syntax highlighting with PrismJS</li>
9494
<li>Table Of Contents</li>
9595
<li>Contact Page with built-in notification service</li>
96+
<li>Google Analytics</li>
9697
</ul>
9798
</details>
9899
<details>

‎appConfig.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
// Cache control
77
export const fileCache: boolean = true
88

9+
// Google analytics tracking ID (now called measurement ID in version 4)
10+
export const gaMeasurementId: string = 'UA-XXXXXXX_or_G-XXXXXXX'
11+
912
// Dark mode
1013
export type DarkMode = 'dark' | 'light' | null
1114
export const defaultMode: DarkMode = 'light'

‎lib/gtag.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* GA integration
3+
* https://github.com/vercel/next.js/tree/canary/examples/with-google-analytics
4+
*/
5+
import { processEnv } from '@lib/processEnv'
6+
7+
export const GA_TRACKING_ID = processEnv.gaMeasurementId
8+
9+
/**
10+
* Custom event type for Google Analytics.
11+
* The action field is required.
12+
*/
13+
export interface EventType {
14+
action: string,
15+
category?: string,
16+
label?: string,
17+
value?: string
18+
}
19+
20+
/**
21+
* Triggers a GA page view event.
22+
* @link https://developers.google.com/analytics/devguides/collection/gtagjs/pages
23+
*
24+
* @param {string} url The URL to save the page view event with.
25+
*/
26+
export const pageview = (url: string): void => {
27+
(window as any).gtag('config', GA_TRACKING_ID, {
28+
page_path: url,
29+
})
30+
}
31+
32+
/**
33+
* Pushes a custom GA event.
34+
* @link https://developers.google.com/analytics/devguides/collection/gtagjs/events
35+
*
36+
* @param {EventType} parameters The event parameters.
37+
*/
38+
export const event = ({ action, category, label, value }: EventType): void => {
39+
(window as any).gtag('event', action, {
40+
event_category: category,
41+
event_label: label,
42+
value: value,
43+
})
44+
}

‎lib/processEnv.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ function reolveJSON<T>(value: string | undefined, defaultValue: T) {
3535
export interface ProcessEnvProps {
3636
siteUrl: string
3737
platform: string
38+
gaMeasurementId: string
3839
darkMode: {
3940
defaultMode: appConfig.DarkMode
4041
overrideOS: boolean
@@ -73,6 +74,7 @@ export interface ProcessEnvProps {
7374
export const processEnv: ProcessEnvProps = {
7475
siteUrl,
7576
platform,
77+
gaMeasurementId: process.env.JAMIFY_GA_MEASUREMENT_ID || appConfig.gaMeasurementId,
7678
darkMode: {
7779
defaultMode: resolveDarkMode(process.env.JAMIFY_DARK_MODE_DEFAULT, appConfig.defaultMode),
7880
overrideOS: resolveBool(process.env.JAMIFY_DARK_MODE_OVERRIDE_OS, appConfig.overrideOS),

‎pages/_app.tsx

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1+
import { useEffect } from 'react'
2+
import Script from 'next/script'
13
import { AppProps } from 'next/app'
4+
import { useRouter } from 'next/router'
25
import { OverlayProvider } from '@components/contexts/overlayProvider'
36
import { ThemeProvider } from '@components/contexts/themeProvider'
47
import { processEnv } from '@lib/processEnv'
8+
import * as gtag from '../lib/gtag'
59

610
import '@styles/screen.css'
711
import '@styles/screen-fixings.css'
@@ -10,9 +14,41 @@ import '@styles/prism.css'
1014
import '@styles/toc.css'
1115

1216
function App({ Component, pageProps }: AppProps) {
17+
const router = useRouter()
18+
19+
useEffect(() => {
20+
const handleRouteChange = (url: string) => {
21+
gtag.pageview(url)
22+
}
23+
router.events.on('routeChangeComplete', handleRouteChange)
24+
return () => {
25+
router.events.off('routeChangeComplete', handleRouteChange)
26+
}
27+
}, [router.events])
28+
1329
return (
1430
<ThemeProvider {...processEnv.darkMode} >
1531
<OverlayProvider >
32+
{/* Global site tag (gtag.js) - Google Analytics */}
33+
<Script
34+
strategy="afterInteractive"
35+
src={`https://www.googletagmanager.com/gtag/js?id=${gtag.GA_TRACKING_ID}`}
36+
/>
37+
<Script
38+
id="gtag-init"
39+
strategy="afterInteractive"
40+
dangerouslySetInnerHTML={{
41+
__html: `
42+
window.dataLayer = window.dataLayer || [];
43+
function gtag(){dataLayer.push(arguments);}
44+
gtag('js', new Date());
45+
46+
gtag('config', '${gtag.GA_TRACKING_ID}', {
47+
page_path: window.location.pathname,
48+
});
49+
`,
50+
}}
51+
/>
1652
<Component {...pageProps} />
1753
</OverlayProvider>
1854
</ThemeProvider>

0 commit comments

Comments
 (0)