Files
portfolio/components/AnalyticsProvider.tsx
denshooter be01ee2adb 🔧 Enhance Middleware and Admin Features
 Updated Middleware Logic:
- Enhanced admin route protection with Basic Auth for legacy routes and session-based auth for `/manage` and `/editor`.

 Improved Admin Panel Styles:
- Added glassmorphism styles for admin components to enhance UI aesthetics.

 Refined Rate Limiting:
- Adjusted rate limits for admin dashboard requests to allow more generous access.

 Introduced Analytics Reset API:
- Added a new endpoint for resetting analytics data with rate limiting and admin authentication.

🎯 Overall Improvements:
- Strengthened security and user experience for admin functionalities.
- Enhanced visual design for better usability.
- Streamlined analytics management processes.
2025-09-09 19:50:52 +02:00

131 lines
4.1 KiB
TypeScript

'use client';
import { useEffect } from 'react';
import { useWebVitals } from '@/lib/useWebVitals';
import { trackEvent, trackPageLoad } from '@/lib/analytics';
interface AnalyticsProviderProps {
children: React.ReactNode;
}
export const AnalyticsProvider: React.FC<AnalyticsProviderProps> = ({ children }) => {
// Initialize Web Vitals tracking
useWebVitals();
useEffect(() => {
if (typeof window === 'undefined') return;
// Track page view
const trackPageView = () => {
trackEvent('page-view', {
url: window.location.pathname,
referrer: document.referrer,
timestamp: Date.now(),
});
};
// Track page load performance
trackPageLoad();
// Track initial page view
trackPageView();
// Track route changes (for SPA navigation)
const handleRouteChange = () => {
setTimeout(() => {
trackPageView();
trackPageLoad();
}, 100);
};
// Listen for popstate events (back/forward navigation)
window.addEventListener('popstate', handleRouteChange);
// Track user interactions
const handleClick = (event: MouseEvent) => {
const target = event.target as HTMLElement;
const element = target.tagName.toLowerCase();
const className = target.className;
const id = target.id;
trackEvent('click', {
element,
className: (typeof className === 'string' && className) ? className.split(' ')[0] : undefined,
id: id || undefined,
url: window.location.pathname,
});
};
// Track form submissions
const handleSubmit = (event: SubmitEvent) => {
const form = event.target as HTMLFormElement;
trackEvent('form-submit', {
formId: form.id || undefined,
formClass: form.className || undefined,
url: window.location.pathname,
});
};
// Track scroll depth
let maxScrollDepth = 0;
const handleScroll = () => {
const scrollDepth = Math.round(
(window.scrollY / (document.documentElement.scrollHeight - window.innerHeight)) * 100
);
if (scrollDepth > maxScrollDepth) {
maxScrollDepth = scrollDepth;
// Track scroll milestones
if (scrollDepth >= 25 && scrollDepth < 50 && maxScrollDepth >= 25) {
trackEvent('scroll-depth', { depth: 25, url: window.location.pathname });
} else if (scrollDepth >= 50 && scrollDepth < 75 && maxScrollDepth >= 50) {
trackEvent('scroll-depth', { depth: 50, url: window.location.pathname });
} else if (scrollDepth >= 75 && scrollDepth < 90 && maxScrollDepth >= 75) {
trackEvent('scroll-depth', { depth: 75, url: window.location.pathname });
} else if (scrollDepth >= 90 && maxScrollDepth >= 90) {
trackEvent('scroll-depth', { depth: 90, url: window.location.pathname });
}
}
};
// Add event listeners
document.addEventListener('click', handleClick);
document.addEventListener('submit', handleSubmit);
window.addEventListener('scroll', handleScroll, { passive: true });
// Track errors
const handleError = (event: ErrorEvent) => {
trackEvent('error', {
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
url: window.location.pathname,
});
};
const handleUnhandledRejection = (event: PromiseRejectionEvent) => {
trackEvent('unhandled-rejection', {
reason: event.reason?.toString(),
url: window.location.pathname,
});
};
window.addEventListener('error', handleError);
window.addEventListener('unhandledrejection', handleUnhandledRejection);
// Cleanup
return () => {
window.removeEventListener('popstate', handleRouteChange);
document.removeEventListener('click', handleClick);
document.removeEventListener('submit', handleSubmit);
window.removeEventListener('scroll', handleScroll);
window.removeEventListener('error', handleError);
window.removeEventListener('unhandledrejection', handleUnhandledRejection);
};
}, []);
return <>{children}</>;
};