Stylish Multilingual GDPR & Cookie Consent Popup In Vanilla JavaScript

Category: Javascript , Recommended | February 5, 2025
Author:orestbida
Views Total:120 views
Official Page:Go to website
Last Update:February 5, 2025
License:MIT

Preview:

Stylish Multilingual GDPR & Cookie Consent Popup In Vanilla JavaScript

Description:

A standalone JavaScript library that displays a stylish, multilingual, customizable, accessible, GDPR compliant cookie consent popup to make your site comply with GDPR and EU Cookie Law.

Click the Learn More link to display Cookie Consent Policy content in a popup window.

More Features:

  • Auto language detection.
  • Configurable expiration date.
  • Easy to create your own styles.
  • Cookie settings modal.
  • Compatible with Vanilla JS, React, Angular, and Vue.

How to use it:

1. Install & download.

# Yarn
$ yarn add vanilla-cookieconsent
# NPM
$ npm install vanilla-cookieconsent
# PNPM
$ pnpm add vanilla-cookieconsent

2. Import JavaScript file cookieconsent.js and stylesheet cookieconsent.css into the HTML document.

<link href="/dist/cookieconsent.css" rel="stylesheet" />
<script type="module">
  import './dist/cookieconsent.umd.js';
</script>

3. Initialize the library and display the cookie consent popup on page load.

CookieConsent.run({
  // configs here
});

4. All the available configuration options.

CookieConsent.run({
  // root (parent) element where the modal will be appended as a last child
  root: 'body',
  // 'opt-in', 'opt-out'
  mode: 'opt-in',
  // auto-show the consent modal if consent is not valid
  autoShow: true,
  // create a dark overlay and blocks the page scroll until consent is expressed
  disablePageInteraction: true,
  // prevent bots from indexing the modal's content.
  hideFromBots: true,
  // manage consent revisions 
  revision: 0,
  // intercept all script tags with a data-category attribute, and enables them based on the accepted categories
  manageScriptTags: true,
  // clear cookies when user rejects a specific category
  autoClearCookies: true,
  // delay the generation of the modal's markup until they're about to become visible
  // useful to improve the TTI score
  lazyHtmlGeneration: true,
  // customize the plugin's cookies
  cookie: {
    name: 'cc_cookie',
    domain: window.location.hostname,
    path: '/',
    expiresAfterDays: 182,
    sameSite: 'Lax',
    useLocalStorage: false
  },
  guiOptions: {
    consentModal: {
      layout: 'box',
      position: 'bottom right',
      flipButtons: false,
      equalWeightButtons: true
    },
    preferencesModal: {
      layout: 'box',
      position: 'right',
      flipButtons: false,
      equalWeightButtons: true
    }
  },
  // callbacks
  onFirstConsent: ({
    cookie
  }) => {
    console.log('onFirstConsent fired', cookie);
  },
  onConsent: ({
    cookie
  }) => {
    console.log('onConsent fired!', cookie)
  },
  onChange: ({
    changedCategories,
    changedServices
  }) => {
    console.log('onChange fired!', changedCategories, changedServices);
  },
  onModalReady: ({
    modalName
  }) => {
    console.log('ready:', modalName);
  },
  onModalShow: ({
    modalName
  }) => {
    console.log('visible:', modalName);
  },
  onModalHide: ({
    modalName
  }) => {
    console.log('hidden:', modalName);
  },
  categories: {
    necessary: {
      enabled: true, // this category is enabled by default
      readOnly: true // this category cannot be disabled
    },
    analytics: {
      readOnly: false,
      autoClear: {
        cookies: [{
            name: /^_ga/, // regex: match all cookies starting with '_ga'
          },
          {
            name: '_gid', // string: exact cookie name
          }
        ]
      },
      services: {
        ga: {
          label: 'Google Analytics',
          onAccept: () => {},
          onReject: () => {},
          cookies: [
            {
              name: /^(_ga|_gid)/
            }
          ]
        },
        youtube: {
          label: 'Youtube Embed',
          onAccept: () => {},
          onReject: () => {}
        },
      }
    },
    ads: {}
  },
  language: {
    default: 'en',
    rtl: 'ar',  // enable RTL for Arabic
    autoDetect: 'browser', // 'document', 'browser'
    translations: {
      en: {
        consentModal: {
          title: 'We use cookies',
          description: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua',
          acceptAllBtn: 'Accept all',
          acceptNecessaryBtn: 'Reject all',
          showPreferencesBtn: 'Manage Individual preferences',
          // closeIconLabel: 'Reject all and close modal',
          footer: `
                        <a href="#path-to-impressum.html" target="_blank">Impressum</a>
                        <a href="#path-to-privacy-policy.html" target="_blank">Privacy Policy</a>
                    `,
        },
        preferencesModal: {
          title: 'Manage cookie preferences',
          acceptAllBtn: 'Accept all',
          acceptNecessaryBtn: 'Reject all',
          savePreferencesBtn: 'Accept current selection',
          closeIconLabel: 'Close modal',
          serviceCounterLabel: 'Service|Services',
          sections: [{
              title: 'Your Privacy Choices',
              description: `In this panel you can express some preferences related to the processing of your personal information. You may review and change expressed choices at any time by resurfacing this panel via the provided link. To deny your consent to the specific processing activities described below, switch the toggles to off or use the “Reject all” button and confirm you want to save your choices.`,
            },
            {
              title: 'Strictly Necessary',
              description: 'These cookies are essential for the proper functioning of the website and cannot be disabled.',
              //this field will generate a toggle linked to the 'necessary' category
              linkedCategory: 'necessary'
            },
            {
              title: 'Performance and Analytics',
              description: 'These cookies collect information about how you use our website. All of the data is anonymized and cannot be used to identify you.',
              linkedCategory: 'analytics',
              cookieTable: {
                caption: 'Cookie table',
                headers: {
                  name: 'Cookie',
                  domain: 'Domain',
                  desc: 'Description'
                },
                body: [{
                    name: '_ga',
                    domain: location.hostname,
                    desc: 'Description 1',
                  },
                  {
                    name: '_gid',
                    domain: location.hostname,
                    desc: 'Description 2',
                  }
                ]
              }
            },
            {
              title: 'Targeting and Advertising',
              description: 'These cookies are used to make advertising messages more relevant to you and your interests. The intention is to display ads that are relevant and engaging for the individual user and thereby more valuable for publishers and third party advertisers.',
              linkedCategory: 'ads',
            },
            {
              title: 'More information',
              description: 'For any queries in relation to my policy on cookies and your choices, please <a href="#contact-page">contact us</a>'
            }
          ]
        }
      }
    }
  }
});

