From a53964661668c8e2dd45a93a78c69128ab3da86f Mon Sep 17 00:00:00 2001 From: congdu-kun <126609480+congdu-kun@users.noreply.github.com> Date: Wed, 19 Apr 2023 11:40:10 -0700 Subject: [PATCH] pairId userId submodule: initial commit for pairId submodule (#9662) * add userId submodule for pairId system * [PairIdSystem] add logic to fetch from liveramp cookie * Fix liveramp local storage/cookie key for PairId * addressed PR review comments --- modules/pairIdSystem.js | 78 ++++++++++++++++++++++++++ modules/userId/eids.js | 6 ++ test/spec/modules/pairIdSystem_spec.js | 68 ++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 modules/pairIdSystem.js create mode 100644 test/spec/modules/pairIdSystem_spec.js diff --git a/modules/pairIdSystem.js b/modules/pairIdSystem.js new file mode 100644 index 00000000000..1f39169d52b --- /dev/null +++ b/modules/pairIdSystem.js @@ -0,0 +1,78 @@ +/** + * This module adds PAIR Id to the User ID module + * The {@link module:modules/userId} module is required + * @module modules/pairIdSystem + * @requires module:modules/userId + */ + +import { submodule } from '../src/hook.js'; +import {getStorageManager} from '../src/storageManager.js' +import { logError } from '../src/utils.js'; + +const MODULE_NAME = 'pairId'; +const PAIR_ID_KEY = 'pairId'; +const DEFAULT_LIVERAMP_PAIR_ID_KEY = '_lr_pairId'; + +export const storage = getStorageManager() + +function pairIdFromLocalStorage(key) { + return storage.localStorageIsEnabled ? storage.getDataFromLocalStorage(key) : null; +} + +function pairIdFromCookie(key) { + return storage.cookiesAreEnabled ? storage.getCookie(key) : null; +} + +/** @type {Submodule} */ +export const pairIdSubmodule = { + /** + * used to link submodule with config + * @type {string} + */ + name: MODULE_NAME, + /** + * decode the stored id value for passing to bid requests + * @function + * @param { string | undefined } value + * @returns {{pairId:string} | undefined } + */ + decode(value) { + return value && Array.isArray(value) ? {'pairId': value} : undefined + }, + /** + * performs action to obtain id and return a value in the callback's response argument + * @function + * @returns {id: string | undefined } + */ + getId(config) { + const pairIdsString = pairIdFromLocalStorage(PAIR_ID_KEY) || pairIdFromCookie(PAIR_ID_KEY) + let ids = [] + if (pairIdsString && typeof pairIdsString == 'string') { + try { + ids = ids.concat(JSON.parse(atob(pairIdsString))) + } catch (error) { + logError(error) + } + } + + const configParams = (config && config.params) || {}; + if (configParams && configParams.liveramp) { + let LRStorageLocation = configParams.liveramp.storageKey || DEFAULT_LIVERAMP_PAIR_ID_KEY + const liverampValue = pairIdFromLocalStorage(LRStorageLocation) || pairIdFromCookie(LRStorageLocation) + try { + const obj = JSON.parse(atob(liverampValue)); + ids = ids.concat(obj.envelope); + } catch (error) { + logError(error) + } + } + + if (ids.length == 0) { + logError('PairId not found.') + return undefined; + } + return {'id': ids}; + } +}; + +submodule('userId', pairIdSubmodule); diff --git a/modules/userId/eids.js b/modules/userId/eids.js index 2f2d1ca7514..fa8e6f7647c 100644 --- a/modules/userId/eids.js +++ b/modules/userId/eids.js @@ -45,6 +45,12 @@ export const USER_IDS_CONFIG = { atype: 1 }, + // pairId + 'pairId': { + source: 'google.com', + atype: 571187 + }, + // justId 'justId': { source: 'justtag.com', diff --git a/test/spec/modules/pairIdSystem_spec.js b/test/spec/modules/pairIdSystem_spec.js new file mode 100644 index 00000000000..4f75666affe --- /dev/null +++ b/test/spec/modules/pairIdSystem_spec.js @@ -0,0 +1,68 @@ +import { storage, pairIdSubmodule } from 'modules/pairIdSystem.js'; +import * as utils from 'src/utils.js'; + +describe('pairId', function () { + let sandbox; + let logErrorStub; + + beforeEach(() => { + sandbox = sinon.sandbox.create(); + logErrorStub = sandbox.stub(utils, 'logError'); + }); + afterEach(() => { + sandbox.restore(); + }); + + it('should log an error if no ID is found when getId', function() { + pairIdSubmodule.getId({ params: {} }); + expect(logErrorStub.calledOnce).to.be.true; + }); + + it('should read pairId from local storage if exists', function() { + let pairIds = ['test-pair-id1', 'test-pair-id2', 'test-pair-id3']; + sandbox.stub(storage, 'getDataFromLocalStorage').withArgs('pairId').returns(btoa(JSON.stringify(pairIds))); + + let id = pairIdSubmodule.getId({ params: {} }); + expect(id).to.be.deep.equal({id: pairIds}); + }); + + it('should read pairId from cookie if exists', function() { + let pairIds = ['test-pair-id4', 'test-pair-id5', 'test-pair-id6']; + sandbox.stub(storage, 'getCookie').withArgs('pairId').returns(btoa(JSON.stringify(pairIds))); + + let id = pairIdSubmodule.getId({ params: {} }); + expect(id).to.be.deep.equal({id: pairIds}); + }); + + it('should read pairId from default liveramp envelope local storage key if configured', function() { + let pairIds = ['test-pair-id1', 'test-pair-id2', 'test-pair-id3']; + sandbox.stub(storage, 'getDataFromLocalStorage').withArgs('_lr_pairId').returns(btoa(JSON.stringify({'envelope': pairIds}))); + let id = pairIdSubmodule.getId({ + params: { + liveramp: {} + }}) + expect(id).to.be.deep.equal({id: pairIds}) + }) + + it('should read pairId from default liveramp envelope cookie entry if configured', function() { + let pairIds = ['test-pair-id4', 'test-pair-id5', 'test-pair-id6']; + sandbox.stub(storage, 'getDataFromLocalStorage').withArgs('_lr_pairId').returns(btoa(JSON.stringify({'envelope': pairIds}))); + let id = pairIdSubmodule.getId({ + params: { + liveramp: {} + }}) + expect(id).to.be.deep.equal({id: pairIds}) + }) + + it('should read pairId from specified liveramp envelope cookie entry if configured with storageKey', function() { + let pairIds = ['test-pair-id7', 'test-pair-id8', 'test-pair-id9']; + sandbox.stub(storage, 'getDataFromLocalStorage').withArgs('lr_pairId_custom').returns(btoa(JSON.stringify({'envelope': pairIds}))); + let id = pairIdSubmodule.getId({ + params: { + liveramp: { + storageKey: 'lr_pairId_custom' + } + }}) + expect(id).to.be.deep.equal({id: pairIds}) + }) +});