GDPR-Compliant Cookie Consent Banner/Modal in JavaScript

Category: Javascript , Recommended | September 2, 2025
Authortagconcierge
Last UpdateSeptember 2, 2025
LicenseMIT
Views257 views
GDPR-Compliant Cookie Consent Banner/Modal in JavaScript

cookiesBannerJs is a small JavaScript library that lets you create a GDPR-compliant cookie consent banner or modal on your website. This allows your visitors to easily grant or deny permission for different types of cookies.

The library gives you full control over how the consent banner is displayed and how user preferences are handled. Whether you opt for a modal or bar-style banner, cookiesBannerJs allows you to specify the consent types you need (e.g., ad storage, analytics, personalization, etc.).

More Features:

  • It provides JSON-based configuration for complete banner customization.
  • It triggers JavaScript callbacks when users interact with the banner and provides a simple JavaScript object with the consent state.
  • As a consent-platform-agnostic tool, it can be used across various websites without concerns over compatibility with specific cookie consent solutions.

More Examples:

How to use it:

1. Download the cookiesBannerJs package and link the required JavaScript and CSS files in your HTML document.

<link rel="stylesheet" href="styles/light.css">
<script src="src/app.js"></script>

2. Initialize the cookiesBannerJs by passing functions to load and save the consent state, along with a configuration object to customize the banner.

cookiesBannerJs(
  function loadConsentState() {
    const consentState = {}; // get it from somewhere (e.g. localStorage);
    return consentState;
  },
  function saveConsentState(consentState) {
    // do something with consentState, which is basic JS object:
    // {
    //   ad_storage: 'granted',
    //   analytics_storage: 'denied'
    // }
  },
  config
);

3. Customize the banner by defining the configuration object. You can set the display mode, consent types, and modal or bar settings based on your preferences.

// Modal 
{
  display: {
    mode: 'modal', // 'modal' or 'bar'
    wall: true // covers the page with opaque layer to prevent user interactions
  },
  consent_types: [{
    name: 'ad_storage', // internal name of consent type
    title: 'Ad Storage',
    description: 'Cookies used for advertising purposes', 
    default: 'denied', // what should be the default state when user decides to customize the settings
    require: false // if set to true it won't be possible to save consent without this granted
  }],
  modal: {
    title: 'Learn how we protect your privacy', 
    description: 'Longer description with *simple markdown support*.',
    buttons: {
      settings: 'Settings',
      close: 'Close',
      reject: 'Reject',
      accept: 'Accept all'
    }
  },
  settings: {
    title: 'Customise your preferences',
    description: 'Longer description with *simple markdown support*.',
    buttons: {
      reject: 'Reject',
      close: 'Close',
      save: 'Save',
      accept: 'Accept all'
    }
  }
}
// Bar
{
  display: {
    mode: "bar"
  },
  consent_types: [{
    name: "ad_storage",
    title: "Ads storage",
    description: "Enables storage, such as cookies, related to advertising [link](https://www.google.com)",
    default: 'denied'
  }, {
    name: 'analytics_storage',
    title: "Analytics storage",
    description: 'Enables storage, such as cookies, related to analytics (for example, visit duration)',
    default: 'denied'
  }, {
    name: 'functionality_storage',
    title: "Functionality storage",
    description: 'Enables storage that supports the functionality of the website or app such as language settings',
    default: 'denied'
  }, {
    name: 'personalization_storage',
    title: "Personalization storage",
    description: 'Enables storage related to personalization such as video recommendations',
    default: 'denied'
  }, {
    name: 'security_storage',
    title: "Security storage",
    description: 'Enables storage related to security such as authentication functionality, fraud prevention, and other user protection',
    default: 'denied'
  }],
  settings: {
    title: "Cookies Settings",
    description: "In order to provide you with best experience we use various...",
    buttons: {
      save: "Save preferences",
      close: "Close"
    }
  },
  modal: {
    title: 'Cookies',
    description: 'We are using various cookies files. Learn more in our [privacy policy](#) and make your choice.',
    buttons: {
      accept: 'Accept',
      settings: 'Settings'
    }
  }
};

4. cookiesBannerJs can integrate with Google Tag Manager to manage your marketing and analytics tags based on user consent. Here’s an example:

<script>
// Define dataLayer and the gtag function.
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
// Set default consent to 'denied' as a placeholder
// Determine actual values based on your own requirements
gtag('consent', 'default', {
  'ad_storage': 'denied',
  'ad_user_data': 'denied',
  'ad_personalization': 'denied',
  'analytics_storage': 'denied'
});
</script>
<!-- Google Tag Manager Here -->

5. Adjust the appearance of the cookie banner by overriding the default CSS styles.

