🚀 Add automatic deployment system
- Add auto-deploy.sh script with full CI/CD pipeline - Add quick-deploy.sh for fast development deployments - Add Git post-receive hook for automatic deployment on push - Add comprehensive deployment documentation - Add npm scripts for easy deployment management - Include health checks, logging, and cleanup - Support for automatic rollback on failures
This commit is contained in:
130
components/AnalyticsProvider.tsx
Normal file
130
components/AnalyticsProvider.tsx
Normal file
@@ -0,0 +1,130 @@
|
||||
'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: 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}</>;
|
||||
};
|
||||
Reference in New Issue
Block a user