5. API methods.

// show the cookie consent popup
cookieconsent.show();
// hide the cookie consent popup
CookieConsent.hide();
// show cookie settings
CookieConsent.showPreferences();
// hide cookie settings
cookieconsent.hidePreferences();
// accept all categories
CookieConsent.acceptCategory('all');    
// reject all            
CookieConsent.acceptCategory([]); 
// accept currently selected categories 
CookieConsent.acceptCategory(); 
// accept only the "analytics" category
CookieConsent.acceptCategory('analytics');          
// accept only these 2 categories
CookieConsent.acceptCategory(['cat_1', 'cat_2']);   
// accept all categories except the "analytics" category
CookieConsent.acceptCategory('all', ['analytics']); 
// accept all categories except these 2
CookieConsent.acceptCategory('all', ['cat_1', 'cat_2']); 
// accepted category
if(CookieConsent.acceptedCategory('analytics')){
  // great
}
if(!CookieConsent.acceptedCategory('ads')){
    // not so great
}
// accept all services
CookieConsent.acceptService('all', 'analytics');
// reject all services
CookieConsent.acceptService([], 'analytics');      
// accept only this specific service
CookieConsent.acceptService('service1', 'analytics');
// accept only these 2 services
CookieConsent.acceptService(['service1', 'service2'], 'analytics'); 
// accepted service
if(CookieConsent.acceptedService('Google Analytics', 'analytics')){
    // great
}else{
    // not so great
}
// check consent is valid
if(CookieConsent.validConsent()){
  // consent is valid
}else{
  // consent is not valid
}
// check cookie is valid
if(CookieConsent.validCookie('_gid')){
  // _gid cookie is valid!
}else{
  // _gid cookie is not set ...
}
// delete the plugin's own cookie
CookieConsent.eraseCookies('cc_cookie');
// Delete the _gid and all cookies starting with _ga
CookieConsent.eraseCookies(['_gid', /^_ga/], '/', location.hostname);
// load script
cookieconsent.loadScript(path, customAttributes>): Promise
// get only the 'data' field
const data = CookieConsent.getCookie('data');
// get all fields
const cookieContent = CookieConsent.getCookie();
// get the entire config
const config = CookieConsent.getConfig();
// get only the language' prop.
const language = CookieConsent.getConfig('language');
// get user's preferences
CookieConsent.getUserPreferences();
// changes the modal's language
CookieConsent.setLanguage('en', true);
// First set: true
CookieConsent.setData({
  value: {id: 21, lang: 'it'}
}); //{id: 21, lang: 'it'}
// Change only the 'id' field: true
CookieConsent.setData({
  value: {id: 22},
  mode: 'update'
}); //{id: 22, lang: 'it'}
// Add a new field: true
CookieConsent.setData({
  value: {newField: 'newValue'},
  mode: 'update'
}); //{id: 22, lang: 'it', newField: 'newValue'}
// Change 'id' to a string value: FALSE
CookieConsent.setData({
  value: {id: 'hello'},
  mode: 'update'
}); //{id: 22, lang: 'it', newField: 'newValue'}
// Overwrite: true
CookieConsent.setData({
  value: 'overwriteEverything'
}); // 'overwriteEverything'
// reset
CookieConsent.reset(true);

