Cookie consent bar for October CMS with native Google Consent Mode v2 — no pasted gtag/GTM snippets needed.
Cookies & Consent Mode
- One Tag ID field — enter a GA4 (
G-…) or GTM (GTM-…) ID and the plugin renders the loader automatically - Map cookie groups to Google consent types (
analytics_storage,ad_storage,ad_user_data, …) — the plugin builds thegtag('consent', 'update', …)for you - Persistent consent — the choice is re-applied on every page load, not just after clicking the bar
cookie_consent_updatedataLayer event on every change/page load — fire non-Google tags (Meta Pixel, LinkedIn Insight, Hotjar, …) via a Custom Event trigger in GTM- Modern floating-pill bar + native
<dialog>settings window — no Bootstrap dependency, fully themable via CSS custom properties - Custom
<head>/<body>code fields for anything the plugin doesn't load directly - Manage cookies component (and Static Pages snippet) for your privacy/GDPR page
- Fully translatable (with RainLab.Translate)
- Import & export your settings as presets (or use the bundled default)
- Advanced: optional per-group custom scripts with head/body placement, production-only and per-page limits
This plugin is also included into the following bundle
Installation via Command Line
php artisan plugin:install JanVince.SmallGDPR
Small GDPR
Cookie consent bar for October CMS with native Google Consent Mode v2.
Version 2 is a major rewrite: the plugin now owns the Consent Mode plumbing.
You map cookie groups to Google consent types and the plugin emits the
gtag('consent', 'update', …) signal and a dataLayer event on every page
load and consent change — no pasted gtag/GTM snippets needed for the common case.
Upgrading from 1.x? v2.0 is a conscious major upgrade (bump the version in
composer.json). A migration moves your data to the new schema automatically (it guessesconsent_typesfrom group slugs and copies your button labels). The Bootstrap dependency and the old style presets are gone — there is now a single floating-pill bar and a native<dialog>settings window, themable via CSS custom properties.
Installation
GitHub — clone into the /plugins dir:
git clone https://github.com/jan-vince/smallgdpr plugins/janvince/smallgdpr
October backend — search for Small GDPR in:
Settings → Updates & Plugins → Install plugins
Quick start
- Settings → Small GDPR → Settings → Import → Import default settings.
- Settings → Small GDPR → Cookies → Integration:
Tag type= Google Analytics 4 or Google Tag ManagerTag ID=G-XXXXXXX(GA4) orGTM-XXXXXXX(GTM)
- Add the two components to your layout — both are required:
<head>
...
{# REQUIRED — must be inside <head>, as high as possible,
before any analytics / tag scripts #}
{% component 'cookiesConfig' %}
</head>
<body>
{# right after <body> opens #}
{% component 'cookiesBar' %}
...
</body>
⚠️
cookiesConfigmust live in<head>. It sets the Consent Modedefaultand loads the GA4/GTM tag, and that has to happen before any tag fires. Put it as high in<head>as possible (ideally first). Without it the bar still renders, but no tags are loaded and consent is never applied.
- (Optional) create a
/gdprpage and drop in the Manage cookies component (or its page snippet) so visitors can change their choice later.
That's it — no need to paste GA4/GTM code anywhere. The plugin renders the loader, the consent default, the consent update and the dataLayer event for you.
How it works
cookiesConfig(head) outputs, in order: thedataLayer/gtagstub, the Consent Modedefault(seeded from saved cookies so returning visitors startgranted), the GA4/GTM loader (fromTag ID), your custom head code, and the plugin JS.cookiesBar(body) renders the GTM<noscript>(GTM only), your custom body code, the floating-pill bar and the settings<dialog>.- On every consent change and every page load (once a decision exists), the
JS calls
gtag('consent', 'update', …)and pushes adataLayerevent so non-Google tags can fire via a Custom Event trigger:
dataLayer.push({
event: 'cookie_consent_update',
analytics_storage: 'granted',
ad_storage: 'denied',
ad_user_data: 'denied',
ad_personalization: 'denied'
});
Settings
Tab: Cookies
Integration
Tag type—none/Google Analytics 4 (gtag.js)/Google Tag Manager.Tag ID—G-…orGTM-…. The plugin renders the matching loader.Load tags only in production— when on, the loader is rendered only in the production environment (the bar still works everywhere so you can test the UI).Consent dataLayer event name— defaultcookie_consent_update.
Cookies groups — one group per cookie category (Necessary, Statistical, Marketing, …):
Required— cannot be disabled by the user.Default enabled— active without explicit consent (use for anonymous data only, mind your local laws).Default checked— pre-checked in the settings dialog (scripts still gated).Google consent types— which Consent Mode signals this group grants (analytics_storage,ad_storage,ad_user_data,ad_personalization,functionality_storage,personalization_storage,security_storage). This mapping drives the automatic consent update.Scripts(advanced) — optional raw JS/files injected server-side when the group is consented, withhead/bodyposition, production and per-page limits. Most setups won't need this — use GTM + the dataLayer event instead.
Custom code — raw <head> / <body> code injected after the plugin block,
for tags the plugin does not load directly (Meta, LinkedIn, Hotjar, …).
Tab: Cookies bar
Title, content, page-reload toggle, and the button labels / visibility (Accept, Reject, Settings, Save).
Tab: Manage cookies
Title and content shown above the cookie list in the Manage cookies component / dialog.
Tab: Settings
Cookies expiration— cookie lifetime in days.Set cookies for each language— adds a locale prefix to cookie names (for RainLab.Translate setups that need a separate consent per language).- Import — import a YAML preset from Media, a custom path, or the bundled default (leave empty).
- Export — export current settings as a YAML preset (backup / template).
Components
cookiesConfig
Place inside <head>, as high as possible. Renders the Consent Mode init and the
tag loader.
cookiesBar
Place right after <body>. Renders the bar and the settings dialog.
Hide the bar on a specific page/layout via the View Bag:
[viewBag] hideCookiesBar = 1
cookiesManage
Put on a privacy page (e.g. /gdpr) so visitors can change their choice. Also
available as a Static Pages snippet.
JavaScript API
A global SmallGDPR object is available:
SmallGDPR.get() // { necessary: true, statistical: false, … }
SmallGDPR.set(state) // persist a state object + emit signals
SmallGDPR.acceptAll()
SmallGDPR.rejectAll()
SmallGDPR.hasDecision() // has the user decided yet?
SmallGDPR.openSettings()
Listen for changes:
document.addEventListener('smallgdpr:consent', function (e) {
console.log(e.detail.state, e.detail.consent);
});
Twig
With the cookiesBar or cookiesManage component on the page you can read the
consent state in Twig:
{% if sgCookies.statistical %}
...
{% endif %}
Theming
The bar and dialog are styled with CSS custom properties — override them in your own stylesheet (no Bootstrap required):
:root {
--sg-bg: #1a2842;
--sg-primary: #0d6efd;
--sg-text: #ffffff;
/* … see assets/css/smallgdpr.css for the full list */
}
Thanks to the October CMS team and to OFFLINE for inspiration from their GDPR plugin.
Created by Jan Vince, freelance web designer from the Czech Republic.
-
Paolo M
Found the plugin useful on 1 Feb, 2022
Very good plugin, complete and easy to set up. Nice work, thanks
-
Jan Vince author
Replied on 1 Feb, 2022
Hi and thank you!
-
Ostlancer FZE LLC
Found the plugin useful on 20 Mar, 2021
This is a really useful solution for modern websites. Thanks and respect to the author.
-
Jan Vince author
Replied on 20 Mar, 2021
Thanks, i appreciate it!
Jan
-
Romain 'Maz' BILLOIR
Found the plugin useful on 16 Jul, 2020
It's already a must have plugin! The ability to manage cookies' categories independently is such a great feature.
Working on an implementation using TailwindCSS, I was afraid about the support but really well-surprised of the good design of the code (at least the components partial, didn't look yet the PHP code :) ).
I will share my TwCSS implementation in this comment in few days for those who want.
Thanks Jan Vince for the work!
-
Jan Vince author
Replied on 17 Jul, 2020
Thank you :)
Best regards,
Jan
-
| 2.0.3 |
Update composer/installers version for PHP 8.4 compatibility. Tanks @eoler. Jul 05, 2026 |
|---|---|
| 2.0.2 |
Compatibility fix: settings page no longer throws "undefined method formBeforeSave" when saving a translatable field via the multisite translate popup (RainLab.Translate v2 + Multisite on newer OctoberCMS). Thanks @mcoredev. Jun 25, 2026 |
| 2.0.1 |
Fixed Manage cookies (/gdpr) styling on light backgrounds; bumped asset cache-busting version. Jun 21, 2026 |
| 2.0.0 |
Major rewrite. Native Google Consent Mode v2: map cookie groups to Google consent types, plugin emits gtag consent update + a dataLayer event on every page load and consent change. Jun 15, 2026 |
| 1.29.0 |
Added 'Floating pill (BS5)' style preset and modal May 16, 2026 |
| 1.28.2 |
Removed remaining jQuery dependency from frontend components (list-cookies, cookiesmanage), replaced with vanilla JS and native Bootstrap 5 Modal API May 16, 2026 |
| 1.28.1 |
Fixed CSS styles Feb 12, 2026 |
| 1.28.0 |
Added option to run JS script after Disable-all Button click Aug 04, 2025 |
| 1.27.1 |
Added btn-disable-all class to cookiesbar-btn-default Mar 07, 2025 |
| 1.27.0 |
French translation (thanks Jean-Daniel Kneubühler) Mar 21, 2024 |
| 1.26.1 |
Modal reload logic updated Mar 12, 2024 |
| 1.26.0 |
Updated templates for Google Consent v2 Mar 01, 2024 |
| 1.25.0 |
Simplified Chinese Language (thanks @ZhiweiWu0425) Mar 01, 2024 |
| 1.24.0 |
Replaced jQuery with vanilla JS (thanks @anik1ng) Dec 16, 2023 |
| 1.23.1 |
Fixed export settings Nov 25, 2023 |
| 1.23.0 |
Added option to run JS script after Accept-all Button click May 13, 2023 |
| 1.22.0 |
Strict variables fix (thanks @SamBrishes) Mar 29, 2023 |
| 1.21.0 |
OC3 compatibility Nov 09, 2022 |
| 1.20.0 |
Added option to pre-check cookies list items in modal window Sep 21, 2022 |
| 1.19.1 |
Fixed css Sep 21, 2022 |
| 1.19.0 |
Updated preset Sep 17, 2022 |
| 1.18.2 |
Fixed Twig code for OC3 Sep 17, 2022 |
| 1.18.1 |
Fixed version yaml for OC3 May 21, 2022 |
| 1.18.0 |
Added Finnish language (thanks mediaclinic) Mar 01, 2022 |
| 1.17.0 |
Updated default presets with Google Analytics code to run without consent with disabled storage Feb 06, 2022 |
| 1.16.0 |
Added option to require cookies consent for each web site language separately Feb 06, 2022 |
| 1.15.5 |
Fixed bug in Bootstrap 5 modal form template Feb 06, 2022 |
| 1.15.4 |
Fixed bug in JS Jan 18, 2022 |
| 1.15.3 |
Updated presets texts Jan 16, 2022 |
| 1.15.2 |
Updated css for Bootstrap box UI Jan 13, 2022 |
| 1.15.1 |
Fixed cookies bar buttons function Jan 13, 2022 |
| 1.15.0 |
Added Reject all button onption, updated import presets Jan 10, 2022 |
| 1.14.2 |
Updated css styles for topline strip in container Sep 07, 2021 |
| 1.14.1 |
Fixed css styles for topline strip in container Sep 07, 2021 |
| 1.14.0 |
Added option to display top strip in Bootstrap container Sep 07, 2021 |
| 1.13.0 |
Updated default presets with new GA code Sep 01, 2021 |
| 1.12.1 |
Fixed modal hide function Mar 19, 2021 |
| 1.12.0 |
Fixed versions numbering Mar 19, 2021 |
| 1.11.2 |
!!! If you edited default components markup (or you use only parts of it), please check if everything works after update. If you use plugin as is, you should be fine :) Mar 19, 2021 |
| 1.10.2 |
Fixed external URL handling with cookies bar buttons Mar 19, 2021 |
| 1.10.1 |
Fixed cookie lifetime function Mar 19, 2021 |
| 1.10.0 |
Added Slovak translation, fixed Czech translation Feb 01, 2021 |
| 1.9.1 |
Added optional Cookies bar strip CSS styles Jan 30, 2021 |
| 1.8.1 |
Updated Bootstrap 5 modal support (thanks evwerkz) Jan 04, 2021 |
| 1.8.0 |
Added Russian and German language (thanks evwerkz) Dec 21, 2020 |
| 1.7.1 |
Fixed HTML attributes field localization in Settings Nov 24, 2020 |
| 1.7.0 |
Added option to specify pages to run scripts on Nov 19, 2020 |
| 1.6.0 |
Changed settings for import (added second btn for import default settings) Nov 19, 2020 |
| 1.5.1 |
Changed buttons HTML attributes field to prevent naming collision Nov 03, 2020 |
| 1.5.0 |
Added Twig support for Translate plugin (thanks evwerkz) Aug 07, 2020 |
| 1.4.11 |
Fixed localization Aug 05, 2020 |
| 1.4.10 |
Moved modal help-block div from label tag (to be HTML5 valid) Jul 31, 2020 |
| 1.4.9 |
Fixed CookiesSettings model Jun 29, 2020 |
| 1.4.8 |
Added sgCookies to Cookies Manage component (for case when you do not want to use Cookies Bar in your layout or page) Jun 27, 2020 |
| 1.4.7 |
Fixed components file name case Jun 25, 2020 |
| 1.4.6 |
Updated translation and docs. Jun 23, 2020 |
| 1.4.5 |
!!! Cookies JS code placed in code window now requires <script> tags to be present! Please check your code. Jun 23, 2020 |
| 1.4.4 |
Fixed folders and models name case Jun 23, 2020 |
| 1.4.3 |
Fixed migration not working on new installs Jun 23, 2020 |
| 1.4.2 |
Removed forgotten dump Jun 23, 2020 |
| 1.4.1 |
Extended import tab to be able to use Media, own path or default preset file Jun 23, 2020 |
| 1.4.0 |
Added option do have more scripts and files in scripts group (old scripts data are automatically migrated to the new structure) Jun 23, 2020 |
| 1.3.2 |
Fixed import function Jun 22, 2020 |
| 1.3.1 |
Import file can be now selected from Media panel Jun 22, 2020 |
| 1.3.0 |
Added export settings function Jun 22, 2020 |
| 1.2.7 |
Changed fields order in form Jun 22, 2020 |
| 1.2.6 |
Added option to run JS only in production mode Jun 22, 2020 |
| 1.2.5 |
Updated styling, removed unnecessary styles Jun 22, 2020 |
| 1.2.4 |
Added optional cookies group script file to be executed Jun 21, 2020 |
| 1.2.3 |
Updated hideCookiesBar check to support Static Pages Jun 21, 2020 |
| 1.2.2 |
Added option to hide Cookies bar on specific Page or Layout with View Bag property Jun 21, 2020 |
| 1.2.1 |
Fixed values checks in CookiesSettings Jun 21, 2020 |
| 1.2.0 |
Added Default enabled option for cookies groups for cookies to be executed without explicit consent Jun 21, 2020 |
| 1.1.9 |
Removed unnecessary line in Manage cookies component Jun 21, 2020 |
| 1.1.8 |
Added Static Pages snippet for Cookies manage component Jun 20, 2020 |
| 1.1.7 |
Removed option Default active Jun 20, 2020 |
| 1.1.6 |
Fixed default active cookies group to be active even without explicit consent Jun 20, 2020 |
| 1.1.5 |
Fixed default EN preset Jun 20, 2020 |
| 1.1.4 |
Fixed sgCookies array Jun 20, 2020 |
| 1.1.3 |
Fixed scripts Jun 20, 2020 |
| 1.1.2 |
Fixed sgCookies array to reflect required cookies group state Jun 20, 2020 |
| 1.1.1 |
Updated default presets and README Jun 20, 2020 |
| 1.1.0 |
Added settings in modal window Jun 20, 2020 |
| 1.0.0 |
First version of Small GDPR Jun 19, 2020 |



