Cookie Consent - National Design System

A privacy-compliant consent banner, built on the Cards component, that captures the user's cookie preferences, gates analytics and marketing cookies on decline, and can be re-opened from any trigger for ongoing settings control.

Overview

A fixed bottom banner by default, with an optional compact desktop card and a programmatic entry point for re-opening

Built-in Features

Auto-initialization

Opens two seconds after first load when no consent is stored. Re-visits skip the banner until you clear the saved preference.

Consent Persistence

Saves the choice for 365 days with SameSite=Lax, and falls back to localStorage when the site runs from a file:// URL.

Analytics Gating

On decline, clears _ga, _gid, _gat, _fbp, _fbc cookies and sets the Google Analytics ga-disable flag for every configured tracking ID.

gtag Consent Signals

Emits gtag('consent', 'update', ...) with granted or denied values on every decision, so downstream Google tags react immediately without a page reload.

Compact Layout

Adding nds-compact re-centers the banner as a capped-width card on tablet and up, staying full-width on mobile.

Programmatic Control

Call NDS.Cookies.show() from any trigger (footer link, settings button) to re-open the banner after a decision has been made.

Usage Guidelines

Best Practices

  • Let the component auto-open on the first visit. A 2000 ms delay keeps the banner from fighting with first-paint content, and the saved consent means return visitors never see it again unnecessarily
  • Add a persistent "Cookie Settings" link in the footer that calls NDS.Cookies.show(). Consent is a reversible decision, and users expect to find the control later without digging
  • Choose nds-compact for desktop-first products where the bottom banner would cover a fixed footer, chatbot, or data table. The compact card sits above content as a floating dialog rather than a bar
  • Keep the body text to one or two sentences. Lead with the "why", then link to the Terms and Privacy pages for the full policy. Users skim, not read, consent banners
  • Always include both Terms & Conditions and Privacy Policy links. Regulations in most jurisdictions require them to be reachable at the moment of consent, not only after. The bundled include points to /terms-and-conditions and /privacy-policy; override _includes/cookie-popup.html if your site uses different paths
  • Wire Accept as the primary button and Decline as the secondary. This matches user expectation and keeps keyboard focus order predictable
  • Register your Google Analytics property ID through window.GA_TRACKING_ID (string or array) or a data-ga-tracking-id attribute so Decline can set the ga-disable-<ID> flag. Without a registered ID, Decline still clears the cookies but GA keeps running
  • Treat the close (×) button as "decide later", not "decline". It hides the banner for the current page load without writing a consent value, so the popup re-appears on the next visit
  • Do not use this banner as a blocking gate. The page must remain readable and interactive behind it. For mandatory decisions (age gates, payment confirmations) use the Modal component with a backdrop instead
  • Do not stack multiple cookie banners on the same page. The component is already included in the site layout, so you do not need to add it to individual pages
  • Custom toast strings are used verbatim when set via the data attributes. Set both Arabic and English variants per page (or leave the attribute off to inherit the language-aware default, which keys on NDS.isArabic)

Modifier Classes

ClassDescription
nds-cardRequired. The popup composes on Cards for background, padding, radius, and typography. Keep it on the root element
nds-compactRe-centers the banner as a capped-width floating card on tablet and larger viewports. Mobile behavior is unchanged (full-width bottom bar). Do not confuse with card's nds-center, which centers card content, not the card itself

Data Attributes

AttributeDescription
data-accept-titleSet on #ndsCookiesAcceptBtn to override the toast title shown after Accept. Falls back to a language-aware default (EN: "Accepted", AR: "تم القبول")
data-accept-messageSet on #ndsCookiesAcceptBtn to override the toast description after Accept
data-decline-titleSet on #ndsCookiesDeclineBtn to override the toast title shown after Decline
data-decline-messageSet on #ndsCookiesDeclineBtn to override the toast description after Decline
data-ga-tracking-idSet on any element to register a Google Analytics tracking ID that should be disabled when the user declines. Multiple IDs are supported (one per element)

Required Element IDs

The JS wires events and updates text by ID, so renaming or removing these on your copy of the markup will break the component. If you translate the banner server-side, edit the text nodes inside these IDs but keep the IDs themselves intact.

IDRequired on
#ndsCookiesPopupRoot .nds-cookie-popup container. Target of NDS.Cookies.show() and the hidden attribute toggle
#ndsCookiesAcceptBtnPrimary Accept button. Also the selector the loader watches to know when to initialize
#ndsCookiesDeclineBtnSecondary Decline button
#ndsCookiesCloseBtnClose (×) button. Dismisses the popup without persisting a consent value

JavaScript API

The NDS.Cookies namespace exposes both the consent lifecycle and a generic cookie read/write utility. NDS.Cookies.init() is called automatically by the loader, so most integrations only need show, getConsent, and the cookie helpers. Consent is persisted in a cookie named cookieConsent for 365 days (or in localStorage under nds_cookieConsent when the site is served from file://).

// ── Re-open the banner ─────────────────────────────── // Removes the `hidden` attribute from #ndsCookiesPopup. // Works at any time, regardless of whether consent was // previously saved. Useful for a footer "Cookie Settings" // link or an in-app preferences screen. NDS.Cookies.show(); // ── Read the current consent state ─────────────────── // Returns 'accepted' | 'declined' | null (no decision yet). const state = NDS.Cookies.getConsent(); // ── Reset consent and re-prompt ────────────────────── // There is no dedicated reset method; clear the cookie // and call show() to re-ask the user. NDS.Cookies.delete('cookieConsent'); NDS.Cookies.show(); // ── Set a functional cookie ────────────────────────── // Essential cookies do not require consent. Use this for // user-preference flags, dismissed banners, etc. // Cookies are written with SameSite=Lax and path=/. NDS.Cookies.set('my-preference', 'value', 30); // name, value, days // ── Read a cookie by name ──────────────────────────── const value = NDS.Cookies.get('my-preference'); // ── Delete a cookie ────────────────────────────────── // Clears both the root-domain and host-only variants. NDS.Cookies.delete('my-preference'); // ── Register a Google Analytics property ID ────────── // Set before nds-main.min.js loads (e.g. in <head>). // String or array; Decline sets window['ga-disable-<ID>'] = true // for every registered ID and emits gtag('consent', 'update', …). window.GA_TRACKING_ID = 'G-XXXXXXXXXX'; // or window.GA_TRACKING_ID = ['G-AAA', 'G-BBB']; // ── Re-initialize after dynamic markup (rare) ──────── // Only needed if the banner markup was injected after load. // Re-binds click handlers to the four required IDs. NDS.Cookies.init();
Was this page useful?
60% of users said Yes from 2843 Feedbacks