6. Enable a trigger button to toggle the cookie settings modal. Available data-cc actions:

  • show-preferencesModal
  • show-consentModal
  • accept-all
  • accept-necessary
  • accept-custom
<button data-cc="show-preferencesModal">View Preferences Modal</button>

Changelog:

v3.1.0 (02/05/2025)

  • feat: store language code of the consent in the cookie
  • bugfixes

v3.0.1 (04/02/2024)

  • fix: unhandled exception when category is unknown
  • fix: default enabled categories reset on preferences modal close

v3.0.0 (03/03/2024)

  • more granular control over scripts
  • better language/translation handling (allow the use of external .json files)
  • more intuitive and clearer configuration parameters
  • easier integration with various frameworks thanks to the ESM format
  • many new customization options (button/modal layouts)
  • multiple ways to handle your scripts, using either script-tags, callbacks or events
  • bugfixes

v2.9.2 (08/07/2023)

  • Fix a11y issue caused by missing aria-level attribute
  • Fix .updateScripts() method doesn’t work when mode is set to ‘opt-out’

v2.9.1 (08/07/2023)

  • Fix wrong toggle states after opening and closing the settings modal
  • Code refactoring
  • Update dependencies

v2.9.0 (04/21/2023)

  • Add new CSS variables
  • Allow custom script type via the data-type attribute
  • Add settings_modal.cookie_table_caption option for better a11y
  • Allow custom z-index value via the –cc-z-index css variable
  • Allow data-cc attributes on all HTML elements
  • Disable transitions if prefers-reduced-motion is enabled
  • Discard unsaved settings inside settings_modal
  • Fix focus restoration when modals are hidden
  • Small ui tweaks: slightly reduce padding
  • Remove old IE8 specific css rules
  • Update all dependencies
  • Code refactoring/cleanup

v2.8.9 (11/28/2022)

  • Bugfixes

v2.8.8 (10/18/2022)

  • Remove hardcoded css values for a simpler styling
  • Set z-index to highest possible value
  • Added css variable to configure border radius
  • Bugfix

v2.8.6 (09/03/2022)

  • Bugfix: cookie not deleted if not .domain.com
  • Restore level property to avoid breaking change in patch version

v2.8.5 (08/02/2022)

  • Bugfix

v2.8.4 (07/27/2022)

  • Fix incompatible/missing types

v2.8.3 (07/23/2022)

  • Fixed a UI bug
  • Added build tools (postcss && terser)
  • Minor UI tweak: modals have a slightly reduced padding

v2.8.2 (07/02/2022)

  • Set up automatic NPM releases
  • Fix minified files and hide_from_bots option
  • Fix types

v2.8.1 (06/22/2022)

  • Typescript Support
  • Fix issue with nextjs

v2.8.0 (01/16/2022)

  • Clear unused cookies onFirstAction
  • data-cc attribute now supports: accept-all, accept-necessary and accept-selection values
  • Added new mode option: opt-in/opt-out
  • Added .updateLanguage(<lang>) method
  • Allow .getConfig() to retrieve all config. properties
  • Allow .updateLanguage(<lang>, <force>) to forcefully refresh current modals
  • Minor code refactoring
  • Bugfixes

v2.7.2 (12/23/2021)

  • Fixed cookie_necessary_only_expiration option

v2.7.1 (12/12/2021)

  • Pass cookie data also to onFirstAction callback
  • Fix .getUserPreferences() not working if consent is already given
  • Fix wrong background-color on old browsers that don’t support css variables

v2.7.0 (12/07/2021)

  • Added .updateScripts() method to manage dynamically added scripts
  • Added .getConfig() method to read configuration values
  • Added language autodetection strategy based on <html lang>
  • Added swap_buttons inside gui_options to invert button’s order
  • Added onFirstAction and getUserPreferences() for logging/analytics purposes
  • Added cookie_necessary_only_expiration option
  • Always allow the middle position inside gui_options
  • bugfixes:

