Skip to content

Commit

Permalink
Merge pull request #18 from Lotame/feature/GRUE-1114_pub_configuration
Browse files Browse the repository at this point in the history
Lotame ID Module: honor publisher-supplied storage configuration
  • Loading branch information
Tonsil authored Nov 1, 2024
2 parents 073e935 + 17d9669 commit 77f8346
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 58 deletions.
115 changes: 62 additions & 53 deletions modules/lotamePanoramaIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@ import {
isBoolean,
buildUrl,
isEmpty,
isArray,
isEmptyStr
isArray
} from '../src/utils.js';
import { ajax } from '../src/ajax.js';
import { submodule } from '../src/hook.js';
import {getStorageManager} from '../src/storageManager.js';
import { uspDataHandler } from '../src/adapterManager.js';
import {MODULE_TYPE_UID} from '../src/activities/modules.js';

/**
Expand All @@ -38,16 +36,24 @@ const MISSING_CORE_CONSENT = 111;
const GVLID = 95;
const ID_HOST = 'id.crwdcntrl.net';
const ID_HOST_COOKIELESS = 'c.ltmsphrcl.net';
const DO_NOT_HONOR_CONFIG = false;

export const storage = getStorageManager({moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME});
let cookieDomain;
let appliedConfig = {
name: 'lotamePanoramaId',
storage: {
type: 'cookie&html5',
name: 'panoramaId'
}
};

/**
* Set the Lotame First Party Profile ID in the first party namespace
* @param {String} profileId
*/
function setProfileId(profileId) {
if (storage.cookiesAreEnabled()) {
if (cookiesAreEnabled()) {
let expirationDate = new Date(timestamp() + NINE_MONTHS_MS).toUTCString();
storage.setCookie(
KEY_PROFILE,
Expand All @@ -58,7 +64,7 @@ function setProfileId(profileId) {
undefined
);
}
if (storage.hasLocalStorage()) {
if (localStorageIsEnabled()) {
storage.setDataInLocalStorage(KEY_PROFILE, profileId, undefined);
}
}
Expand All @@ -68,10 +74,10 @@ function setProfileId(profileId) {
*/
function getProfileId() {
let profileId;
if (storage.cookiesAreEnabled()) {
if (cookiesAreEnabled(DO_NOT_HONOR_CONFIG)) {
profileId = storage.getCookie(KEY_PROFILE, undefined);
}
if (!profileId && storage.hasLocalStorage()) {
if (!profileId && localStorageIsEnabled(DO_NOT_HONOR_CONFIG)) {
profileId = storage.getDataFromLocalStorage(KEY_PROFILE, undefined);
}
return profileId;
Expand All @@ -83,21 +89,11 @@ function getProfileId() {
*/
function getFromStorage(key) {
let value = null;
if (storage.cookiesAreEnabled()) {
if (cookiesAreEnabled(DO_NOT_HONOR_CONFIG)) {
value = storage.getCookie(key, undefined);
}
if (storage.hasLocalStorage() && value === null) {
const storedValueExp = storage.getDataFromLocalStorage(
`${key}_exp`, undefined
);

if (storedValueExp === '' || storedValueExp === null) {
value = storage.getDataFromLocalStorage(key, undefined);
} else if (storedValueExp) {
if ((new Date(parseInt(storedValueExp, 10))).getTime() - Date.now() > 0) {
value = storage.getDataFromLocalStorage(key, undefined);
}
}
if (value === null && localStorageIsEnabled(DO_NOT_HONOR_CONFIG)) {
value = storage.getDataFromLocalStorage(key, undefined);
}
return value;
}
Expand All @@ -115,7 +111,7 @@ function saveLotameCache(
) {
if (key && value) {
let expirationDate = new Date(expirationTimestamp).toUTCString();
if (storage.cookiesAreEnabled()) {
if (cookiesAreEnabled()) {
storage.setCookie(
key,
value,
Expand All @@ -125,12 +121,7 @@ function saveLotameCache(
undefined
);
}
if (storage.hasLocalStorage()) {
storage.setDataInLocalStorage(
`${key}_exp`,
String(expirationTimestamp),
undefined
);
if (localStorageIsEnabled()) {
storage.setDataInLocalStorage(key, value, undefined);
}
}
Expand Down Expand Up @@ -172,7 +163,7 @@ function getLotameLocalCache(clientId = undefined) {
*/
function clearLotameCache(key) {
if (key) {
if (storage.cookiesAreEnabled()) {
if (cookiesAreEnabled(DO_NOT_HONOR_CONFIG)) {
let expirationDate = new Date(0).toUTCString();
storage.setCookie(
key,
Expand All @@ -183,11 +174,50 @@ function clearLotameCache(key) {
undefined
);
}
if (storage.hasLocalStorage()) {
if (localStorageIsEnabled(DO_NOT_HONOR_CONFIG)) {
storage.removeDataFromLocalStorage(key, undefined);
}
}
}
/**
* @param {boolean} honorConfig - false to override for reading or deleting old cookies
* @returns {boolean} for whether we can write the cookie
*/
function cookiesAreEnabled(honorConfig = true) {
if (honorConfig) {
return storage.cookiesAreEnabled() && appliedConfig.storage.type.includes('cookie');
}
return storage.cookiesAreEnabled();
}
/**
* @param {boolean} honorConfig - false to override for reading or deleting old stored items
* @returns {boolean} for whether we can write the cookie
*/
function localStorageIsEnabled(honorConfig = true) {
if (honorConfig) {
return storage.hasLocalStorage() && appliedConfig.storage.type.includes('html5');
}
return storage.hasLocalStorage();
}
/**
* @param {SubmoduleConfig} config
* @returns {null|string} - string error if it finds one, null otherwise.
*/
function checkConfigHasErrorsAndReport(config) {
let error = null;
if (typeof config.storage !== 'undefined') {
Object.assign(appliedConfig.storage, appliedConfig.storage, config.storage);
const READABLE_MODULE_NAME = 'Lotame ID module';
const PERMITTED_STORAGE_TYPES = ['cookie', 'html5', 'cookie&html5'];
if (typeof config.storage.name !== 'undefined' && config.storage.name !== KEY_ID) {
logError(`Misconfigured ${READABLE_MODULE_NAME}, "storage.name" is expected to be "${KEY_ID}", actual is "${config.storage.name}"`);
error = true;
} else if (config.storage.type !== 'undefined' && !PERMITTED_STORAGE_TYPES.includes(config.storage.type)) {
logError(`Misconfigured ${READABLE_MODULE_NAME}, "storage.type" is expected to be one of "${PERMITTED_STORAGE_TYPES.join(', ')}", actual is "${config.storage.type}"`);
}
}
return error;
}
/** @type {Submodule} */
export const lotamePanoramaIdSubmodule = {
/**
Expand Down Expand Up @@ -222,6 +252,9 @@ export const lotamePanoramaIdSubmodule = {
* @returns {IdResponse|undefined}
*/
getId(config, consentData, cacheIdObj) {
if (checkConfigHasErrorsAndReport(config)) {
return;
}
cookieDomain = lotamePanoramaIdSubmodule.findRootDomain();
const configParams = (config && config.params) || {};
const clientId = configParams.clientId;
Expand Down Expand Up @@ -249,18 +282,6 @@ export const lotamePanoramaIdSubmodule = {

const storedUserId = getProfileId();

// Add CCPA Consent data handling
const usp = uspDataHandler.getConsentData();

let usPrivacy;
if (typeof usp !== 'undefined' && !isEmpty(usp) && !isEmptyStr(usp)) {
usPrivacy = usp;
}
if (!usPrivacy) {
// fallback to 1st party cookie
usPrivacy = getFromStorage('us_privacy');
}

const getRequestHost = function() {
if (navigator.userAgent && navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
return ID_HOST_COOKIELESS;
Expand All @@ -281,22 +302,10 @@ export const lotamePanoramaIdSubmodule = {
}
consentString = consentData.consentString;
}
// If no consent string, try to read it from 1st party cookies
if (!consentString) {
consentString = getFromStorage('eupubconsent-v2');
}
if (!consentString) {
consentString = getFromStorage('euconsent-v2');
}
if (consentString) {
queryParams.gdpr_consent = consentString;
}

// Add usPrivacy to the url
if (usPrivacy) {
queryParams.us_privacy = usPrivacy;
}

// Add clientId to the url
if (hasCustomClientId) {
queryParams.c = clientId;
Expand Down
5 changes: 0 additions & 5 deletions test/spec/modules/lotamePanoramaIdSystem_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
lotamePanoramaIdSubmodule,
storage,
} from 'modules/lotamePanoramaIdSystem.js';
import { uspDataHandler } from 'src/adapterManager.js';
import * as utils from 'src/utils.js';
import { server } from 'test/mocks/xhr.js';
import sinon from 'sinon';
Expand All @@ -19,7 +18,6 @@ describe('LotameId', function() {
let setLocalStorageStub;
let removeFromLocalStorageStub;
let timeStampStub;
let uspConsentDataStub;
let requestHost;

const nowTimestamp = new Date().getTime();
Expand All @@ -34,7 +32,6 @@ describe('LotameId', function() {
'removeDataFromLocalStorage'
);
timeStampStub = sinon.stub(utils, 'timestamp').returns(nowTimestamp);
uspConsentDataStub = sinon.stub(uspDataHandler, 'getConsentData');
if (navigator.userAgent && navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
requestHost = 'https://c.ltmsphrcl.net/id';
} else {
Expand All @@ -50,7 +47,6 @@ describe('LotameId', function() {
setLocalStorageStub.restore();
removeFromLocalStorageStub.restore();
timeStampStub.restore();
uspConsentDataStub.restore();
});

describe('caching initial data received from the remote server', function () {
Expand Down Expand Up @@ -809,7 +805,6 @@ describe('LotameId', function() {
let callBackSpy = sinon.spy();

beforeEach(function () {
uspConsentDataStub.returns('1NNN');
let submoduleCallback = lotamePanoramaIdSubmodule.getId(
{
params: {
Expand Down

0 comments on commit 77f8346

Please sign in to comment.