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.

Maintainers

Package info

github.com/jostkleigrewe/cookie-consent-bundle

Type:symfony-bundle

pkg:composer/jostkleigrewe/cookie-consent-bundle

Fund package maintenance!

jostkleigrewe

Statistics

Installs: 59

Dependents: 0

Suggesters: 0

Stars: 1

Open Issues: 0

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.