DeveloperHow to Guides

How to Build a Cookie Consent Popup in Salesforce Using Apex & Lightning Web Components

With global privacy regulations like GDPR and ePrivacy Directive, businesses must seek user consent before storing cookies—especially for marketing and analytics purposes.
While Salesforce Experience Cloud provides great flexibility, it doesn’t come with a built-in cookie consent manager for your portals.

In this guide, we’ll create a Cookie Consent Popup that:

  • Appears only on first login (or until the user saves their preferences).
  • Lets users toggle cookie categories (Preferences, Marketing, Statistics).
  • Saves choices both in Salesforce and in the browser.

Solution Overview

The consent popup will be powered by:

  • Apex Controllers – Handle database checks and updates.
  • Parent LWC – Checks if the popup is needed and manages modal visibility.
  • Child LWC – Displays consent toggles and saves preferences.
  • Custom User Fields – Store the consent status.

Apex Classes

CookieConsentLoginController

Purpose: This Apex class controls the first-login behavior. It checks whether the popup should appear and saves preferences along with a timestamp.

Key Methods:

@AuraEnabled(cacheable=true)

public static Boolean needsConsentPopup()

  • Checks if the current user’s Cookies_Save_Preference_Time__c is null.
  • If null, this means the user hasn’t saved preferences yet → popup should show.

@AuraEnabled

public static void updateConsentAndTime(Boolean preferences, Boolean marketing, Boolean statistics)

  • Updates cookie preference fields (Cookie_Preferences__c, Marketing_Allowed__c, Statistics_Allowed__c)
  • Also sets the timestamp field to current time.
  • Prevents popup from appearing again in future logins.

CookieConsentLoginController

Checks if popup is needed and updates preferences with a timestamp.

				
					public with sharing class CookieConsentLoginController {

    
    @AuraEnabled(cacheable=true)

    public static Boolean needsConsentPopup() {

        User u = [

            SELECT Cookies_Save_Preference_Time__c

            FROM User

            WHERE Id = :UserInfo.getUserId()

        ];

        return u.Cookies_Save_Preference_Time__c == null;

    }

 @AuraEnabled

    public static void updateConsentAndTime(Boolean preferences, Boolean marketing, Boolean statistics) {

        User u = [

            SELECT Id, Cookie_Preferences__c, Marketing_Allowed__c, Statistics_Allowed__c, Cookies_Save_Preference_Time__c

            FROM User

            WHERE Id = :UserInfo.getUserId()

        ];

        

        u.Cookie_Preferences__c = preferences;

        u.Marketing_Allowed__c = marketing;

        u.Statistics_Allowed__c = statistics;

        u.Cookies_Save_Preference_Time__c = System.now();

        update u;

    }

}
				
			

CookieConsentController

Purpose: Allows updating cookie preferences without modifying the timestamp. This is useful when the user is editing preferences later from a settings page.

Key Method:

@AuraEnabled

public static void updateConsent(Boolean preferences, Boolean marketing, Boolean statistics)

  • Updates cookie preferences in the database.
  • Does not update the Cookies_Save_Preference_Time__c, ensuring the original consent timestamp remains intact.
  • Updates preferences without modifying the timestamp (useful for settings page edits).
				
					public with sharing class CookieConsentController {

    @AuraEnabled

    public static void updateConsent(Boolean preferences, Boolean marketing, Boolean statistics) {

        User u = [

            SELECT Id, Cookie_Preferences__c, Marketing_Allowed__c, Statistics_Allowed__c

            FROM User

            WHERE Id = :UserInfo.getUserId()

        ];

        

        u.Cookie_Preferences__c = preferences;

        u.Marketing_Allowed__c = marketing;

        u.Statistics_Allowed__c = statistics;

 

        update u;

    }

}


				
			

Lightning Web Components

Parent LWC – cookieMain

Purpose: Controls whether the cookie consent popup should appear by calling Apex. Also hosts the child component in a modal dialog.

What It Does:

  • Calls needsConsentPopup() in connectedCallback() to determine if the popup should appear.
  • If the Apex method returns true, it shows the modal containing the child LWC.
  • Includes a “Cookie Preferences” link to manually open the popup again.
  • Listens for a closechild event from the child component to close the modal.

Acts as the controller and modal wrapper.

Responsible for checking if the popup should be shown and for rendering the child component.

HTML

				
					<template>

    <template if:true={initialized}>

        <div class=”centered-link”>

            <a href=”javascript:void(0);” onclick={handleClick}>Cookie Preferences</a>

        </div>

 

        <template if:true={showChild}>

            <section role=”dialog” tabindex=”-1″ class=”slds-modal slds-fade-in-open”>

                <div class=”slds-modal__container”>

                    <header class=”slds-modal__header”>

                        <h2 class=”slds-text-heading_medium”>Cookie Preferences</h2>

                    </header>

                    <div class=”slds-modal__content slds-p-around_medium” style=”overflow:visible;”>

                        <c-cookies-for-portal onclosechild={handleClose}></c-cookies-for-portal>

                    </div>

                </div>

            </section>

            <div class=”slds-backdrop slds-backdrop_open”></div>

        </template>

    </template>

</template>
				
			

JS

				
					import { LightningElement, track } from ‘lwc’;

