feat: Add Google Analytics integration and fix anonymous tracking

- Add Google Analytics tracking (G-ZDZ26XYN2P) to frontend
- Create comprehensive analytics utility with event tracking
- Track URL submissions, analysis results, and user authentication
- Add route tracking for SPA navigation
- Fix CORS configuration to support both localhost and production
- Fix home page tracking form to display results instead of auto-redirect
- Add service management scripts for easier deployment
- Update database migrations for enhanced analysis features

Key Features:
- Anonymous and authenticated user tracking
- SSL/SEO/Security analysis event tracking
- Error tracking for debugging
- Page view tracking for SPA routes
- Multi-origin CORS support for development and production
This commit is contained in:
Andrei
2025-08-23 17:45:01 +00:00
parent 58f8093689
commit 6e41d9874d
19 changed files with 1904 additions and 95 deletions

View File

@@ -3,6 +3,7 @@
*/
import { useState } from 'react';
import { trackUrlSubmission, trackAnalysisResult, trackError } from '../utils/analytics';
import {
Box,
Heading,
@@ -49,7 +50,7 @@ import {
// Image,
// Center,
} from '@chakra-ui/react';
import { Link as RouterLink, useNavigate } from 'react-router-dom';
import { Link as RouterLink } from 'react-router-dom';
import { useMutation } from '@tanstack/react-query';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
@@ -90,7 +91,6 @@ export function HomePage() {
const [showAdvanced, setShowAdvanced] = useState(false);
const [trackingResult, setTrackingResult] = useState<any>(null);
const { isAuthenticated } = useAuth();
const navigate = useNavigate();
const toast = useToast();
const cardBg = useColorModeValue('white', 'gray.800');
@@ -124,6 +124,8 @@ export function HomePage() {
// Tracking mutation
const trackingMutation = useMutation({
mutationFn: async (data: TrackRequestV2) => {
// Track URL submission
trackUrlSubmission(data.url, isAuthenticated);
return await trackingApi.trackUrlV2(data);
},
onSuccess: (result) => {
@@ -136,12 +138,24 @@ export function HomePage() {
isClosable: true,
});
// Navigate to check detail page for authenticated users
if (isAuthenticated) {
navigate(`/check/${result.check.id}`);
// Track analysis results
const analysis = (result as any).check?.analysis;
if (analysis) {
trackAnalysisResult(
(result as any).check.redirectCount || 0,
analysis.ssl?.warningsJson?.length > 0 || false,
!analysis.seo?.robotsTxtStatus || analysis.seo?.noindex || false,
analysis.security?.mixedContent === 'PRESENT' || analysis.security?.safeBrowsingStatus !== 'safe' || false
);
}
// Don't auto-navigate on home page to allow users to see results
// They can manually navigate to their dashboard to see saved results
},
onError: (error: any) => {
// Track errors
trackError('tracking_failed', error.response?.data?.message || error.message || 'Unknown error');
toast({
title: 'Tracking failed',
description: error.response?.data?.message || 'An error occurred',