Implement cookie consent banner and integrate Google Consent API
Integrate Google Consent Management Platform (CMP) and a custom cookie consent banner component to manage user privacy preferences, including consent for analytics and advertising cookies. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 2cd2c0bc-434c-4bc9-ad3f-b99d3897a0d1 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/2cd2c0bc-434c-4bc9-ad3f-b99d3897a0d1/gjpMN2A
This commit is contained in:
parent
d40cabef2d
commit
b9b89c6025
2
.replit
2
.replit
@ -40,4 +40,4 @@ args = "npm run dev"
|
||||
waitForPort = 5000
|
||||
|
||||
[agent]
|
||||
integrations = ["javascript_google_analytics==1.0.0", "javascript_database==1.0.0"]
|
||||
integrations = ["javascript_database==1.0.0", "javascript_google_analytics==1.0.0"]
|
||||
|
||||
BIN
attached_assets/image_1756931997437.png
Normal file
BIN
attached_assets/image_1756931997437.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
@ -4,6 +4,20 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
|
||||
<title>go4.video – Top-Inhalte von Folx TV</title>
|
||||
|
||||
<!-- Google Consent Management Platform -->
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
gtag('consent', 'default', {
|
||||
'ad_storage': 'denied',
|
||||
'analytics_storage': 'denied',
|
||||
'ad_user_data': 'denied',
|
||||
'ad_personalization': 'denied'
|
||||
});
|
||||
</script>
|
||||
<script async src="https://fundingchoicesmessages.google.com/i/pub-4465464714854276?ers=1" nonce="temp-nonce"></script>
|
||||
<script nonce="temp-nonce">(function() {function signalGooglefcPresent() {if (!window.frames['googlefcPresent']) {if (document.body) {const iframe = document.createElement('iframe'); iframe.style = 'width: 0; height: 0; border: none; z-index: -1000; left: -1000px; top: -1000px;'; iframe.style.display = 'none'; iframe.name = 'googlefcPresent'; document.body.appendChild(iframe);} else {setTimeout(signalGooglefcPresent, 0);}}}signalGooglefcPresent();})();</script>
|
||||
<meta name="description" content="Video-Welt von Folx TV – immer bei dir" />
|
||||
|
||||
<!-- Google Search Console verification -->
|
||||
|
||||
@ -3,6 +3,7 @@ import { queryClient } from "./lib/queryClient";
|
||||
import { QueryClientProvider } from "@tanstack/react-query";
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
import { TooltipProvider } from "@/components/ui/tooltip";
|
||||
import CookieConsent from "@/components/CookieConsent";
|
||||
import Home from "@/pages/home";
|
||||
import VideoPage from "@/pages/VideoPage";
|
||||
import FolxStadlPage from "@/pages/FolxStadlPage";
|
||||
@ -36,6 +37,7 @@ function App() {
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<TooltipProvider>
|
||||
<Toaster />
|
||||
<CookieConsent />
|
||||
<Router />
|
||||
</TooltipProvider>
|
||||
</QueryClientProvider>
|
||||
|
||||
242
client/src/components/CookieConsent.tsx
Normal file
242
client/src/components/CookieConsent.tsx
Normal file
@ -0,0 +1,242 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { X } from 'lucide-react';
|
||||
|
||||
interface ConsentState {
|
||||
necessary: boolean;
|
||||
analytics: boolean;
|
||||
advertising: boolean;
|
||||
}
|
||||
|
||||
export default function CookieConsent() {
|
||||
const [showBanner, setShowBanner] = useState(false);
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
const [consent, setConsent] = useState<ConsentState>({
|
||||
necessary: true,
|
||||
analytics: false,
|
||||
advertising: false
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Check if user has already made a choice
|
||||
const hasConsented = localStorage.getItem('cookie_consent');
|
||||
if (!hasConsented) {
|
||||
setShowBanner(true);
|
||||
} else {
|
||||
// Load existing consent
|
||||
const savedConsent = JSON.parse(hasConsented);
|
||||
setConsent(savedConsent);
|
||||
updateGoogleConsent(savedConsent);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const updateGoogleConsent = (consentState: ConsentState) => {
|
||||
if (window.gtag) {
|
||||
window.gtag('consent', 'update', {
|
||||
'ad_storage': consentState.advertising ? 'granted' : 'denied',
|
||||
'analytics_storage': consentState.analytics ? 'granted' : 'denied',
|
||||
'ad_user_data': consentState.advertising ? 'granted' : 'denied',
|
||||
'ad_personalization': consentState.advertising ? 'granted' : 'denied'
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleAcceptAll = () => {
|
||||
const newConsent = {
|
||||
necessary: true,
|
||||
analytics: true,
|
||||
advertising: true
|
||||
};
|
||||
|
||||
setConsent(newConsent);
|
||||
updateGoogleConsent(newConsent);
|
||||
localStorage.setItem('cookie_consent', JSON.stringify(newConsent));
|
||||
setShowBanner(false);
|
||||
setShowDetails(false);
|
||||
};
|
||||
|
||||
const handleRejectAll = () => {
|
||||
const newConsent = {
|
||||
necessary: true,
|
||||
analytics: false,
|
||||
advertising: false
|
||||
};
|
||||
|
||||
setConsent(newConsent);
|
||||
updateGoogleConsent(newConsent);
|
||||
localStorage.setItem('cookie_consent', JSON.stringify(newConsent));
|
||||
setShowBanner(false);
|
||||
setShowDetails(false);
|
||||
};
|
||||
|
||||
const handleSavePreferences = () => {
|
||||
updateGoogleConsent(consent);
|
||||
localStorage.setItem('cookie_consent', JSON.stringify(consent));
|
||||
setShowBanner(false);
|
||||
setShowDetails(false);
|
||||
};
|
||||
|
||||
const handleConsentChange = (key: keyof ConsentState, value: boolean) => {
|
||||
if (key === 'necessary') return; // Cannot disable necessary cookies
|
||||
setConsent(prev => ({ ...prev, [key]: value }));
|
||||
};
|
||||
|
||||
if (!showBanner) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-[9999] flex items-end justify-center p-4 pointer-events-none">
|
||||
<div className="w-full max-w-4xl pointer-events-auto">
|
||||
<div className="bg-bunny-dark border border-white/20 rounded-lg shadow-2xl">
|
||||
{!showDetails ? (
|
||||
// Simple banner
|
||||
<div className="p-6">
|
||||
<div className="flex items-start justify-between mb-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-6 h-6 bg-gradient-to-r from-purple-600 to-blue-500 rounded-lg flex items-center justify-center">
|
||||
<div className="w-0 h-0 border-l-[6px] border-l-white border-y-[4px] border-y-transparent ml-0.5"></div>
|
||||
</div>
|
||||
<h3 className="text-lg font-semibold text-white">Cookie-Einstellungen</h3>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowBanner(false)}
|
||||
className="text-bunny-muted hover:text-white transition-colors"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<p className="text-bunny-light text-sm mb-4">
|
||||
Wir verwenden Cookies und ähnliche Technologien, um unsere Website zu verbessern,
|
||||
Inhalte zu personalisieren und Werbung zu schalten. Durch das Fortsetzen der Nutzung
|
||||
unserer Website stimmen Sie der Verwendung von Cookies zu.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-3">
|
||||
<Button
|
||||
onClick={handleAcceptAll}
|
||||
className="gradient-primary text-white border-none hover:opacity-90 transition-opacity"
|
||||
>
|
||||
Alle akzeptieren
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleRejectAll}
|
||||
variant="outline"
|
||||
className="border-white/20 text-white hover:bg-white/10"
|
||||
>
|
||||
Alle ablehnen
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => setShowDetails(true)}
|
||||
variant="ghost"
|
||||
className="text-bunny-blue hover:text-purple-400 hover:bg-transparent"
|
||||
>
|
||||
Einstellungen verwalten
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
// Detailed settings
|
||||
<div className="p-6">
|
||||
<div className="flex items-start justify-between mb-6">
|
||||
<h3 className="text-xl font-semibold text-white">Cookie-Einstellungen</h3>
|
||||
<button
|
||||
onClick={() => setShowDetails(false)}
|
||||
className="text-bunny-muted hover:text-white transition-colors"
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6 mb-6">
|
||||
{/* Necessary Cookies */}
|
||||
<div className="bg-bunny-gray/20 p-4 rounded-lg">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h4 className="text-white font-medium">Notwendige Cookies</h4>
|
||||
<div className="bg-bunny-blue/20 text-bunny-blue px-2 py-1 rounded text-xs">
|
||||
Immer aktiv
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-bunny-light text-sm">
|
||||
Diese Cookies sind für das Funktionieren der Website erforderlich und können
|
||||
in unseren Systemen nicht deaktiviert werden.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Analytics Cookies */}
|
||||
<div className="bg-bunny-gray/20 p-4 rounded-lg">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h4 className="text-white font-medium">Analyse-Cookies</h4>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={consent.analytics}
|
||||
onChange={(e) => handleConsentChange('analytics', e.target.checked)}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-bunny-gray peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-bunny-blue"></div>
|
||||
</label>
|
||||
</div>
|
||||
<p className="text-bunny-light text-sm">
|
||||
Diese Cookies ermöglichen es uns, Besuche und Verkehrsquellen zu zählen,
|
||||
damit wir die Leistung unserer Website messen und verbessern können.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Advertising Cookies */}
|
||||
<div className="bg-bunny-gray/20 p-4 rounded-lg">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<h4 className="text-white font-medium">Werbe-Cookies</h4>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={consent.advertising}
|
||||
onChange={(e) => handleConsentChange('advertising', e.target.checked)}
|
||||
className="sr-only peer"
|
||||
/>
|
||||
<div className="w-11 h-6 bg-bunny-gray peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-bunny-blue"></div>
|
||||
</label>
|
||||
</div>
|
||||
<p className="text-bunny-light text-sm">
|
||||
Diese Cookies werden von Werbepartnern über unsere Website gesetzt. Sie können
|
||||
verwendet werden, um ein Profil Ihrer Interessen zu erstellen und relevante
|
||||
Werbung auf anderen Websites zu zeigen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-3">
|
||||
<Button
|
||||
onClick={handleSavePreferences}
|
||||
className="gradient-primary text-white border-none hover:opacity-90 transition-opacity"
|
||||
>
|
||||
Einstellungen speichern
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleAcceptAll}
|
||||
variant="outline"
|
||||
className="border-white/20 text-white hover:bg-white/10"
|
||||
>
|
||||
Alle akzeptieren
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleRejectAll}
|
||||
variant="ghost"
|
||||
className="text-bunny-muted hover:text-white hover:bg-white/5"
|
||||
>
|
||||
Alle ablehnen
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Global declaration for gtag
|
||||
declare global {
|
||||
interface Window {
|
||||
gtag: (...args: any[]) => void;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user