import needsConsentPopup from ‘@salesforce/apex/CookieConsentLoginController.needsConsentPopup’;

 

export default class CookiePreferencesParent extends LightningElement {

    @track initialized = false;

    @track showChild = false;

 

    connectedCallback() {

        needsConsentPopup()

            .then(result => {

                this.showChild = result;

            })

            .catch(error => {

                console.error(‘Error checking consent popup:’, error);

            })

            .finally(() => {

                this.initialized = true;

            });

    }

 

    handleClick() {

        this.showChild = true;

    }

 

    handleClose() {

        this.showChild = false;

    }

}


				
			

CSS

				
					.centered-link {

    text-align: center;

    margin-top: 20px;

}

 

.slds-modal__container {

    max-width: 40rem;

    width: 100%;

}
				
			

Child LWC – cookiesForPortal

Purpose: Displays the actual cookie settings UI and handles saving the user’s preferences to both the Salesforce backend and the browser.

What It Does:

  • Displays toggle switches for Preferences, Marketing, and Statistics cookies.
  • Updates internal consent object when toggles change.
  • On clicking “Save Preferences”:
    • Saves consent to the browser via setCookieConsent().
    • Calls updateConsentAndTime() Apex method to save in Salesforce.
    • Displays success/error message using ShowToastEvent.
    • Fires a closechild event to tell the parent to close the modal.

Handles all user interaction and data saving logic.

Handles displaying and saving the cookie consent options.

HTML

				
					<template>

    <lightning-card title=”Cookie Consent Settings” icon-name=”utility:info”>

        <div class=”slds-m-around_medium”>

            <p>We use cookies to personalize content and ads. Please adjust your preferences below:</p>

 

            <lightning-input type=”toggle” label=”Preferences” checked={checkedPreferences}

                onchange={changeTogglePreferences}></lightning-input>

 

            <lightning-input type=”toggle” label=”Marketing” checked={checkedMarketing}

                onchange={changeToggleMarketing}></lightning-input>

 

            <lightning-input type=”toggle” label=”Statistics” checked={checkedStatistics}

                onchange={changeToggleStatistics}></lightning-input>

 

            <div class=”cookie-link” style=”margin-top: 1rem;”>

                <p>

                    Check our cookie preferences 

                    <a href=”Your company cookie site” 

                        target=”_blank” rel=”noopener noreferrer”>here</a>.

                </p>

            </div>

 

            <div style=”margin-top: 1.5rem;”>

                <lightning-button variant=”brand” label=”Save Preferences”

                    onclick={handleClickSetConsent}></lightning-button>

            </div>

        </div>

    </lightning-card>

</template>
				
			

JS

				
					import { LightningElement, track } from ‘lwc’;

import { setCookieConsent, isCategoryAllowedForCurrentConsent } from ‘lightning/userConsentCookie’;

import { ShowToastEvent } from ‘lightning/platformShowToastEvent’;

import updateConsentAndTime from ‘@salesforce/apex/CookieConsentLoginController.updateConsentAndTime’;

export default class CookieConsentToggle extends LightningElement {

    @track checkedPreferences = isCategoryAllowedForCurrentConsent(“Preferences”);

    @track checkedMarketing = isCategoryAllowedForCurrentConsent(“Marketing”);

    @track checkedStatistics = isCategoryAllowedForCurrentConsent(“Statistics”);

    consent = {

        Preferences: this.checkedPreferences,

        Marketing: this.checkedMarketing,

        Statistics: this.checkedStatistics

    };

    changeTogglePreferences(event) {

        this.checkedPreferences = event.target.checked;

        this.consent.Preferences = this.checkedPreferences;

    }

    changeToggleMarketing(event) {

        this.checkedMarketing = event.target.checked;

        this.consent.Marketing = this.checkedMarketing;

    }

    changeToggleStatistics(event) {

        this.checkedStatistics = event.target.checked;

        this.consent.Statistics = this.checkedStatistics;

    }

    handleClickSetConsent() {

        setCookieConsent(this.consent);

 

        updateConsentAndTime({

            preferences: this.checkedPreferences,

            marketing: this.checkedMarketing,

            statistics: this.checkedStatistics

        })

        .then(() => {

            this.dispatchEvent(

                new ShowToastEvent({

                    title: ‘Preferences Saved’,

                    message: ‘Your cookie settings have been updated.’,

                    variant: ‘success’

                })

            );

            this.dispatchEvent(new CustomEvent(‘closechild’));

        })

        .catch(error => {

            this.dispatchEvent(

                new ShowToastEvent({

                    title: ‘Error’,

                    message: error.body.message,

                    variant: ‘error’

                })

            );

        });

    }

}


				
			

CSS

				
					.custom-container {

    color: black;

}
				
			

Key Points

  • The decision point for showing the popup is:
  • return u.Cookies_Save_Preference_Time__c == null;
  • Preferences are stored in two places: Salesforce (server-side) and browser consent cookie (client-side).
  • Users can reopen the popup anytime via the “Cookie Preferences” link.
  • Future logins skip the popup unless the timestamp is cleared.

Conclusion

This approach delivers a compliant and user-friendly cookie consent manager within Salesforce.
It’s flexible enough to:

  • Integrate with Experience Cloud sites.
  • Allow users to change preferences anytime.
  • Store consent history securely.
Shares:

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *