"use client"; import React, { useEffect, Suspense } from "react"; import { useSafePathname, useSafeSearchParams } from "./analytics/useSafePathname"; import { ScrollDepthTracker } from "./analytics/ScrollDepthTracker"; import { getDefaultAnalytics } from "../utils/analytics"; import { getDefaultErrorTracking } from "../utils/error-tracking"; const AnalyticsInner: React.FC = () => { const pathname = useSafePathname(); const searchParams = useSafeSearchParams(); // Track pageviews on route change useEffect(() => { if (!pathname) return; const analytics = getDefaultAnalytics(); const url = `${pathname}${searchParams?.size ? `?${searchParams.toString()}` : ""}`; analytics.page(url); }, [pathname, searchParams]); useEffect(() => { const analytics = getDefaultAnalytics(); const errorTracking = getDefaultErrorTracking(); // Track page load performance const trackPageLoad = () => { // ... existing implementation ... const perfData = performance.getEntriesByType( "navigation", )[0] as PerformanceNavigationTiming; if ( perfData && typeof perfData.loadEventEnd === "number" && typeof perfData.startTime === "number" ) { const loadTime = perfData.loadEventEnd - perfData.startTime; analytics.trackPageLoad( loadTime, window.location.pathname, navigator.userAgent, ); } }; // Track outbound links const trackOutboundLinks = () => { document.querySelectorAll('a[href^="http"]').forEach((link) => { const anchor = link as HTMLAnchorElement; if (!anchor.href.includes(window.location.hostname)) { anchor.addEventListener("click", () => { analytics.trackOutboundLink( anchor.href, anchor.textContent?.trim() || "unknown", ); }); } }); }; // Track search const trackSearch = () => { const searchInput = document.querySelector( 'input[type="search"]', ) as HTMLInputElement; if (searchInput) { const handleSearch = (e: Event) => { const target = e.target as HTMLInputElement; if (target.value) { analytics.trackSearch(target.value, window.location.pathname); } }; searchInput.addEventListener("search", handleSearch); return () => searchInput.removeEventListener("search", handleSearch); } }; // Global error handler for error tracking const handleGlobalError = (event: ErrorEvent) => { errorTracking.captureException(event.error || event.message); }; const handleUnhandledRejection = (event: PromiseRejectionEvent) => { errorTracking.captureException(event.reason); }; window.addEventListener("error", handleGlobalError); window.addEventListener("unhandledrejection", handleUnhandledRejection); // Initial load tracking if (document.readyState === "complete") { trackPageLoad(); trackOutboundLinks(); const cleanupSearch = trackSearch(); return () => { if (cleanupSearch) cleanupSearch(); window.removeEventListener("error", handleGlobalError); window.removeEventListener( "unhandledrejection", handleUnhandledRejection, ); }; } else { window.addEventListener("load", () => { trackPageLoad(); trackOutboundLinks(); // search tracking might need to wait for hydration/render }); // Fallback/standard cleanup return () => { window.removeEventListener("error", handleGlobalError); window.removeEventListener( "unhandledrejection", handleUnhandledRejection, ); }; } }, []); const analytics = getDefaultAnalytics(); const adapter = analytics.getAdapter(); const scriptTag = adapter.getScriptTag ? adapter.getScriptTag() : null; return ( <> {scriptTag && (
)} ); }; export const Analytics: React.FC = () => { return ( ); };