Leitfaden zur Einwilligung in die Verwendung von Cookies und zur SPA-Implementierung
Die Herausforderung verstehen
Single-Page-Anwendungen (SPAs), die mit React, Vue, Angular oder anderen Frameworks erstellt wurden, stellen TermsFeed Cookie Consent vor besondere Herausforderungen, da:
- Keine Seitenaktualisierung. Die Seite wird nicht wie klassische Webseiten neu geladen.
- Dynamische Inhalte. Inhalte werden dynamisch geladen, ohne dass DOMContentLoaded erneut ausgelöst wird.
- Routenwechsel. Die Navigation erfolgt über JavaScript und nicht über herkömmliche Seitenladungen.
- Zustandsverwaltung. Der Zustimmungsstatus muss über Routenwechsel hinweg erhalten bleiben.
Lösung: Neuladen bei Navigation
Problem
„Ich habe eine React-SPA und das Cookie-Banner wird nur beim ersten Laden der Seite angezeigt. Wenn Nutzer zu anderen Seiten navigieren, erscheint das Banner nicht erneut, sofern sie keine Auswahl getroffen haben. Außerdem werden Skripte auf nachfolgenden Seiten erst nach einer vollständigen Aktualisierung geladen, wenn sie Cookies auf einer Seite akzeptieren.“
Lösung
Bei der Implementierung von TermsFeed Cookie Consent in einer SPA müssen Sie:
- Die Einwilligung beim ersten Laden initialisieren.
- Routenänderungen erkennen.
- Laden Sie das Banner bei Bedarf neu.
- Den Zustimmungsstatus erneut überprüfen.
React-Implementierung
Schritt 1: Erstellen Sie eine Cookie-Einwilligungskomponente
// CookieConsent.js
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
const CookieConsent = () => {
const location = useLocation();
useEffect(() => {
// Load TermsFeed script if not already loaded
if (!window.cookieconsent) {
const script = document.createElement('script');
script.src = '//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js';
script.charset = 'UTF-8';
script.onload = () => initializeCookieConsent();
document.head.appendChild(script);
} else {
// Script already loaded, just check if banner needs to be shown
checkBannerState();
}
}, []); // Run once on mount
useEffect(() => {
// Check banner state on route change
if (window.cookieconsent) {
checkBannerState();
}
}, [location]); // Run on every route change
const initializeCookieConsent = () => {
if (window.cookieconsent && typeof window.cookieconsent.run === 'function') {
window.cookieconsent.run({
"notice_banner_type": "headline",
"consent_type": "express",
"palette": "light",
"language": "en",
"website_name": "My SPA",
"website_privacy_policy_url": "https://mysite.com/privacy",
"open_preferences_center_selector": "#changePreferences",
"page_load_consent_levels": ["strictly-necessary"],
"callbacks": {
"scripts_specific_loaded": (level) => {
console.log("Scripts loaded for: " + level);
// Re-initialize any components that need tracking
if (level === 'tracking') {
reinitializeAnalytics();
}
}
}
});
}
};
const checkBannerState = () => {
// Check if user has already made a consent choice
const consentCookie = getCookie('cookie_consent_level');
if (!consentCookie) {
// No consent yet, banner should be visible
// No action needed - banner will show automatically
}
};
const getCookie = (name) => {
const value = ; ${document.cookie};
const parts = value.split(; ${name}=);
if (parts.length === 2) return parts.pop().split(';').shift();
};
const reinitializeAnalytics = () => {
// Re-run any analytics initialization needed
if (window.gtag) {
window.gtag('config', 'G-XXXXXXXXXX', {
'page_path': location.pathname
});
}
};
return null; // This component doesn't render anything
};
export default CookieConsent;
Schritt 2: Fügen Sie die Komponente zur App hinzu
// App.js
import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import CookieConsent from './components/CookieConsent';
import Home from './pages/Home';
import About from './pages/About';
function App() {
return (
<Router>
<CookieConsent />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
{/ Preferences button /}
<button id="changePreferences" style={{
position: 'fixed',
bottom: '20px',
right: '20px',
zIndex: 9999
}}>
Cookie Settings
</button>
<noscript>
Free cookie consent management tool by <a href="https://www.termsfeed.com/">TermsFeed</a>
</noscript>
</Router>
);
}
export default App;
Vue.js-Implementierung
Schritt 1: Erstellen Sie das Cookie-Einwilligungs-Plugin
// plugins/cookieConsent.js
export default {
install(app, options) {
// Load script
const loadCookieConsent = () => {
if (window.cookieconsent) return Promise.resolve();
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = '//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js';
script.charset = 'UTF-8';
script.onload = () => resolve();
script.onerror = () => reject();
document.head.appendChild(script);
});
};
// Initialize
const initCookieConsent = () => {
if (window.cookieconsent && typeof window.cookieconsent.run === 'function') {
window.cookieconsent.run({
"notice_banner_type": "headline",
"consent_type": "express",
"palette": "light",
"language": "en",
"website_name": options.websiteName || "My Vue SPA",
"website_privacy_policy_url": options.privacyUrl || "#",
"open_preferences_center_selector": "#changePreferences",
"page_load_consent_levels": ["strictly-necessary"]
});
}
};
// Make available globally
app.config.globalProperties.$cookieConsent = {
load: loadCookieConsent,
init: initCookieConsent
};
// Auto-initialize on mount
if (typeof window !== 'undefined') {
loadCookieConsent().then(() => {
document.addEventListener('DOMContentLoaded', initCookieConsent);
});
}
}
};
Schritt 2: Verwenden Sie es in der Haupt-App
// main.js
import { createApp } from 'vue';
import { createRouter, createWebHistory } from 'vue-router';
import App from './App.vue';
import cookieConsentPlugin from './plugins/cookieConsent';
const router = createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: () => import('./views/Home.vue') },
{ path: '/about', component: () => import('./views/About.vue') }
]
});
const app = createApp(App);
app.use(router);
app.use(cookieConsentPlugin, {
websiteName: 'My Vue App',
privacyUrl: 'https://mysite.com/privacy'
});
app.mount('#app');
Schritt 3: Erstellen der App-Komponente
<!-- App.vue -->
<template>
<div id="app">
<router-view />
<button id="changePreferences" class="cookie-settings-btn">
Cookie Settings
</button>
<noscript>
Free cookie consent management tool by
<a href="https://www.termsfeed.com/">TermsFeed</a>
</noscript>
</div>
</template>
<script>
export default {
name: 'App',
mounted() {
// Watch for route changes
this.$router.afterEach((to, from) => {
// Check if consent banner needs to be re-shown
this.checkConsentState();
});
},
methods: {
checkConsentState() {
const consentCookie = document.cookie
.split('; ')
.find(row => row.startsWith('cookie_consent_level='));
if (!consentCookie) {
console.log('No consent given yet');
}
}
}
};
</script>
<style>
.cookie-settings-btn {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
padding: 10px 20px;
background: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
</style>
Angular-Implementierung
Schritt 1: Erstellen des Cookie-Einwilligungs-Dienstes
// services/cookie-consent.service.ts
import { Injectable } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';
declare global {
interface Window {
cookieconsent: any;
}
}
@Injectable({
providedIn: 'root'
})
export class CookieConsentService {
private scriptLoaded = false;
constructor(private router: Router) {}
initialize(): Promise<void> {
return this.loadScript().then(() => {
this.initializeConsent();
this.watchRouteChanges();
});
}
private loadScript(): Promise<void> {
if (this.scriptLoaded || window.cookieconsent) {
return Promise.resolve();
}
return new Promise((resolve, reject) => {
const script = document.createElement('script');
script.src = '//www.termsfeed.com/public/cookie-consent/4.2.0/cookie-consent.js';
script.charset = 'UTF-8';
script.onload = () => {
this.scriptLoaded = true;
resolve();
};
script.onerror = () => reject();
document.head.appendChild(script);
});
}
private initializeConsent(): void {
if (window.cookieconsent && typeof window.cookieconsent.run === 'function') {
window.cookieconsent.run({
notice_banner_type: 'headline',
consent_type: 'express',
palette: 'light',
language: 'en',
website_name: 'My Angular App',
website_privacy_policy_url: 'https://mysite.com/privacy',
open_preferences_center_selector: '#changePreferences',
page_load_consent_levels: ['strictly-necessary'],
callbacks: {
scripts_specific_loaded: (level: string) => {
console.log('Scripts loaded for:', level);
this.handleConsentUpdate(level);
}
}
});
}
}
private watchRouteChanges(): void {
this.router.events.pipe(
filter(event => event instanceof NavigationEnd)
).subscribe(() => {
// Check consent state on route change
this.checkConsentState();
});
}
private checkConsentState(): void {
const consentCookie = this.getCookie('cookie_consent_level');
if (!consentCookie) {
console.log('No consent given yet');
}
}
private handleConsentUpdate(level: string): void {
// Handle consent updates
if (level === 'tracking') {
this.initializeAnalytics();
}
}
private initializeAnalytics(): void {
// Re-initialize analytics on consent
if ((window as any).gtag) {
(window as any).gtag('config', 'G-XXXXXXXXXX', {
page_path: this.router.url
});
}
}
private getCookie(name: string): string | null {
const value = ; ${document.cookie};
const parts = value.split(; ${name}=);
if (parts.length === 2) {
return parts.pop()?.split(';').shift() || null;
}
return null;
}
openPreferences(): void {
if (window.cookieconsent && typeof window.cookieconsent.openPreferencesCenter === 'function') {
window.cookieconsent.openPreferencesCenter();
}
}
}
Schritt 2: Initialisierung in der App-Komponente
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { CookieConsentService } from './services/cookie-consent.service';
@Component({
selector: 'app-root',
template:
<router-outlet></router-outlet>
<button id="changePreferences" class="cookie-settings-btn">
Cookie Settings
</button>
<noscript>
Free cookie consent management tool by
<a href="https://www.termsfeed.com/">TermsFeed</a>
</noscript>
,
styles: [
.cookie-settings-btn {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
padding: 10px 20px;
background: #007bff;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
}
]
})
export class AppComponent implements OnInit {
constructor(private cookieConsentService: CookieConsentService) {}
ngOnInit(): void {
this.cookieConsentService.initialize().catch(error => {
console.error('Failed to initialize cookie consent:', error);
});
}
}
Häufige Probleme mit SPA und Cookie-Einwilligung
Problem 1: Das Banner erscheint bei der Navigation nicht erneut
Problem
Der Benutzer navigiert, ohne eine Auswahl zu treffen, und das Banner verschwindet.
Lösung
Überprüfen Sie, ob bei einem Routenwechsel die Zustimmung erteilt wurde.
// Check if consent was given on route change
router.afterEach(() => {
const hasConsent = getCookie('cookie_consent_level');
if (!hasConsent) {
// Banner should be visible - it will show automatically
// No manual action needed if properly configured
}
});
Problem 2: Skripte werden nach der Einwilligung auf neuen Routen nicht geladen
Problem
„Der Nutzer akzeptiert Cookies, navigiert zu einer anderen Seite in meiner React-App, aber Google Analytics erfasst den neuen Seitenaufruf nicht.“
Lösung
Verwenden Sie Callbacks, um die Seitenaufrufe bei jedem Routenwechsel zu erfassen.
// In your callback
"callbacks": {
"scripts_specific_loaded": (level) => {
if (level === 'tracking' && window.gtag) {
// Track page view on every route change
router.afterEach((to) => {
gtag('config', 'G-XXXXXXXXXX', {
'page_path': to.path
});
});
}
}
}
Problem 3: Es erscheinen mehrere Banner-Instanzen
Problem
Das Banner erscheint mehrmals, wenn schnell navigiert wird.
Lösung
Verwenden Sie einen Guard, um mehrfache Initialisierungen zu verhindern
// Use a guard to prevent multiple initializations
let isInitialized = false;
const initCookieConsent = () => {
if (isInitialized) return;
isInitialized = true;
cookieconsent.run({ / config / });
};
Öffnen Sie das Einstellungscenter programmgesteuert
Bei SPAs möchten Sie die Einstellungen möglicherweise ohne statische Schaltfläche öffnen:
// Method 1: Using the openPreferencesCenter() method
const openPreferences = () => {
if (window.cookieconsent && typeof window.cookieconsent.openPreferencesCenter === 'function') {
window.cookieconsent.openPreferencesCenter();
} else {
console.error('Cookie consent not initialized');
}
};
// In React
<button onClick={openPreferences}>Change Cookie Settings</button>
// In Vue
<button @click="openPreferences">Change Cookie Settings</button>
// In Angular
<button (click)="openPreferences()">Change Cookie Settings</button>