Implementing cookie bar
Cookie bar informs visitors about cookie usage and obtains consent before installation. GDPR requires: consent voluntary, explicit, granular (by category), easily revocable.
Cookie categories
| Category | Requires consent | Examples |
|---|---|---|
| Essential | No | session, CSRF-token, cookie-consent |
| Functional | Yes | language, theme, remember me |
| Analytics | Yes | Google Analytics, Yandex.Metrica |
| Marketing | Yes | Google Ads, Facebook Pixel |
React component
import { useState, useEffect } from 'react';
interface CookieConsent {
functional: boolean;
analytics: boolean;
marketing: boolean;
}
const CONSENT_KEY = 'cookie_consent_v2';
function useCookieConsent() {
const [consent, setConsent] = useState<CookieConsent | null>(null);
const [showBanner, setShowBanner] = useState(false);
useEffect(() => {
const saved = localStorage.getItem(CONSENT_KEY);
if (saved) {
const parsed = JSON.parse(saved);
setConsent(parsed);
applyConsent(parsed);
} else {
setShowBanner(true);
}
}, []);
const acceptAll = () => {
const all = { functional: true, analytics: true, marketing: true };
save(all);
};
const rejectAll = () => {
const none = { functional: false, analytics: false, marketing: false };
save(none);
};
const save = (c: CookieConsent) => {
localStorage.setItem(CONSENT_KEY, JSON.stringify({
...c,
updatedAt: new Date().toISOString(),
}));
setConsent(c);
setShowBanner(false);
applyConsent(c);
reportConsent(c);
};
return { consent, showBanner, acceptAll, rejectAll, save };
}
function applyConsent(consent: CookieConsent) {
if (consent.analytics) {
loadGoogleAnalytics();
loadYandexMetrica();
}
if (consent.marketing) {
loadFacebookPixel();
}
}
async function reportConsent(consent: CookieConsent) {
await fetch('/api/cookie-consent', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ consent }),
});
}
export function CookieBanner() {
const { showBanner, acceptAll, rejectAll, save } = useCookieConsent();
const [showDetails, setShowDetails] = useState(false);
const [selections, setSelections] = useState({ functional: false, analytics: false, marketing: false });
if (!showBanner) return null;
return (
<div className="cookie-banner" role="dialog">
<h2>We use cookies</h2>
<p>We use necessary cookies. With your consent — analytics and marketing.</p>
{showDetails && (
<div className="cookie-categories">
<label className="required">
<input type="checkbox" checked disabled />
<span>Essential</span>
</label>
{(['functional', 'analytics', 'marketing'] as const).map(cat => (
<label key={cat}>
<input checked={selections[cat]} onChange={e => setSelections(s => ({ ...s, [cat]: e.target.checked }))} />
<span>{cat}</span>
</label>
))}
</div>
)}
<div className="actions">
<button onClick={rejectAll}>Reject all</button>
<button onClick={() => setShowDetails(!showDetails)}>Settings</button>
{showDetails
? <button onClick={() => save(selections)}>Save</button>
: <button onClick={acceptAll}>Accept all</button>
}
</div>
</div>
);
}
Server: recording consent
class CookieConsentController extends Controller
{
public function store(Request $request): JsonResponse
{
$request->validate([
'consent.functional' => 'required|boolean',
'consent.analytics' => 'required|boolean',
'consent.marketing' => 'required|boolean',
]);
CookieConsent::create([
'user_id' => auth()->id(),
'session_id' => $request->session()->getId(),
'ip' => $request->ip(),
'user_agent' => $request->userAgent(),
'consent' => $request->consent,
'version' => config('cookies.policy_version', '2.0'),
'consented_at' => now(),
]);
return response()->json(['status' => 'saved']);
}
}
Google Analytics with consent
function loadGoogleAnalytics() {
if (document.getElementById('ga-script')) return;
const script = document.createElement('script');
script.id = 'ga-script';
script.src = `https://www.googletagmanager.com/gtag/js?id=${GA_ID}`;
document.head.appendChild(script);
window.dataLayer = window.dataLayer || [];
window.gtag = function() { window.dataLayer.push(arguments); };
window.gtag('config', GA_ID, { anonymize_ip: true });
}
Implementation Timeline
Cookie bar with 3 categories, localStorage consent, API: 2–3 days. With audit log in DB and GDPR-compatible withdrawal: 3–4 days.







