Skip to content

Commit f32d8c9

Browse files
authored
Feature/ga4 (#15)
1 parent 23b1b1d commit f32d8c9

File tree

7 files changed

+121
-1
lines changed

7 files changed

+121
-1
lines changed

index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
<!doctype html>
22
<html lang="en">
33
<head>
4+
<!-- Google tag (gtag.js) -->
5+
<script async src="https://www.googletagmanager.com/gtag/js?id=G-LKVJ6R5XLV"></script>
6+
<script>
7+
window.dataLayer = window.dataLayer || [];
8+
function gtag() {
9+
dataLayer.push(arguments);
10+
}
11+
gtag('js', new Date());
12+
13+
gtag('config', 'G-LKVJ6R5XLV');
14+
</script>
15+
416
<meta charset="UTF-8" />
517
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
618
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

src/components/Footer/Footer.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Box, Container, Link, Stack, Typography } from '@mui/material';
2+
import { createTrackedLinkHandler } from '../../services/analytics-handlers.ts';
23

34
export const Footer = () => {
45
return (
@@ -27,6 +28,11 @@ export const Footer = () => {
2728
target="_blank"
2829
rel="noreferrer"
2930
underline="hover"
31+
onClick={createTrackedLinkHandler('npm', {
32+
location: 'footer',
33+
url: 'https://github.com/dfsyncjs/dfsync',
34+
label: 'npm',
35+
})}
3036
>
3137
npm
3238
</Link>
@@ -35,6 +41,11 @@ export const Footer = () => {
3541
target="_blank"
3642
rel="noreferrer"
3743
underline="hover"
44+
onClick={createTrackedLinkHandler('github', {
45+
location: 'footer',
46+
url: 'https://github.com/dfsyncjs/dfsync',
47+
label: 'GitHub',
48+
})}
3849
>
3950
GitHub
4051
</Link>

src/components/Header/Header.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { AppBar, Box, Button, Container, Toolbar } from '@mui/material';
33
import { Link as RouterLink } from 'react-router-dom';
44
import { Brand } from '../Brand/Brand';
55
import { ThemeToggle } from '../ThemeToggle/ThemeToggle';
6+
import { createTrackedLinkHandler } from '../../services/analytics-handlers.ts';
67

78
export const Header = () => {
89
return (
@@ -20,14 +21,28 @@ export const Header = () => {
2021
<Toolbar disableGutters sx={{ minHeight: 72, gap: 2, justifyContent: 'space-between' }}>
2122
<Brand />
2223
<Box sx={{ flexShrink: 0 }}>
23-
<Button component={RouterLink} to="/docs" color="inherit">
24+
<Button
25+
component={RouterLink}
26+
to="/docs"
27+
color="inherit"
28+
onClick={createTrackedLinkHandler('docs', {
29+
location: 'header',
30+
url: 'https://github.com/dfsyncjs/dfsync',
31+
label: 'Docs',
32+
})}
33+
>
2434
Docs
2535
</Button>
2636
<Button
2737
color="inherit"
2838
href="https://www.npmjs.com/package/@dfsync/client"
2939
target="_blank"
3040
rel="noreferrer"
41+
onClick={createTrackedLinkHandler('npm', {
42+
location: 'header',
43+
url: 'https://github.com/dfsyncjs/dfsync',
44+
label: 'npm',
45+
})}
3146
>
3247
npm
3348
</Button>
@@ -37,6 +52,11 @@ export const Header = () => {
3752
target="_blank"
3853
rel="noreferrer"
3954
startIcon={<GitHubIcon />}
55+
onClick={createTrackedLinkHandler('github', {
56+
location: 'header',
57+
url: 'https://github.com/dfsyncjs/dfsync',
58+
label: 'GitHub',
59+
})}
4060
>
4161
GitHub
4262
</Button>

src/components/Hero/Hero.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Box, Button, Chip, Container, Stack, Typography } from '@mui/material';
44
import { Link as RouterLink } from 'react-router-dom';
55
import { InstallCommand } from '../InstallCommand/InstallCommand';
66
import { ProjectBadges } from '../ProjectBadges/ProjectBadges.tsx';
7+
import { createTrackedLinkHandler } from '../../services/analytics-handlers.ts';
78

89
export const Hero = () => {
910
return (
@@ -74,6 +75,11 @@ export const Hero = () => {
7475
target="_blank"
7576
rel="noreferrer"
7677
endIcon={<OpenInNewIcon />}
78+
onClick={createTrackedLinkHandler('npm', {
79+
location: 'hero',
80+
url: 'https://github.com/dfsyncjs/dfsync',
81+
label: 'View on npm',
82+
})}
7783
>
7884
View on npm
7985
</Button>
@@ -84,6 +90,11 @@ export const Hero = () => {
8490
size="medium"
8591
to="/docs"
8692
startIcon={<ListIcon />}
93+
onClick={createTrackedLinkHandler('docs', {
94+
location: 'hero',
95+
url: 'https://github.com/dfsyncjs/dfsync',
96+
label: 'Documentation',
97+
})}
8798
>
8899
Documentation
89100
</Button>

src/services/analytics-handlers.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Analytics } from './analytics';
2+
3+
export function createTrackedLinkHandler(
4+
ctaName: string,
5+
options: {
6+
location?: string;
7+
url?: string;
8+
label?: string;
9+
},
10+
) {
11+
return () => {
12+
Analytics.trackCta(ctaName, options);
13+
};
14+
}

src/services/analytics.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
type AnalyticsEventName = 'cta_click' | 'page_view' | 'custom_event';
2+
3+
type CtaName = 'github' | 'npm' | 'docs';
4+
5+
type TrackEventParams = Record<string, string | number | boolean | undefined>;
6+
7+
export class Analytics {
8+
private static isEnabled(): boolean {
9+
return typeof window !== 'undefined' && typeof window.gtag === 'function';
10+
}
11+
12+
static track(eventName: AnalyticsEventName | string, params?: TrackEventParams): void {
13+
if (!this.isEnabled()) return;
14+
15+
window.gtag!('event', eventName, params ?? {});
16+
}
17+
18+
static trackCta(
19+
ctaName: CtaName | string,
20+
params?: {
21+
location?: string;
22+
url?: string;
23+
label?: string;
24+
},
25+
): void {
26+
this.track('cta_click', {
27+
cta_name: ctaName,
28+
location: params?.location,
29+
link_url: params?.url,
30+
label: params?.label,
31+
});
32+
}
33+
34+
static trackPageView(path: string, title?: string): void {
35+
if (!this.isEnabled()) return;
36+
37+
window.gtag!('event', 'page_view', {
38+
page_path: path,
39+
page_title: title,
40+
page_location: typeof window !== 'undefined' ? window.location.href : undefined,
41+
});
42+
}
43+
}

src/types/global.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
3+
export {};
4+
5+
declare global {
6+
interface Window {
7+
gtag?: (...args: any[]) => void;
8+
}
9+
}

0 commit comments

Comments
 (0)