/** * usePageTracking - Automatic page view tracking for React Router * * This hook automatically tracks page views when the route changes. * Place it in your root layout component. */ import { useEffect, useRef } from 'react'; import { useLocation } from 'react-router-dom'; // or your router of choice import { useAnalytics } from '@analytics/client/react'; interface PageTrackingOptions { /** * Extract page title from the current route. * Default: Uses document.title */ getPageTitle?: (pathname: string) => string; /** * Additional metadata to include with every page view. */ metadata?: Record; /** * Skip tracking for certain paths. */ excludePaths?: string[]; } /** * Track page views automatically on route changes. * * @example * ```tsx * function RootLayout({ children }) { * usePageTracking(); * return
{children}
; * } * ``` */ export function usePageTracking(options: PageTrackingOptions = {}) { const { trackView } = useAnalytics(); const location = useLocation(); const previousPathRef = useRef(null); const { getPageTitle = () => document.title, metadata = {}, excludePaths = [], } = options; useEffect(() => { const currentPath = location.pathname; // Skip if path is excluded if (excludePaths.some((path) => currentPath.startsWith(path))) { return; } // Skip if same path (prevents double-tracking on hash changes) if (previousPathRef.current === currentPath) { return; } previousPathRef.current = currentPath; // Small delay to ensure document.title is updated const timeoutId = setTimeout(() => { trackView({ pageUrl: window.location.href, pageTitle: getPageTitle(currentPath), ...metadata, }); }, 0); return () => clearTimeout(timeoutId); }, [location.pathname, trackView, getPageTitle, metadata, excludePaths]); } /** * Example with custom page titles: * * ```tsx * const PAGE_TITLES: Record = { * '/': 'Home', * '/products': 'Products', * '/about': 'About Us', * }; * * function RootLayout({ children }) { * usePageTracking({ * getPageTitle: (pathname) => PAGE_TITLES[pathname] || 'My App', * excludePaths: ['/admin', '/api'], * }); * * return
{children}
; * } * ``` */