jostkleigrewe/cookie-consent-bundle

Symfony 8 bundle for GDPR/DSGVO cookie consent with Google Consent Mode v2, Twig components, Stimulus.js, and AssetMapper. Supports cookie, Doctrine, or combined storage. Includes YouTube, Vimeo, Google Maps embed components.

Fund package maintenance!
jostkleigrewe

Installs: 53

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 0

Forks: 0

Open Issues: 0

Type:symfony-bundle

pkg:composer/jostkleigrewe/cookie-consent-bundle

v0.5.1 2026-02-16 21:55 UTC

This package is auto-updated.

Last update: 2026-02-16 22:02:12 UTC


README

Packagist Version Packagist Downloads PHP Version CI License

A modern Symfony 8 bundle for GDPR/DSGVO-compliant cookie consent management. Includes Google Consent Mode v2 support, Twig components, Stimulus.js integration, and AssetMapper compatibility. Perfect for cookie banners, consent modals, and privacy-compliant websites.

๐Ÿ‡ฉ๐Ÿ‡ช Deutsche Version ยท ๐Ÿ“ฆ Packagist ยท ๐Ÿ“– Documentation

Why this bundle?

  • โœ… Symfony-native consent handling with Twig, Stimulus, and AssetMapper
  • โœ… Vendor-level toggles + Consent Mode v2 for modern ad stacks
  • โœ… Session-safe by design: prevents unwanted session cookies

Screenshot

Cookie Consent Modal

Features

  • ๐ŸŽฏ GDPR & DSGVO Compliant โ€“ Cookie consent with policy versioning and audit logging
  • ๐Ÿ“Š Google Consent Mode v2 โ€“ Built-in GA4, Google Ads, and gtag integration
  • ๐ŸŽจ Multiple Themes โ€“ Tabler (light/dark), Bootstrap 5, or custom templates
  • โšก Stimulus.js & Turbo โ€“ Hotwire-compatible, no full page reload needed
  • ๐Ÿ—‚๏ธ AssetMapper Ready โ€“ No Webpack/Encore required, works out of the box
  • ๐Ÿงญ Flexible Storage โ€“ Cookie-only, Doctrine ORM, or combined (hybrid)
  • ๐Ÿงฉ Vendor-Level Consent โ€“ Optional per-vendor toggles (Google Ads, Meta, etc.)
  • ๐Ÿ›ก๏ธ Session Protection โ€“ Prevents session cookies without explicit consent
  • ๐ŸŽฌ Embed Components โ€“ YouTube, Vimeo, Google Maps, Spotify, Instagram, TikTok with consent gates
  • ๐Ÿงช Twig Helpers โ€“ cookie_consent_has(), cookie_consent_modal(), and more
  • ๐Ÿ“ Audit Logging โ€“ Track consent changes with optional database persistence

Requirements

  • PHP 8.4+
  • Symfony 8.0+
  • Twig Bundle, Security Bundle, Stimulus Bundle
  • Doctrine ORM + DoctrineBundle (optional, only for storage: doctrine|both)

Compatibility

Bundle Version PHP Symfony
0.4.x 8.4+ 8.0+
0.3.x 8.3+ 7.1+
0.2.x 8.2+ 7.0+

Quick Start

1. Install

composer require jostkleigrewe/cookie-consent-bundle

2. Register routes

Create config/routes/cookie_consent.yaml:

cookie_consent:
    resource: '@CookieConsentBundle/config/routes.php'

This registers the /_cookie-consent endpoint required for consent updates.

3. Configure assets

Option A: Twig helper (CSP-compatible, recommended)

