- Added global ScrollDepthTracker (25%, 50%, 75%, 100%) - Implemented ProductEngagementTracker for deep product analytics - Added field-level tracking to ContactForm and RequestQuoteForm - Standardized SEO metadata (canonical, alternates, x-default) across all routes - Created reusable TrackedLink and TrackedButton components for server components - Fixed 'useAnalytics' hook error in Footer.tsx by adding 'use client'
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useRef } from 'react';
|
|
import { usePathname } from 'next/navigation';
|
|
import { useAnalytics } from './useAnalytics';
|
|
import { AnalyticsEvents } from './analytics-events';
|
|
|
|
/**
|
|
* ScrollDepthTracker
|
|
* Tracks user scroll progress across pages.
|
|
* Fires events at 25%, 50%, 75%, and 100% depth.
|
|
*/
|
|
export default function ScrollDepthTracker() {
|
|
const pathname = usePathname();
|
|
const { trackEvent } = useAnalytics();
|
|
const trackedDepths = useRef<Set<number>>(new Set());
|
|
|
|
// Reset tracking when path changes
|
|
useEffect(() => {
|
|
trackedDepths.current.clear();
|
|
}, [pathname]);
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => {
|
|
const scrollY = window.scrollY;
|
|
const windowHeight = window.innerHeight;
|
|
const documentHeight = document.documentElement.scrollHeight;
|
|
|
|
// Calculate how far the user has scrolled in percentage
|
|
// documentHeight - windowHeight is the total scrollable distance
|
|
const totalScrollable = documentHeight - windowHeight;
|
|
if (totalScrollable <= 0) return; // Not scrollable
|
|
|
|
const scrollPercentage = Math.round((scrollY / totalScrollable) * 100);
|
|
|
|
// We only care about specific milestones
|
|
const milestones = [25, 50, 75, 100];
|
|
|
|
milestones.forEach((milestone) => {
|
|
if (scrollPercentage >= milestone && !trackedDepths.current.has(milestone)) {
|
|
trackedDepths.current.add(milestone);
|
|
trackEvent(AnalyticsEvents.SCROLL_DEPTH, {
|
|
depth: milestone,
|
|
path: pathname,
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
// Use passive listener for better performance
|
|
window.addEventListener('scroll', handleScroll, { passive: true });
|
|
|
|
// Initial check (in case page is short or already scrolled)
|
|
handleScroll();
|
|
|
|
return () => {
|
|
window.removeEventListener('scroll', handleScroll);
|
|
};
|
|
}, [pathname, trackEvent]);
|
|
|
|
return null;
|
|
}
|