diff --git a/modules/1plusXRtdProvider.js b/modules/1plusXRtdProvider.js index c5c4594ff22..88891b14a78 100644 --- a/modules/1plusXRtdProvider.js +++ b/modules/1plusXRtdProvider.js @@ -1,5 +1,7 @@ import { submodule } from '../src/hook.js'; +import { MODULE_TYPE_RTD } from '../src/activities/modules.js'; import { ajax } from '../src/ajax.js'; +import { getStorageManager, STORAGE_TYPE_COOKIES, STORAGE_TYPE_LOCALSTORAGE } from '../src/storageManager.js'; import { logMessage, logError, deepAccess, deepSetValue, mergeDeep, @@ -13,6 +15,9 @@ const ORTB2_NAME = '1plusX.com' const PAPI_VERSION = 'v1.0'; const LOG_PREFIX = '[1plusX RTD Module]: '; const OPE_FPID = 'ope_fpid' + +export const fpidStorage = getStorageManager({ moduleType: MODULE_TYPE_RTD, moduleName: MODULE_NAME }); + export const segtaxes = { // cf. https://github.com/InteractiveAdvertisingBureau/openrtb/pull/108 AUDIENCE: 526, @@ -53,7 +58,19 @@ export const extractConfig = (moduleConfig, reqBidsConfigObj) => { throw new Error('No bidRequestConfig bidder found in moduleConfig bidders'); } - return { customerId, timeout, bidders }; + const fpidStorageType = deepAccess(moduleConfig, 'params.fpidStorageType', + STORAGE_TYPE_LOCALSTORAGE) + + if ( + fpidStorageType !== STORAGE_TYPE_COOKIES && + fpidStorageType !== STORAGE_TYPE_LOCALSTORAGE + ) { + throw new Error( + `fpidStorageType must be ${STORAGE_TYPE_LOCALSTORAGE} or ${STORAGE_TYPE_COOKIES}` + ) + } + + return { customerId, timeout, bidders, fpidStorageType }; } /** @@ -81,16 +98,20 @@ export const extractConsent = ({ gdpr }) => { } /** - * Extracts the OPE first party id field from local storage + * Extracts the OPE first party id field + * @param {string} fpidStorageType indicates where fpid should be read from * @returns fpid string if found, else null */ -export const extractFpid = () => { +export const extractFpid = (fpidStorageType) => { try { - const fpid = window.localStorage.getItem(OPE_FPID); - if (fpid) { - return fpid; + switch (fpidStorageType) { + case STORAGE_TYPE_COOKIES: return fpidStorage.getCookie(OPE_FPID) + case STORAGE_TYPE_LOCALSTORAGE: return fpidStorage.getDataFromLocalStorage(OPE_FPID) + default: { + logError(`Got unknown fpidStorageType ${fpidStorageType}. Aborting...`) + return null + } } - return null; } catch (error) { return null; } @@ -231,10 +252,10 @@ const init = (config, userConsent) => { const getBidRequestData = (reqBidsConfigObj, callback, moduleConfig, userConsent) => { try { // Get the required config - const { customerId, bidders } = extractConfig(moduleConfig, reqBidsConfigObj); + const { customerId, bidders, fpidStorageType } = extractConfig(moduleConfig, reqBidsConfigObj); const { ortb2Fragments: { bidder: biddersOrtb2 } } = reqBidsConfigObj; // Get PAPI URL - const papiUrl = getPapiUrl(customerId, extractConsent(userConsent) || {}, extractFpid()) + const papiUrl = getPapiUrl(customerId, extractConsent(userConsent) || {}, extractFpid(fpidStorageType)) // Call PAPI getTargetingDataFromPapi(papiUrl) .then((papiResponse) => { diff --git a/modules/1plusXRtdProvider.md b/modules/1plusXRtdProvider.md index 6a6211b37cc..c1e5a6f48a4 100644 --- a/modules/1plusXRtdProvider.md +++ b/modules/1plusXRtdProvider.md @@ -45,15 +45,16 @@ pbjs.setConfig({ ### Parameters -| Name | Type | Description | Default | -| :---------------- | :------------ | :--------------------------------------------------------------- |:----------------- | -| name | String | Real time data module name | Always '1plusX' | -| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` | -| params | Object | | | -| params.customerId | String | Your 1plusX customer id | | -| params.bidders | Array | List of bidders for which you would like data to be set | | -| params.timeout | Integer | timeout (ms) | 1000ms | - +| Name | Type | Description | Default | +| :------------------------ | :------------ | :--------------------------------------------------------------- |:----------------- | +| name | String | Real time data module name | Always '1plusX' | +| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (optional) | `false` | +| params | Object | | | +| params.customerId | String | Your 1plusX customer id | | +| params.bidders | Array | List of bidders for which you would like data to be set | | +| params.timeout | Integer | timeout (ms) | 1000ms | +| params.fpidStorageType | String | Specifies where the 1plusX fpid should be read from. Either | html5 | +| | | "html5" (local storage) or "cookie" (first party cookie) | | ## Testing To view an example of how the 1plusX RTD module works : diff --git a/test/spec/modules/1plusXRtdProvider_spec.js b/test/spec/modules/1plusXRtdProvider_spec.js index 4e4092ea26e..1059f43fb4d 100644 --- a/test/spec/modules/1plusXRtdProvider_spec.js +++ b/test/spec/modules/1plusXRtdProvider_spec.js @@ -12,6 +12,7 @@ import { updateBidderConfig, } from 'modules/1plusXRtdProvider'; import {deepClone} from '../../../src/utils.js'; +import { STORAGE_TYPE_COOKIES, STORAGE_TYPE_LOCALSTORAGE } from 'src/storageManager.js'; describe('1plusXRtdProvider', () => { // Fake server config @@ -126,6 +127,7 @@ describe('1plusXRtdProvider', () => { const customerId = 'test'; const timeout = 1000; const bidders = ['appnexus']; + const fpidStorageType = STORAGE_TYPE_LOCALSTORAGE it('Throws an error if no customerId is specified', () => { const moduleConfig = { params: { timeout, bidders } }; @@ -141,13 +143,14 @@ describe('1plusXRtdProvider', () => { expect(() => extractConfig(moduleConfig, reqBidsConfigEmpty)).to.throw(); }) it('Returns an object containing the parameters specified', () => { - const moduleConfig = { params: { customerId, timeout, bidders } }; - const expectedKeys = ['customerId', 'timeout', 'bidders'] + const moduleConfig = { params: { customerId, timeout, bidders, fpidStorageType } }; + const expectedKeys = ['customerId', 'timeout', 'bidders', 'fpidStorageType'] const extractedConfig = extractConfig(moduleConfig, reqBidsConfigObj); expect(extractedConfig).to.be.an('object').and.to.have.all.keys(expectedKeys); expect(extractedConfig.customerId).to.equal(customerId); expect(extractedConfig.timeout).to.equal(timeout); expect(extractedConfig.bidders).to.deep.equal(bidders); + expect(extractedConfig.fpidStorageType).to.equal(fpidStorageType) }) /* 1plusX RTD module may only use bidders that are both specified in : - the bid request configuration @@ -166,6 +169,20 @@ describe('1plusXRtdProvider', () => { const moduleConfig = { params: { customerId, timeout, bidders } }; expect(() => extractConfig(moduleConfig, reqBidsConfigObj)).to.throw(); }) + it('Throws an error if wrong fpidStorageType is provided', () => { + const moduleConfig = { params: { customerId, timeout, bidders, fpidStorageType: 'bogus' } }; + expect(() => extractConfig(moduleConfig, reqBidsConfigObj).to.throw()) + }) + it('Defaults fpidStorageType to localStorage', () => { + const moduleConfig = { params: { customerId, timeout, bidders } }; + const extractedConfig = extractConfig(moduleConfig, reqBidsConfigObj); + expect(extractedConfig.fpidStorageType).to.equal(STORAGE_TYPE_LOCALSTORAGE) + }) + it('Correctly instantiates fpidStorageType to cookie store if instructed', () => { + const moduleConfig = { params: { customerId, timeout, bidders, fpidStorageType: STORAGE_TYPE_COOKIES } }; + const extractedConfig = extractConfig(moduleConfig, reqBidsConfigObj); + expect(extractedConfig.fpidStorageType).to.equal(STORAGE_TYPE_COOKIES) + }) }) describe('buildOrtb2Updates', () => { @@ -284,17 +301,6 @@ describe('1plusXRtdProvider', () => { }) }) - describe('extractFpid', () => { - it('correctly extracts an ope fpid if present', () => { - window.localStorage.setItem('ope_fpid', 'oneplusx_test_key') - const id1 = extractFpid() - window.localStorage.removeItem('ope_fpid') - const id2 = extractFpid() - expect(id1).to.equal('oneplusx_test_key') - expect(id2).to.equal(null) - }) - }) - describe('getPapiUrl', () => { const customer = 'acme' const consent = {