API Docs for: 2.18.0
Show:

File: src/consent.js

export default function Consent(mpInstance) {
    var self = this;
    var CCPAPurpose = 'data_sale_opt_out';

    // this function is called when consent is required to determine if a cookie sync should happen, or a forwarder should be initialized
    this.isEnabledForUserConsent = function(consentRules, user) {
        if (
            !consentRules ||
            !consentRules.values ||
            !consentRules.values.length
        ) {
            return true;
        }
        if (!user) {
            return false;
        }

        var purposeHashes = {},
            consentState = user.getConsentState(),
            purposeHash;
        if (consentState) {
            // the server hashes consent purposes in the following way:
            // GDPR - '1' + purpose name
            // CCPA - '2data_sale_opt_out' (there is only 1 purpose of data_sale_opt_out for CCPA)
            var GDPRConsentHashPrefix = '1';
            var CCPAPurpose = 'data_sale_opt_out';
            var CCPAHashString = '2' + CCPAPurpose;

            var gdprConsentState = consentState.getGDPRConsentState();
            if (gdprConsentState) {
                for (var purpose in gdprConsentState) {
                    if (gdprConsentState.hasOwnProperty(purpose)) {
                        purposeHash = mpInstance._Helpers
                            .generateHash(GDPRConsentHashPrefix + purpose)
                            .toString();
                        purposeHashes[purposeHash] =
                            gdprConsentState[purpose].Consented;
                    }
                }
            }
            var CCPAConsentState = consentState.getCCPAConsentState();
            if (CCPAConsentState) {
                purposeHash = mpInstance._Helpers
                    .generateHash(CCPAHashString)
                    .toString();
                purposeHashes[purposeHash] = CCPAConsentState.Consented;
            }
        }
        var isMatch = consentRules.values.some(function(consentRule) {
            var consentPurposeHash = consentRule.consentPurpose;
            var hasConsented = consentRule.hasConsented;
            if (purposeHashes.hasOwnProperty(consentPurposeHash)) {
                return purposeHashes[consentPurposeHash] === hasConsented;
            }
        });

        return consentRules.includeOnMatch === isMatch;
    };

    this.createPrivacyConsent = function(
        consented,
        timestamp,
        consentDocument,
        location,
        hardwareId
    ) {
        if (typeof consented !== 'boolean') {
            mpInstance.Logger.error(
                'Consented boolean is required when constructing a Consent object.'
            );
            return null;
        }
        if (timestamp && isNaN(timestamp)) {
            mpInstance.Logger.error(
                'Timestamp must be a valid number when constructing a Consent object.'
            );
            return null;
        }
        if (consentDocument && typeof consentDocument !== 'string') {
            mpInstance.Logger.error(
                'Document must be a valid string when constructing a Consent object.'
            );
            return null;
        }
        if (location && typeof location !== 'string') {
            mpInstance.Logger.error(
                'Location must be a valid string when constructing a Consent object.'
            );
            return null;
        }
        if (hardwareId && typeof hardwareId !== 'string') {
            mpInstance.Logger.error(
                'Hardware ID must be a valid string when constructing a Consent object.'
            );
            return null;
        }
        return {
            Consented: consented,
            Timestamp: timestamp || Date.now(),
            ConsentDocument: consentDocument,
            Location: location,
            HardwareId: hardwareId,
        };
    };

    this.ConsentSerialization = {
        toMinifiedJsonObject: function(state) {
            var jsonObject = {};
            if (state) {
                var gdprConsentState = state.getGDPRConsentState();
                if (gdprConsentState) {
                    jsonObject.gdpr = {};
                    for (var purpose in gdprConsentState) {
                        if (gdprConsentState.hasOwnProperty(purpose)) {
                            var gdprConsent = gdprConsentState[purpose];
                            jsonObject.gdpr[purpose] = {};
                            if (typeof gdprConsent.Consented === 'boolean') {
                                jsonObject.gdpr[purpose].c =
                                    gdprConsent.Consented;
                            }
                            if (typeof gdprConsent.Timestamp === 'number') {
                                jsonObject.gdpr[purpose].ts =
                                    gdprConsent.Timestamp;
                            }
                            if (
                                typeof gdprConsent.ConsentDocument === 'string'
                            ) {
                                jsonObject.gdpr[purpose].d =
                                    gdprConsent.ConsentDocument;
                            }
                            if (typeof gdprConsent.Location === 'string') {
                                jsonObject.gdpr[purpose].l =
                                    gdprConsent.Location;
                            }
                            if (typeof gdprConsent.HardwareId === 'string') {
                                jsonObject.gdpr[purpose].h =
                                    gdprConsent.HardwareId;
                            }
                        }
                    }
                }

                var ccpaConsentState = state.getCCPAConsentState();
                if (ccpaConsentState) {
                    jsonObject.ccpa = {};
                    jsonObject.ccpa[CCPAPurpose] = {};

                    if (typeof ccpaConsentState.Consented === 'boolean') {
                        jsonObject.ccpa[CCPAPurpose].c =
                            ccpaConsentState.Consented;
                    }
                    if (typeof ccpaConsentState.Timestamp === 'number') {
                        jsonObject.ccpa[CCPAPurpose].ts =
                            ccpaConsentState.Timestamp;
                    }
                    if (typeof ccpaConsentState.ConsentDocument === 'string') {
                        jsonObject.ccpa[CCPAPurpose].d =
                            ccpaConsentState.ConsentDocument;
                    }
                    if (typeof ccpaConsentState.Location === 'string') {
                        jsonObject.ccpa[CCPAPurpose].l =
                            ccpaConsentState.Location;
                    }
                    if (typeof ccpaConsentState.HardwareId === 'string') {
                        jsonObject.ccpa[CCPAPurpose].h =
                            ccpaConsentState.HardwareId;
                    }
                }
            }
            return jsonObject;
        },

        fromMinifiedJsonObject: function(json) {
            var state = self.createConsentState();
            if (json.gdpr) {
                for (var purpose in json.gdpr) {
                    if (json.gdpr.hasOwnProperty(purpose)) {
                        var gdprConsent = self.createPrivacyConsent(
                            json.gdpr[purpose].c,
                            json.gdpr[purpose].ts,
                            json.gdpr[purpose].d,
                            json.gdpr[purpose].l,
                            json.gdpr[purpose].h
                        );
                        state.addGDPRConsentState(purpose, gdprConsent);
                    }
                }
            }

            if (json.ccpa) {
                if (json.ccpa.hasOwnProperty(CCPAPurpose)) {
                    var ccpaConsent = self.createPrivacyConsent(
                        json.ccpa[CCPAPurpose].c,
                        json.ccpa[CCPAPurpose].ts,
                        json.ccpa[CCPAPurpose].d,
                        json.ccpa[CCPAPurpose].l,
                        json.ccpa[CCPAPurpose].h
                    );
                    state.setCCPAConsentState(ccpaConsent);
                }
            }
            return state;
        },
    };

    this.createConsentState = function(consentState) {
        var gdpr = {};
        var ccpa = {};

        if (consentState) {
            setGDPRConsentState(consentState.getGDPRConsentState());
            setCCPAConsentState(consentState.getCCPAConsentState());
        }

        function canonicalizeForDeduplication(purpose) {
            if (typeof purpose !== 'string') {
                return null;
            }
            var trimmedPurpose = purpose.trim();
            if (!trimmedPurpose.length) {
                return null;
            }
            return trimmedPurpose.toLowerCase();
        }

        /**
         * Invoke these methods on a consent state object.
         * <p>
         * Usage: var consent = mParticle.Consent.createConsentState()
         * <br>
         * consent.setGDPRCoonsentState()
         *
         * @class Consent
         */

        /**
         * Add a GDPR Consent State to the consent state object
         *
         * @method addGDPRConsentState
         * @param purpose [String] Data processing purpose that describes the type of processing done on the data subject’s data
         * @param gdprConsent [Object] A GDPR consent object created via mParticle.Consent.createGDPRConsent(...)
         */

        function addGDPRConsentState(purpose, gdprConsent) {
            var normalizedPurpose = canonicalizeForDeduplication(purpose);
            if (!normalizedPurpose) {
                mpInstance.Logger.error('Purpose must be a string.');
                return this;
            }
            if (!mpInstance._Helpers.isObject(gdprConsent)) {
                mpInstance.Logger.error(
                    'Invoked with a bad or empty consent object.'
                );
                return this;
            }
            var gdprConsentCopy = self.createPrivacyConsent(
                gdprConsent.Consented,
                gdprConsent.Timestamp,
                gdprConsent.ConsentDocument,
                gdprConsent.Location,
                gdprConsent.HardwareId
            );
            if (gdprConsentCopy) {
                gdpr[normalizedPurpose] = gdprConsentCopy;
            }
            return this;
        }

        function setGDPRConsentState(gdprConsentState) {
            if (!gdprConsentState) {
                gdpr = {};
            } else if (mpInstance._Helpers.isObject(gdprConsentState)) {
                gdpr = {};
                for (var purpose in gdprConsentState) {
                    if (gdprConsentState.hasOwnProperty(purpose)) {
                        addGDPRConsentState(purpose, gdprConsentState[purpose]);
                    }
                }
            }
            return this;
        }

        /**
         * Remove a GDPR Consent State to the consent state object
         *
         * @method removeGDPRConsentState
         * @param purpose [String] Data processing purpose that describes the type of processing done on the data subject’s data
         */

        function removeGDPRConsentState(purpose) {
            var normalizedPurpose = canonicalizeForDeduplication(purpose);
            if (!normalizedPurpose) {
                return this;
            }
            delete gdpr[normalizedPurpose];
            return this;
        }

        /**
         * Gets the GDPR Consent State
         *
         * @method getGDPRConsentState
         * @return {Object} A GDPR Consent State
         */

        function getGDPRConsentState() {
            return mpInstance._Helpers.extend({}, gdpr);
        }

        /**
         * Sets a CCPA Consent state (has a single purpose of 'data_sale_opt_out')
         *
         * @method setCCPAConsentState
         * @param {Object} ccpaConsent CCPA Consent State
         */
        function setCCPAConsentState(ccpaConsent) {
            if (!mpInstance._Helpers.isObject(ccpaConsent)) {
                mpInstance.Logger.error(
                    'Invoked with a bad or empty CCPA consent object.'
                );
                return this;
            }
            var ccpaConsentCopy = self.createPrivacyConsent(
                ccpaConsent.Consented,
                ccpaConsent.Timestamp,
                ccpaConsent.ConsentDocument,
                ccpaConsent.Location,
                ccpaConsent.HardwareId
            );
            if (ccpaConsentCopy) {
                ccpa[CCPAPurpose] = ccpaConsentCopy;
            }
            return this;
        }

        /**
         * Gets the CCPA Consent State
         *
         * @method getCCPAConsentStatensent
         * @return {Object} A CCPA Consent State
         */
        function getCCPAConsentState() {
            return ccpa[CCPAPurpose];
        }

        /**
         * Removes CCPA from the consent state object
         *
         * @method removeCCPAConsentState
         */
        function removeCCPAConsentState() {
            delete ccpa[CCPAPurpose];
            return this;
        }

        function removeCCPAState() {
            mpInstance.Logger.warning(
                'removeCCPAState is deprecated and will be removed in a future release; use removeCCPAConsentState instead'
            );
            return removeCCPAConsentState();
        }

        return {
            setGDPRConsentState: setGDPRConsentState,
            addGDPRConsentState: addGDPRConsentState,
            setCCPAConsentState: setCCPAConsentState,
            getCCPAConsentState: getCCPAConsentState,
            getGDPRConsentState: getGDPRConsentState,
            removeGDPRConsentState: removeGDPRConsentState,
            removeCCPAState: removeCCPAState,
            removeCCPAConsentState: removeCCPAConsentState,
        };
    };
}