.consent-banner-button {
  text-decoration: none;
  background: none;
  border: 1px solid #000;
  text-wrap: nowrap;
  white-space: nowrap;
  color: rgb(231, 78, 30);
  border-color: rgb(231, 78, 30);
  background-color: transparent;
  border-width: 2px;
  padding: 8px 27px;
  border-radius: 3px;
}
#consent-banner-main {
  position: relative;
  z-index: 2147483647;
}
#consent-banner-modal {
  background: #fff;
  padding: 25px 10px 30px !important;
  box-shadow: rgba(0, 0, 0, 0.4) 0 0 20px;
}
#consent-banner-modal .consent-banner-modal-wrapper {
  display: flex;
  margin: 0 auto;
  justify-content: center;
  padding: 0 10px;
}
#consent-banner-settings h2 {
  padding-bottom: 15px;
  border-bottom: 1px solid #ededed;
}
#consent-banner-modal .consent-banner-modal-wrapper p {
  margin-bottom: 0;
}
#consent-banner-modal .consent-banner-modal-buttons {
  margin-top: 12px;
  text-align: center;
  justify-content: center;
  display: flex;
  align-items: flex-end;
}
#consent-banner-modal .consent-banner-modal-buttons [href="#settings"] {
  margin-left: 10px;
}
#consent-banner-settings .consent-banner-settings-buttons {
  margin-top: 15px;
  text-align: center;
  display: flex;
  justify-content: space-around;
  grid-gap: 5px;
}
#consent-banner-modal .consent-banner-modal-buttons .consent-banner-button {
  margin-left: 10px;
}
#consent-banner-settings .consent-banner-settings-buttons [href="#close"] {
  margin-left: 10px;
}
#consent-banner-settings {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background: #fff;
  box-shadow: rgba(0, 0, 0, 0.4) 0 0 20px;
  padding: 20px 30px 15px;
  overflow-x: hidden;
  min-width: 500px;
  max-height: none;
}
#consent-banner-settings ul {
  list-style: none;
  padding-left: 0;
}
#consent-banner-settings ul label {
  font-weight: bold;
  font-size: 1.1em;
  margin-left: 5px;
}
#consent-banner-settings ul li {
  border-bottom: 1px solid rgba(0, 0, 0, .2);
  margin-bottom: 15px;
}
#consent-banner-settings ul p {
  margin-left: 25px;
}
.consent-banner-button:hover {
  color: rgba(231, 78, 30, .85);
  border-color: rgba(231, 78, 30, .85);
}
#consent-banner-settings .consent-banner-settings-buttons .consent-banner-button {
  flex: 1;
}
#consent-banner-main h2 {
  font-size: 18px;
  font-weight: bold;
}
#consent-banner-settings, #consent-banner-modal {
  border-radius: 6px;
}
.consent-banner-button[href="#accept"] {
  color: #ffffff;
  border-color: rgb(231, 78, 30);
  background-color: rgb(231, 78, 30);
}
.consent-banner-button[href="#accept"]:hover {
  background-color: rgb(220, 114, 80);
  border-color: rgb(220, 114, 80);
}
#consent-banner-modal .consent-banner-modal-wrapper h2 {
  display: block !important;
}
#consent-banner-settings > div > form div:nth-child(2) {
  max-height: 65vh;
  overflow-x: hidden;
}
@media (max-width:576px) {
  #consent-banner-settings > div > form div:nth-child(2) {
    max-height: none;
  }
  #consent-banner-main:not([data-mode="bar"]) #consent-banner-modal {
    width: auto;
    left: 5% !important;
    right: 5% !important;
    min-width: auto;
    transform: translate(0, -50%) !important;
  }
  #consent-banner-settings {
    width: auto;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    transform: none;
    max-height: 100%;
    min-width: auto;
  }
  #consent-banner-settings .consent-banner-settings-buttons {
    position: fixed;
    bottom: 0;
    right: 0;
    left: 0;
    background-color: #fff;
    padding-top: 16px;
    padding-bottom: 30px;
    padding-left: 50px;
    padding-right: 50px;
    text-align: center;
    display: block;
  }
  #consent-banner-settings .consent-banner-settings-buttons .button {
    width: 25%;
  }
  #consent-banner-modal .consent-banner-modal-buttons {
    margin: 0 !important;
  }
  #consent-banner-settings .consent-banner-settings-buttons .consent-banner-button {
    margin: 0;
    display: block;
    margin-bottom: 10px;
    text-align: center;
  }
  #consent-banner-settings ul {
    padding-bottom: 100px;
  }
}
@media (max-width:768px) {
  #consent-banner-modal .consent-banner-modal-wrapper p {
    margin-bottom: 10px;
  }
  #consent-banner-modal .consent-banner-modal-buttons {
    display: block;
  }
  #consent-banner-modal .consent-banner-modal-wrapper {
    display: block;
  }
  #consent-banner-modal .consent-banner-modal-buttons .consent-banner-button {
    margin: 0;
    display: block;
    margin-bottom: 10px;
    text-align: center;
  }
}

Changelog:

v2.0.0 (09/02/2025)

  • switched to native
  • removed tags to avoid heading hierarchy issues for SEO reasons
  • removed domReady wrapper, now the library needs to be loaded in the body

You Might Be Interested In:


Leave a Reply