v2.6.2 (11/14/2021)

  • Fix eslint warnings/errors
  • Fix a ui bug which caused uneven margins when gui_options was omitted
  • Apply hide_from_bots also to WebDriver

v2.6.1 (10/09/2021)

  • breaking change: if use_rfc_cookie is enabled, encode cookie value using encodeUriComponent instead of btoa (base64)
  • fix accessibility issue

v2.6.0 (10/07/2021)

  • added .set() API
  • added .get() API
  • added option to vertically align the consent modal using the middle keyword
  • added use_rfc_cookie option (encodes the cookie value in base64 format)
  • added hide_from_bots option
  • enable force_consent only if consent modal is visible
  • fix: cookies not getting deleted if remove_cookie_tables option is enabled
  • minor tweaks and code refactoring

v2.5.1 (09/15/2021)

  • fix: revision option not working properly
  • fix: eraseCookies() function not working on localhost

v2.5.0 (08/29/2021)

  • added .accept() method
  • added .eraseCookies() method
  • added support for revisions (when cookieconsent terms change => re-prompt users to accept)
  • use better system fonts
  • minor ui tweaks

v2.4.7 (06/18/2021)

  • minor css bugfix (fixed table headers which sometimes covered table cells)
  • added option to specify custom domain for each cookie inside cookie_table

v2.4.6 (06/02/2021)

  • improved autoclear_cookies function
  • fixed minor ui bug which caused links inside cookie tables to be unclickable

v2.4.5 (05/28/2021)

  • allow html use inside table cells for more flexibility
  • fix firefox bug with cloneNode() on script tags
  • added option to set custom cookie name

v2.4.4 (05/27/2021)

  • fix occasional transition skip
  • manage unhandled error caused by a very specific config. object
  • minor code/css refactoring

v2.4 (05/26/2021)

  • added some basic options for layout and position via gui_options
  • better support for existing <script> tags which can now easily be managed through the cookieconsent
  • added new cookie settings: cookie_path, cookie_same_site
  • added new option to hide the html cookie tables
  • minor css refactoring && IE bugfixes

v2.3 (04/30/2021)

  • support WAI-ARIA
  • added css variables for an easier management of color schemes
  • added possibility to append the generated html to any element (default :=> document.body)
  • improved accessibility via css generated icons

v2.2 (03/23/2021)

  • fixed cookie (cc_cookie) not being set with https enabled on localhost
  • fixed minor bug on IE where .innerHTML throws an exception

v2.1 (03/06/2021)

  • added forced consent (block page navigation until consent is given)
  • autoload_css now uses ajax to ensure the css is properly loaded
  • minor code refactoring and optimizations

02/20/2021

  • minor css refactoring
  • catch css load error without local server

11/26/2020

  • darkmode button minor bugfix

11/14/2020

  • darkmode read-more button hover fix

11/09/2020

  • minor code refactoring

11/08/2020

  • fix minor bugs & replace innerText with innerHTML

11/07/2020

  • minor bugfix, increased z-index to 1000000

v1.2 (11/05/2020)

  • add support for custom expiration date with cc_cookie_expiration
  • add support for auto-removal of unused cookies based on cookiepolicy preferences with cc_autoclear_cookies
  • can now autolad css or not with cc_autoload_css
  • fix minor (bug/incoherence): cookiepolicy did not remember/retrieve saved preferences and always displayed default values

10/24/2020

  • add custom table headers

10/02/2020

  • fix minor ui bugs on ie8

09/29/2020

  • fix minor css bug

09/20/2020

  • remove unused code

09/19/2020

  • improve cookie-policy ui

09/15/2020

  • bug fixed for IE 8/9.

09/08/2020

  • now you can bind any buttons to open the cookie policy

09/08/2020

  • cookie-policy-ui update

09/07/2020

  • fix minor glitch on small screen devices

09/06/2020

  • minor changes

09/04/2020

  • fix double saved cookies

09/01/2020

  • fix minor glitch

You Might Be Interested In:


3 thoughts on “Stylish Multilingual GDPR & Cookie Consent Popup In Vanilla JavaScript

  1. Koky

    Hi! I really like this snippet, but I’m newbie and I have a simple question, which file I need to edit to change the text of popup? Thank you so much.

    Reply
  2. Francisco Tazón Vega

    Hi!
    Thank you for your code, great job!

    Can it be done that the first screen, the one that starts with ‘I use cookies….’ is modal, so I can comply with a Spanish resolution that requires that the request is also modal?

    Thanks in advance

    Reply

Leave a Reply