UNPKG

@optic7409/resolvo-analytics

Version:

Simplified analytics client library for Next.js with automatic SSR handling, one-line integration, and comprehensive tracking

162 lines (161 loc) 7.48 kB
import { useEffect, useState } from 'react'; import { AnalyticsClient } from '../../core/AnalyticsClient'; import { detectEnvironment, shouldEnableAnalytics } from '../../utils/environment'; let globalClient = null; let isInitialized = false; export function PageTracker({ config }) { const [isReady, setIsReady] = useState(false); const [error, setError] = useState(null); useEffect(() => { // SSR Safety: Don't run on server unless explicitly enabled if (typeof window === 'undefined' && !config.ssr) { return; } // Check if analytics should be enabled if (!shouldEnableAnalytics(config)) { return; } try { // Initialize client if not already done if (!globalClient && !isInitialized) { globalClient = new AnalyticsClient(config); isInitialized = true; if (config.debug) { console.log('[Resolvo Analytics] Initialized with config:', config); } } // Track initial page load const trackCurrentPage = () => { if (typeof window !== 'undefined' && globalClient) { const url = window.location.href; const title = document.title; globalClient.trackPageView(url, title).catch(err => { if (config.debug) { console.error('[Resolvo Analytics] Error tracking page view:', err); } }); } }; // Track initial page after a small delay to ensure everything is loaded const initialTimer = setTimeout(() => { trackCurrentPage(); setIsReady(true); }, 100); // Setup route change tracking based on framework const env = detectEnvironment(); let cleanup; if (env.framework === 'nextjs') { // Next.js specific route tracking if (env.routerType === 'app') { // App Router - use navigation events const handleRouteChange = () => { setTimeout(() => { if (globalClient) { const url = window.location.href; const title = document.title; globalClient.trackPageView(url, title).catch(err => { if (config.debug) { console.error('[Resolvo Analytics] Error tracking route change:', err); } }); } }, 100); }; // Listen for navigation events window.addEventListener('popstate', handleRouteChange); // For App Router, we also need to listen for pushState/replaceState const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function (...args) { originalPushState.apply(history, args); handleRouteChange(); }; history.replaceState = function (...args) { originalReplaceState.apply(history, args); handleRouteChange(); }; cleanup = () => { window.removeEventListener('popstate', handleRouteChange); history.pushState = originalPushState; history.replaceState = originalReplaceState; }; } else { // Pages Router - use Next.js router events try { const { useRouter } = require('next/router'); const router = useRouter(); const handleRouteChange = (url) => { setTimeout(() => { if (globalClient) { const title = document.title; globalClient.trackPageView(url, title).catch(err => { if (config.debug) { console.error('[Resolvo Analytics] Error tracking route change:', err); } }); } }, 100); }; router.events.on('routeChangeComplete', handleRouteChange); cleanup = () => { router.events.off('routeChangeComplete', handleRouteChange); }; } catch (err) { if (config.debug) { console.warn('[Resolvo Analytics] Could not set up Next.js router tracking:', err); } } } } else { // Generic React/SPA route tracking const handleRouteChange = () => { setTimeout(() => { if (globalClient) { const url = window.location.href; const title = document.title; globalClient.trackPageView(url, title).catch(err => { if (config.debug) { console.error('[Resolvo Analytics] Error tracking route change:', err); } }); } }, 100); }; window.addEventListener('popstate', handleRouteChange); cleanup = () => { window.removeEventListener('popstate', handleRouteChange); }; } // Provide global access to analytics if (typeof window !== 'undefined' && globalClient) { window.analytics = { track: (event, properties) => globalClient?.track(event, properties), identify: (userId, properties) => globalClient?.identify(userId, properties), trackPageView: (url, title) => globalClient?.trackPageView(url, title), client: globalClient }; } return () => { clearTimeout(initialTimer); if (cleanup) { cleanup(); } }; } catch (err) { const errorMessage = err instanceof Error ? err.message : 'Unknown error'; setError(errorMessage); if (config.debug) { console.error('[Resolvo Analytics] Initialization error:', err); } } }, [config]); // Show error in development if (error && config.debug && typeof window !== 'undefined') { console.error('[Resolvo Analytics] Error:', error); } return null; // This component doesn't render anything }