🍪 Simple cross-browser cookie-consent plugin written in vanilla js.
npm install mlj-cookieForked to publish in the NPM registry. No further
changes. Thanks and credits to Orest Bida.
---

!Size

A __lightweight__ & __gdpr compliant__ cookie consent plugin written in plain javascript. An "all-in-one" solution which also allows you to write your cookie policy inside it without the need of having a dedicated page.
``bash`
# CDN links
https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@v2.8.0/dist/cookieconsent.js
https://cdn.jsdelivr.net/gh/orestbida/cookieconsent@v2.8.0/dist/cookieconsent.css
Thanks to Till Sanders for bringing the plugin on npm.
`bash`
npm i vanilla-cookieconsent
yarn add vanilla-cookieconsent
1. Import the plugin: add a script tag pointing to cookieconsent.js`
html`
Note: replace with a valid path!
3. Configure and run - Create a .js ` - Configure the plugin inside cookieconsent-init.js ` // run plugin with your configuration // mode: 'opt-in' // default: 'opt-in'; value: 'opt-in' or 'opt-out' onFirstAction: function(user_preferences, cookie){ onAccept: function (cookie) { onChange: function (cookie, changed_preferences) { languages: { `
- As external script
file (e.g. cookieconsent-init.js) and import it in your html pagehtml`
javascript
// obtain plugin
var cc = initCookieConsent();
cc.run({
current_lang: 'en',
autoclear_cookies: true, // default: false
page_scripts: true, // default: false
// delay: 0, // default: 0
// auto_language: null // default: null; could also be 'browser' or 'document'
// autorun: true, // default: true
// force_consent: false, // default: false
// hide_from_bots: false, // default: false
// remove_cookie_tables: false // default: false
// cookie_name: 'cc_cookie', // default: 'cc_cookie'
// cookie_expiration: 182, // default: 182 (days)
// cookie_necessary_only_expiration: 182 // default: disabled
// cookie_domain: location.hostname, // default: current domain
// cookie_path: '/', // default: root
// cookie_same_site: 'Lax', // default: 'Lax'
// use_rfc_cookie: false, // default: false
// revision: 0, // default: 0
// callback triggered only once
},
// ...
},
// ...
},
'en': {
consent_modal: {
title: 'We use cookies!',
description: 'Hi, this website uses essential cookies to ensure its proper operation and tracking cookies to understand how you interact with it. The latter will be set only after consent. ',
primary_btn: {
text: 'Accept all',
role: 'accept_all' // 'accept_selected' or 'accept_all'
},
secondary_btn: {
text: 'Reject all',
role: 'accept_necessary' // 'settings' or 'accept_necessary'
}
},
settings_modal: {
title: 'Cookie preferences',
save_settings_btn: 'Save settings',
accept_all_btn: 'Accept all',
reject_all_btn: 'Reject all',
close_btn_label: 'Close',
cookie_table_headers: [
{col1: 'Name'},
{col2: 'Domain'},
{col3: 'Expiration'},
{col4: 'Description'}
],
blocks: [
{
title: 'Cookie usage 📢',
description: 'I use cookies to ensure the basic functionalities of the website and to enhance your online experience. You can choose for each category to opt-in/out whenever you want. For more details relative to cookies and other sensitive data, please read the full privacy policy.'
}, {
title: 'Strictly necessary cookies',
description: 'These cookies are essential for the proper functioning of my website. Without these cookies, the website would not work properly',
toggle: {
value: 'necessary',
enabled: true,
readonly: true // cookie categories with readonly=true are all treated as "necessary cookies"
}
}, {
title: 'Performance and Analytics cookies',
description: 'These cookies allow the website to remember the choices you have made in the past',
toggle: {
value: 'analytics', // your cookie category
enabled: false,
readonly: false
},
cookie_table: [ // list of all expected cookies
{
col1: '^_ga', // match all cookies starting with "_ga"
col2: 'google.com',
col3: '2 years',
col4: 'description ...',
is_regex: true
},
{
col1: '_gid',
col2: 'google.com',
col3: '1 day',
col4: 'description ...',
}
]
}, {
title: 'Advertisement and Targeting cookies',
description: 'These cookies collect information about how you use the website, which pages you visited and which links you clicked on. All of the data is anonymized and cannot be used to identify you',
toggle: {
value: 'targeting',
enabled: false,
readonly: false
}
}, {
title: 'More information',
description: 'For any queries in relation to our policy on cookies and your choices, please contact us.',
}
]
}
}
}
});
`
- As inline script
html
`
inside the config. object; example:`javascript
cookieconsent.run({
// ...
gui_options: {
consent_modal: {
layout: 'cloud', // box/cloud/bar
position: 'bottom center', // bottom/middle/top + left/right/center
transition: 'slide', // zoom/slide
swap_buttons: false // enable to invert buttons
},
settings_modal: {
layout: 'box', // box/bar
// position: 'left', // left/right
transition: 'slide' // zoom/slide
}
}
//...
});
`
Default layout is box and default transition is zoom.
How to block/manage scripts
You can manage any script (inline or external) via the page_scripts option:1. Enable page scripts management:
`javascript
cookieconsent.run({
// ...
page_scripts: true
// ...
});
`
2. Set type="text/plain" and data-cookiecategory=" to any script tag you want to manage:
`html
`
Note: data-cookiecategory must be a valid category defined inside the configuration object
API methods
After getting the plugin like so:`javascript
var cookieconsent = initCookieConsent();
`the following methods are available:
- cookieconsent
.run(
- cookieconsent.show(
- cookieconsent.hide()
- cookieconsent.showSettings(
- cookieconsent.hideSettings()Additional methods for an easier management of your scripts and cookie settings (expand them to see usage example):
- cookieconsent.accept(<accepted_categories>, <optional_rejected_categories>) [v2.5.0+]
- accepted_categories:
string or string[]
- rejected_categories: string[] - optional
Note: all categories marked as
readonly will ALWAYS be enabled/accepted regardless of the categories provided inside the .accept() API call. Examples:
`javascript
cookieconsent.accept('all'); // accept all categories
cookieconsent.accept([]); // accept none (reject all)
cookieconsent.accept('analytics'); // accept only analytics category
cookieconsent.accept(['cat_1', 'cat_2']); // accept only these 2 categories
cookieconsent.accept(); // accept all currently selected categories inside modal cookieconsent.accept('all', ['analytics']); // accept all except "analytics" category
cookieconsent.accept('all', ['cat_1', 'cat_2']); // accept all except these 2 categories
` How to later reject a specific category (cookieconsent already accepted)? Same as above:
`javascript
cookieconsent.accept('all', ['targeting']); // opt out of targeting category
`
- cookieconsent.allowedCategory(<category_name>)
Note: there are no default cookie categories, you create them!
A cookie category corresponds to the string of the value property inside the toggle object:
`javascript
// ...
toggle: {
value: 'analytics', // cookie category
enabled: false, // default status
readonly: false // allow to enable/disable
// reload: 'on_disable', // allows to reload page when the current cookie category is deselected
}
// ...
` Example:
`javascript
// Check if user accepts cookie consent with analytics category enabled
if (!cookieconsent.allowedCategory('analytics')) {
// yoo, you might want to load analytics.js ...
};
`
- cookieconsent.validCookie(<cookie_name>)
If cookie exists and has non empty ('') value => return true, otherwise false.
`javascript
// Example: check if '_gid' cookie is set
if (!cookieconsent.validCookie('_gid')) {
// yoo, _gid cookie is not set, do something ...
};
`
- cookieconsent.eraseCookies(<cookie_names>, <optional_path>, <optional_domains>) [v2.5.0+]
- cookie_names:
string[]
- path: string - optional
- domains: string[] - optional
Examples:
`javascript
cookieconsent.eraseCookies(['cc_cookies']); // erase "cc_cookie" if it exists
cookieconsent.eraseCookies(['cookie1', 'cookie2']); // erase these 2 cookies cookieconsent.eraseCookies(['cc_cookie'], "/demo");
cookieconsent.eraseCookies(['cc_cookie'], "/demo", [location.hostname]);
`
- cookieconsent.loadScript(<path>, <callback_function>, <optional_custom_attributes>)
Basic example:
`javascript
cookieconsent.loadScript('https://www.google-analytics.com/analytics.js', function(){
// Script loaded, do something
});
`
How to load scripts with custom attributes:
`javascript
cookieconsent.loadScript('https://www.google-analytics.com/analytics.js', function(){
// Script loaded, do something
}, [
{name: 'id', value: 'ga_id'},
{name: 'another-attribute', value: 'value'}
]);
`
- cookieconsent.set(<field>, <object>) [v2.6.0+]
The
.set() method allows you to set the following values:
- data (used to save custom data inside the plugin's cookie)
- revision
How to save custom
data:
`javascript
// Set cookie's "data" field to whatever the value of the value prop. is
cookieconsent.set('data', {value: {id: 21, country: "italy"}}); // Only add/update the specified props.
cookieconsent.set('data', {value: {id: 22, new_prop: 'new prop value'}, mode: 'update'});
`
- cookieconsent.get(<field>) [v2.6.0+]
The
.get() method allows you to retrieve any of the fields inside the plugin's cookie:
`javascript
cookieconsent.get('level'); // retrieve all accepted categories (if cookie exists)
cookieconsent.get('data'); // retrieve custom data (if cookie exists)
cookieconsent.get('revision'); // retrieve revision number (if cookie exists)
`
- cookieconsent.getConfig(<field>) [v2.7.0+]
The
.getConfig() method allows you to read configuration options from the current instance:
`javascript
cookieconsent.getConfig('current_lang'); // get currently used language
cookieconsent.getConfig('cookie_expiration'); // get configured cookie expiration
// ...
`
- cookieconsent.getUserPreferences() [v2.7.0+]
The
.getUserPreferences() returns the following object (for analytics/logging purposes):
`javascript
{
accept_type: string, // 'all', 'necessary', 'custom'
accepted_categories: string[], // e.g. ['necessary', 'analytics']
rejected_categories: string[] // e.g. ['ads']
}
`
- cookieconsent.updateScripts() [v2.7.0+]
This method allows the plugin to manage dynamically added/injected scripts that have been loaded after the plugin's execution.
E.g. dynamic content generated by server side languages like php, node, ruby ...
- cookieconsent.updateLanguage(<language>, <force_update>) [v2.8.0+]
Use this method to change modal's language dynamically (without page reload).
- language:
string
- force_update: boolean - optional
Example:
`javascript
cookieconsent.updateLanguage('it');
` Note: language will change only if it is valid (already defined) and different from the current language!
You can also forcefully update the modals (useful if you dynamically change the content of the modals). Example:
`javascript
// Change content: e.g. modify modal title
cookieconsent.getConfig('languages').en.consent_modal.title = 'New title'; // Update changes
cookieconsent.updateLanguage('en', true);
`
Available
data-cc actions
Any button (or link) can use the custom data-cc attribute to perform a few actions without manually invoking the api methods.Valid values:
-
c-settings: show settings modal
- accept-all: accept all categories
- accept-necessary: accept only categories marked as necessary/readonly (reject all)
- accept-custom: accept currently selected categories inside the settings modalExamples:
`html
`
Available callbacks
The following functions have to be defined inside the configuration object passed to the .run() method.- onAccept
This function will be executed:
- at the first moment that consent is given (just like
onFirstAction)
- after every page load, if consent (accept or "reject" action) has already been given
parameters:
-
cookie: contains the current value of the cookie
example:
`javascript
//...
cc.run({
// ...
onAccept: function(cookie){
// load somescript, google analytics ...
},
// ...
});
`
- onChange
This function will be executed (only if consent has already been given):
- when user changes his preferences (accepts/rejects a cookie category)
parameters:
-
cookie: contains the current value of the cookie
- changed_categories: array of categories whose state (accepted/rejected) just changed
example:
`javascript
//...
cc.run({
// ...
onChange: function(cookie, changed_categories){
// cleanup logic ... (e.g. disable gtm if analytics category is disabled)
},
// ...
});
`
- onFirstAction [v2.7.0+]
This function will be executed only once, when the user takes the first action (accept/reject).
parameters:
-
user_preferences: contains the same data provided by the .getUserPreferences() API
- cookie: contains the current value of the cookie
example:
`javascript
//...
cc.run({
// ...
onFirstAction: function(user_preferences, cookie){
console.log('User accept type:', user_preferences.accept_type);
console.log('User accepted these categories', user_preferences.accepted_categories)
console.log('User reject these categories:', user_preferences.rejected_categories);
},
// ...
});
`
$3
Below a table which sums up all of the available options (must be passed to the .run() method).
| Option | Type | Default | Description |
|--------------------- |---------- |--------- |---------------------------------------------------------------------------------------------------------------------------------- |
|
autorun | boolean | true | If enabled, show the cookie consent as soon as possible (otherwise you need to manually call the .show() method) |
| delay | number | 0 | Number of milliseconds before showing the consent-modal |
| mode | string | 'opt-in' |Accepted values:
- opt-in: scripts will not run unless consent is given (gdpr compliant)
- opt-out: scripts — that have categories set as enabled by default — will run without consent, until an explicit choice is made |
| cookie_expiration | number | 182 | Number of days before the cookie expires (182 days = 6 months) |
| cookie_necessary_only_expiration | number | - | Specify if you want to set a different number of days - before the cookie expires - when the user accepts only the necessary categories |
| cookie_path | string | "/" | Path where the cookie will be set |
| cookie_domain | string | location.hostname | Specify your domain (will be grabbed by default) or a subdomain |
| cookie_same_site | string | "Lax" | SameSite attribute |
| use_rfc_cookie | boolean | false | Enable if you want the value of the cookie to be rfc compliant |
| force_consent | boolean | false | Enable if you want to block page navigation until user action (check faq for a proper implementation) |
| revision | number | 0 | Specify this option to enable revisions. Check below for a proper usage |
| current_lang | string | - | Specify one of the languages you have defined (can also be dynamic): 'en', 'de' ... |
| auto_language | string | null | Language auto-detection strategy. Null to disable (default), "browser" to get user's browser language or "document" to read value from of current page. If language is not defined => use specified current_lang |
| autoclear_cookies | boolean | false | Enable if you want to automatically delete cookies when user opts-out of a specific category inside cookie settings |
| page_scripts | boolean | false | Enable if you want to easily manage existing
`
, cookie tables, opt-in/out toggle for each category and more. For each language, a consent_modal object and a settings_modal object must be configured.Example with multiple languages ('en' and 'it')
`javascript
cookieconsent.run({
// ...,
languages: {
'en': {
consent_modal: {
title: 'Title here ...',
description: 'Description here ...',
primary_btn: {
text: 'Accept',
role: 'accept_all' // 'accept_selected' or 'accept_all'
},
secondary_btn: {
text: 'Settings',
role: 'settings' // 'settings' or 'accept_necessary'
}
},
settings_modal: {
title: 'Cookie preferences ...',
save_settings_btn: 'Save settings',
accept_all_btn: 'Accept all',
blocks: [
{
title: 'First block title ...',
description: 'First block description ...'
}, {
title: 'Second block title ...',
description: 'Second block description ...',
toggle: {
value: 'my_category1',
enabled: true,
readonly: true
}
}, {
title: 'Third block title ...',
description: 'Third block description ...',
toggle: {
value: 'my_category2',
enabled: false,
readonly: false
}
}
]
}
},
'it': {
consent_modal: {
title: 'Title in italian here ...',
description: 'Description in italian here ...',
primary_btn: {
text: 'Accept in italian',
role: 'accept_all' //'accept_selected' or 'accept_all'
},
secondary_btn: {
text: 'Settings',
role: 'settings' //'settings' or 'accept_necessary'
}
},
settings_modal: {
title: 'Cookie preferences ...',
save_settings_btn: 'Save settings in italian',
accept_all_btn: "Accept all",
blocks: [
{
title: 'First block title in italian ...',
description: 'First block description in italian ...'
}, {
title: 'Second block title in italian ...',
description: 'Second block description in italian...',
toggle: {
value: 'my_category1',
enabled: true,
readonly: true
}
}, {
title: 'Third block title in italian ...',
description: 'Third block description in italian...',
toggle: {
value: 'my_category2',
enabled: false,
readonly: false
}
}
]
}
}
}
});
`
Example with custom cookie table
You can create tables with a custom number of columns to explain what each cookie does.
NOTE: If you want to also use
autoclear_cookie, make sure the first column of the cookie table contains the name of the cookie.Check demo app.js which has a full example with cookie table.
How to enable/manage revisions
Note:
- default revision number is 0
- if existing revision number is different from the one you just specified => show consent modal1. Enable revisions by specifying a valid
revision parameter:
`javascript
cookieconsent.run({
// ...,
revision: 1,
// ...
})
`2. Set a valid
revision_message parameter (optional) inside consent_modal, and add the following placeholder {{revision_message}} inside description:
`javascript
cookieconsent.run({
// ...,
revision: 1,
// ...,
languages: {
en: {
consent_modal: {
// ...,
description: 'Usual description ... {{revision_message}}',
revision_message: '
Dude, my terms have changed. Sorry for bothering you again!',
// ...
},
// ...
}
}
// ...
})
`FAQ
- How to enable dark-mode
Either manually add the following class
c_darkmode to the body/html tag, or toggle it via javascript:
`javascript
document.body.classList.toggle('c_darkmode');
`
- How to add link/button to open cookie settings
Create a button (or link) with
data-cc="c-settings" attribute:
`javascript
`
- How to integrate with my multi-language website
If you have multiple versions of your html page, each with a different <html lang="..." > attribute, you can grab this value using:
`javascript
document.documentElement.getAttribute('lang');
` and then set it as
current_lang value like this:
`javascript
cookieconsent.run({
// ...
current_lang: document.documentElement.getAttribute('lang'),
// ...
});
` Note: make sure that the lang attribute's value format (example: 'en' => 2 characters) is identical to the ones you defined. If you have 'en-US' as lang attribute, make sure to also specify 'en-US' (and not just 'en') in the config. parameters.
- How to load scripts after a specific cookie category has been accepted
Suppose you have a
analytics.js file you want to load after the analytics category has been accepted:
- Method 1 (recommended)
1. enable
page_scripts:
`javascript
cookieconsent.run({
// ...
page_scripts: true,
// ...
});
`
2. add a
- Method 2
Load script using the
.loadScript() method inside the onAccept method:
`javascript
cookieconsent.run({
// ...
onAccept: function () {
if (cookieconsent.allowedCategory('analytics')) {
cookieconsent.loadScript(' // script loaded ...
});
}
}
})
`
- Make consent required (block page navigation until action)
This is a css only solution:
1. enable
force_consent option:
`javascript
cookieconsent.run({
// ...
force_consent: true,
// ...
});
`
2. That should do it. If you want to remove the weird horizontal jump (due to the scrollbar disappearing) you can add the following style inside the head tag of your page:
`html
`
For a full example check the second demo.
- How to create custom cookie tables
- Cookie tables are defined by you, that is you choose how many columns and what their naming will be
- Make sure that the first column of the table contains the name of the cookie for autoclear_cookie to work properly
1. Specify the table structure via the
cookie_table_headers property inside settings_modal object: Example with 3 columns:
`javascript
// ...
cookie_table_headers: [
{col1: "Name"},
{col2: "Source"},
{col3: "Description"},
]
// ...
` 2. Now you can create a
cookie_table array of objects:
`javascript
// ...
cookie_table: [
{
col1: '_ga',
col2: 'google.com',
col3: 'description ..',
},
{
col1: '_gid',
col2: 'google.com',
col3: 'description ..',
}
]
// ...
` Check the examples above for a valid implementation.
- How to use in React
1. Create a new component:
CookieConsent.js
`javascript
import { useEffect } from "react"; import "./";
import "./";
export default function CookieConsent() {
useEffect(() => {
const cc = window.initCookieConsent();
cc.run({
// your config
});
}, []);
return null;
}
` 2. Import the component only once (generally in your main/root component like
App.js or index.js)
`javascript
import CookieConsent from "./"; export default function App() {
return (
Hello World
);
}
``