{# templates/base.html.twig - in <head> #}
{{ cookie_consent_styles() }}

This renders a standard <link> tag, fully compatible with strict Content-Security-Policy headers.

Option B: JavaScript import

// assets/app.js
import '@jostkleigrewe/cookie-consent-bundle/styles/cookie_consent.css';

Note: With strict CSP (style-src 'self'), bundlers may convert CSS imports to data: URLs, which can be blocked. Use Option A if you encounter CSP issues.

// assets/controllers.json
{
  "controllers": {
    "@jostkleigrewe/cookie-consent-bundle": {
      "cookie-consent": { "enabled": true, "fetch": "eager" }
    }
  }
}

4. Render the modal

{# templates/base.html.twig #}
{{ cookie_consent_modal() }}

5. Gate content by consent

{% if cookie_consent_has('analytics') %}
  <script src="https://example.com/analytics.js"></script>
{% endif %}

Or use lazy loading:

<script type="text/plain" data-consent-category="analytics"
        data-consent-src="https://example.com/analytics.js"></script>

Configuration

Create config/packages/cookie_consent.yaml:

cookie_consent:
  policy_version: '1'
  storage: cookie  # cookie, doctrine, or both

  categories:
    necessary:
      label: Necessary
      required: true
      default: true
    analytics:
      label: Analytics
      default: false
    marketing:
      label: Marketing
      default: false
      vendors:
        google_ads:
          label: Google Ads
          default: false

  ui:
    template: '@CookieConsent/styles/tabler/modal.html.twig'
    position: center
    privacy_url: '/privacy'
    reload_on_change: false

  logging:
    retention_days: null

  google_consent_mode:
    enabled: false

Storage Modes

Mode Description Use Case
cookie Browser cookie only (default) Simple sites, no DB required
doctrine Database only via Doctrine ORM Server-side consent verification
both Cookie + Database (cookie as primary, DB as backup) Full audit trail + fast access

If storage is set to doctrine or both, generate migrations in your app (bundle ships entities, not migrations). This requires Doctrine ORM:

bin/console doctrine:migrations:diff
bin/console doctrine:migrations:migrate

Increment policy_version when changing categories to require re-consent.

If logging.retention_days is set, run the cleanup command regularly:

bin/console cookie-consent:cleanup

Documentation

Embed Components

Gate third-party content with built-in components:

<twig:CookieConsentYoutubeEmbed
  video_id="dQw4w9WgXcQ"
  category="marketing"
  vendor="youtube"
/>

Alternative:

{{ component('CookieConsentYoutubeEmbed', {
  video_id: 'dQw4w9WgXcQ',
  category: 'marketing',
  vendor: 'youtube'
}) }}

Available: YouTube, Vimeo, Google Maps, Spotify, Twitter/X, Instagram, TikTok, and more.

Integration Overview

See Integration for Twig components, helpers, data attributes, controller attributes, and events.

Troubleshooting

Modal doesn't appear

  • Ensure {{ cookie_consent_modal() }} is in your base template
  • Check browser console for JavaScript errors
  • Verify Stimulus controller is loaded: @jostkleigrewe/cookie-consent-bundle/cookie-consent

Assets not loading (404)

  • Run bin/console cache:clear
  • Check AssetMapper paths: bin/console debug:asset-map | grep cookie
  • Ensure assets/app.js imports the CSS

Session cookie created before consent

  • Check enforcement.require_consent_for_session is true
  • Add routes to stateless_routes if they should work without session
  • Verify #[ConsentStateless] attribute on stateless controllers

Doctrine storage not working

  • Run migrations: bin/console doctrine:migrations:diff && bin/console doctrine:migrations:migrate
  • Check storage: doctrine or storage: both is set
  • Verify doctrine/orm and doctrine/doctrine-bundle are installed

Google Consent Mode not updating

  • Ensure google_consent_mode.enabled: true
  • Check gtag is loaded before the consent modal
  • Verify category mapping matches your categories

Tabler variant styling issues (missing border-radius, labels below checkbox)

  • Cause: Tabler loads after bundle CSS and overrides .modal-content and form-switch styles
  • Solution: Update to latest bundle version (>= 0.4.2) which includes Tabler-specific fixes
  • Manual fix: Add to your CSS with higher specificity:
.cookie-consent-modal.cookie-consent-variant-tabler .modal-content {
    border: 0;
    border-radius: var(--cc-radius, 18px);
    box-shadow: var(--cc-shadow, 0 24px 60px rgba(15, 23, 42, 0.25));
}
.cookie-consent-variant-tabler .cookie-consent-toggle.form-switch {
    display: block;
    padding-left: 2.5rem;
}
.cookie-consent-variant-tabler .cookie-consent-toggle.form-switch .form-check-input {
    float: left;
    margin-left: -2.5rem;
}

Contributing

composer install
composer ci

License

MIT - see LICENSE.

Resources

Keywords

Symfony cookie consent, GDPR cookie banner, DSGVO cookie modal, Google Consent Mode v2, Symfony 8 bundle, cookie management, consent management platform, CMP, Twig cookie component, Stimulus.js cookie, AssetMapper, Doctrine consent storage, YouTube embed consent, privacy compliance, e-privacy.