Add Google Analytics 4 with cookie consent integration
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m2s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m2s
- Add GA4 measurement ID to config (default: G-J0PCVT14NY) - Add /api/config endpoint to expose GA ID to frontend - Update cookie consent with Analytics category (opt-in) - Load GA4 only after user consents to analytics cookies - Update CSP to allow Google Analytics domains Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -65,11 +65,11 @@ class SecurityHeadersMiddleware(BaseHTTPMiddleware):
|
||||
# Content Security Policy
|
||||
response.headers["Content-Security-Policy"] = (
|
||||
"default-src 'self'; "
|
||||
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://unpkg.com; "
|
||||
"script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://unpkg.com https://www.googletagmanager.com; "
|
||||
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://cdn.jsdelivr.net https://unpkg.com; "
|
||||
"font-src 'self' https://fonts.gstatic.com; "
|
||||
"img-src 'self' data: https://*.tile.openstreetmap.org https://unpkg.com; "
|
||||
"connect-src 'self' https://cdn.jsdelivr.net https://*.tile.openstreetmap.org https://unpkg.com; "
|
||||
"img-src 'self' data: https://*.tile.openstreetmap.org https://unpkg.com https://www.google-analytics.com; "
|
||||
"connect-src 'self' https://cdn.jsdelivr.net https://*.tile.openstreetmap.org https://unpkg.com https://www.google-analytics.com https://analytics.google.com https://*.google-analytics.com; "
|
||||
"frame-ancestors 'none'; "
|
||||
"base-uri 'self'; "
|
||||
"form-action 'self';"
|
||||
@@ -199,6 +199,14 @@ async def serve_rankings():
|
||||
return FileResponse(settings.frontend_dir / "index.html")
|
||||
|
||||
|
||||
@app.get("/api/config")
|
||||
async def get_config():
|
||||
"""Return public configuration for the frontend."""
|
||||
return {
|
||||
"ga_measurement_id": settings.ga_measurement_id
|
||||
}
|
||||
|
||||
|
||||
@app.get("/api/schools")
|
||||
@limiter.limit(f"{settings.rate_limit_per_minute}/minute")
|
||||
async def get_schools(
|
||||
|
||||
@@ -38,6 +38,9 @@ class Settings(BaseSettings):
|
||||
rate_limit_burst: int = 10 # Allow burst of requests
|
||||
max_request_size: int = 1024 * 1024 # 1MB max request size
|
||||
|
||||
# Analytics
|
||||
ga_measurement_id: Optional[str] = "G-J0PCVT14NY" # Google Analytics 4 Measurement ID
|
||||
|
||||
class Config:
|
||||
env_file = ".env"
|
||||
env_file_encoding = "utf-8"
|
||||
|
||||
Reference in New Issue
Block a user