Overview
A fixed bottom banner by default, with an optional compact desktop card and a programmatic entry point for re-opening
Cookies
This website uses cookies to ensure ease of use and provide an enhanced browsing experience. By continuing to browse this site, you acknowledge and accept the use of cookies.
<div class="nds-cookie-popup nds-card" id="ndsCookiesPopup" hidden>
<div class="nds-card-header">
<span class="nds-featured-icon nds-circle">
<i class="nds-icon nds-hgi-cookie" aria-hidden="true"></i>
</span>
<button id="ndsCookiesCloseBtn" class="nds-close nds-btn nds-subtle" aria-label="Close">
<i class="nds-icon nds-hgi-cancel-01" aria-hidden="true"></i>
</button>
</div>
<div class="nds-card-content">
<div class="nds-card-text">
<h3 class="nds-card-title" id="ndsCookiesTitle">Cookies</h3>
<p class="nds-card-description" id="ndsCookiesContent">This website uses cookies to ensure ease of use and provide an enhanced browsing experience. By continuing to browse this site, you acknowledge and accept the use of cookies.</p>
</div>
<div class="nds-cookie-popup-links">
<a href="/terms-and-conditions" id="ndsCookiesTermsLink">Terms & Conditions</a>
<span>|</span>
<a href="/privacy-policy" id="ndsCookiesPrivacyLink">Privacy Policy</a>
</div>
</div>
<div class="nds-card-actions">
<button class="nds-btn nds-primary nds-full" id="ndsCookiesAcceptBtn"
data-accept-title="Accepted" data-accept-message="Cookies have been accepted">
<span class="nds-label">Accept</span>
</button>
<button class="nds-btn nds-secondary nds-full" id="ndsCookiesDeclineBtn"
data-decline-title="Declined" data-decline-message="Optional cookies have been declined">
<span class="nds-label">Decline</span>
</button>
</div>
</div>
Built-in Features
Opens two seconds after first load when no consent is stored. Re-visits skip the banner until you clear the saved preference.
Saves the choice for 365 days with SameSite=Lax, and falls back to localStorage when the site runs from a file:// URL.
On decline, clears _ga, _gid, _gat, _fbp, _fbc cookies and sets the Google Analytics ga-disable flag for every configured tracking ID.
Emits gtag('consent', 'update', ...) with granted or denied values on every decision, so downstream Google tags react immediately without a page reload.
Adding nds-compact re-centers the banner as a capped-width card on tablet and up, staying full-width on mobile.
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-compactfor 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-conditionsand/privacy-policy; override_includes/cookie-popup.htmlif 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 adata-ga-tracking-idattribute so Decline can set thega-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
| Class | Description |
|---|---|
nds-card | Required. The popup composes on Cards for background, padding, radius, and typography. Keep it on the root element |
nds-compact | Re-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
| Attribute | Description |
|---|---|
data-accept-title | Set on #ndsCookiesAcceptBtn to override the toast title shown after Accept. Falls back to a language-aware default (EN: "Accepted", AR: "تم القبول") |
data-accept-message | Set on #ndsCookiesAcceptBtn to override the toast description after Accept |
data-decline-title | Set on #ndsCookiesDeclineBtn to override the toast title shown after Decline |
data-decline-message | Set on #ndsCookiesDeclineBtn to override the toast description after Decline |
data-ga-tracking-id | Set 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.
| ID | Required on |
|---|---|
#ndsCookiesPopup | Root .nds-cookie-popup container. Target of NDS.Cookies.show() and the hidden attribute toggle |
#ndsCookiesAcceptBtn | Primary Accept button. Also the selector the loader watches to know when to initialize |
#ndsCookiesDeclineBtn | Secondary Decline button |
#ndsCookiesCloseBtn | Close (×) 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();