diff --git a/index.html b/index.html
index 0053b62..9860ac4 100644
--- a/index.html
+++ b/index.html
@@ -1,6 +1,18 @@
+
+
+
+
diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx
index 329fd05..0b52cf3 100644
--- a/src/components/Footer/Footer.tsx
+++ b/src/components/Footer/Footer.tsx
@@ -1,4 +1,5 @@
import { Box, Container, Link, Stack, Typography } from '@mui/material';
+import { createTrackedLinkHandler } from '../../services/analytics-handlers.ts';
export const Footer = () => {
return (
@@ -27,6 +28,11 @@ export const Footer = () => {
target="_blank"
rel="noreferrer"
underline="hover"
+ onClick={createTrackedLinkHandler('npm', {
+ location: 'footer',
+ url: 'https://github.com/dfsyncjs/dfsync',
+ label: 'npm',
+ })}
>
npm
@@ -35,6 +41,11 @@ export const Footer = () => {
target="_blank"
rel="noreferrer"
underline="hover"
+ onClick={createTrackedLinkHandler('github', {
+ location: 'footer',
+ url: 'https://github.com/dfsyncjs/dfsync',
+ label: 'GitHub',
+ })}
>
GitHub
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
index 302ed4e..f829ae0 100644
--- a/src/components/Header/Header.tsx
+++ b/src/components/Header/Header.tsx
@@ -3,6 +3,7 @@ import { AppBar, Box, Button, Container, Toolbar } from '@mui/material';
import { Link as RouterLink } from 'react-router-dom';
import { Brand } from '../Brand/Brand';
import { ThemeToggle } from '../ThemeToggle/ThemeToggle';
+import { createTrackedLinkHandler } from '../../services/analytics-handlers.ts';
export const Header = () => {
return (
@@ -20,7 +21,16 @@ export const Header = () => {
-
diff --git a/src/components/Hero/Hero.tsx b/src/components/Hero/Hero.tsx
index 103deb1..4b4b1b8 100644
--- a/src/components/Hero/Hero.tsx
+++ b/src/components/Hero/Hero.tsx
@@ -4,6 +4,7 @@ import { Box, Button, Chip, Container, Stack, Typography } from '@mui/material';
import { Link as RouterLink } from 'react-router-dom';
import { InstallCommand } from '../InstallCommand/InstallCommand';
import { ProjectBadges } from '../ProjectBadges/ProjectBadges.tsx';
+import { createTrackedLinkHandler } from '../../services/analytics-handlers.ts';
export const Hero = () => {
return (
@@ -74,6 +75,11 @@ export const Hero = () => {
target="_blank"
rel="noreferrer"
endIcon={}
+ onClick={createTrackedLinkHandler('npm', {
+ location: 'hero',
+ url: 'https://github.com/dfsyncjs/dfsync',
+ label: 'View on npm',
+ })}
>
View on npm
@@ -84,6 +90,11 @@ export const Hero = () => {
size="medium"
to="/docs"
startIcon={}
+ onClick={createTrackedLinkHandler('docs', {
+ location: 'hero',
+ url: 'https://github.com/dfsyncjs/dfsync',
+ label: 'Documentation',
+ })}
>
Documentation
diff --git a/src/services/analytics-handlers.ts b/src/services/analytics-handlers.ts
new file mode 100644
index 0000000..3be3b2c
--- /dev/null
+++ b/src/services/analytics-handlers.ts
@@ -0,0 +1,14 @@
+import { Analytics } from './analytics';
+
+export function createTrackedLinkHandler(
+ ctaName: string,
+ options: {
+ location?: string;
+ url?: string;
+ label?: string;
+ },
+) {
+ return () => {
+ Analytics.trackCta(ctaName, options);
+ };
+}
diff --git a/src/services/analytics.ts b/src/services/analytics.ts
new file mode 100644
index 0000000..3152f4f
--- /dev/null
+++ b/src/services/analytics.ts
@@ -0,0 +1,43 @@
+type AnalyticsEventName = 'cta_click' | 'page_view' | 'custom_event';
+
+type CtaName = 'github' | 'npm' | 'docs';
+
+type TrackEventParams = Record;
+
+export class Analytics {
+ private static isEnabled(): boolean {
+ return typeof window !== 'undefined' && typeof window.gtag === 'function';
+ }
+
+ static track(eventName: AnalyticsEventName | string, params?: TrackEventParams): void {
+ if (!this.isEnabled()) return;
+
+ window.gtag!('event', eventName, params ?? {});
+ }
+
+ static trackCta(
+ ctaName: CtaName | string,
+ params?: {
+ location?: string;
+ url?: string;
+ label?: string;
+ },
+ ): void {
+ this.track('cta_click', {
+ cta_name: ctaName,
+ location: params?.location,
+ link_url: params?.url,
+ label: params?.label,
+ });
+ }
+
+ static trackPageView(path: string, title?: string): void {
+ if (!this.isEnabled()) return;
+
+ window.gtag!('event', 'page_view', {
+ page_path: path,
+ page_title: title,
+ page_location: typeof window !== 'undefined' ? window.location.href : undefined,
+ });
+ }
+}
diff --git a/src/types/global.d.ts b/src/types/global.d.ts
new file mode 100644
index 0000000..8a29751
--- /dev/null
+++ b/src/types/global.d.ts
@@ -0,0 +1,9 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+
+export {};
+
+declare global {
+ interface Window {
+ gtag?: (...args: any[]) => void;
+ }
+}