diff --git a/modules/intentIqIdSystem.js b/modules/intentIqIdSystem.js index d60ab3962ae..1347fa04bd5 100644 --- a/modules/intentIqIdSystem.js +++ b/modules/intentIqIdSystem.js @@ -6,16 +6,17 @@ */ import { logError, logInfo } from '../src/utils.js'; -import {ajax} from '../src/ajax.js'; -import {submodule} from '../src/hook.js' -import {getStorageManager} from '../src/storageManager.js'; +import { ajax } from '../src/ajax.js'; +import { submodule } from '../src/hook.js' +import { getStorageManager } from '../src/storageManager.js'; const PCID_EXPIRY = 365; const MODULE_NAME = 'intentIqId'; export const FIRST_PARTY_KEY = '_iiq_fdata'; +export var FIRST_PARTY_DATA_KEY = '_iiq_fdata'; -export const storage = getStorageManager({gvlid: undefined, moduleName: MODULE_NAME}); +export const storage = getStorageManager({ gvlid: undefined, moduleName: MODULE_NAME }); const INVALID_ID = 'INVALID_ID'; @@ -117,6 +118,8 @@ export const intentIqIdSubmodule = { logError('User ID - intentIqId submodule requires a valid partner to be defined'); return; } + if (!FIRST_PARTY_DATA_KEY.includes(configParams.partner)) { FIRST_PARTY_DATA_KEY += '_' + configParams.partner } + let rrttStrtTime = 0; // Read Intent IQ 1st party id or generate it if none exists let firstPartyData = tryParse(readData(FIRST_PARTY_KEY)); @@ -126,12 +129,17 @@ export const intentIqIdSubmodule = { storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData)); } + let partnerData = tryParse(readData(FIRST_PARTY_DATA_KEY)); + if (!partnerData) partnerData = {}; + // use protocol relative urls for http or https let url = `https://api.intentiq.com/profiles_engine/ProfilesEngineServlet?at=39&mi=10&dpi=${configParams.partner}&pt=17&dpn=1`; url += configParams.pcid ? '&pcid=' + encodeURIComponent(configParams.pcid) : ''; url += configParams.pai ? '&pai=' + encodeURIComponent(configParams.pai) : ''; url += firstPartyData.pcid ? '&iiqidtype=2&iiqpcid=' + encodeURIComponent(firstPartyData.pcid) : ''; url += firstPartyData.pid ? '&pid=' + encodeURIComponent(firstPartyData.pid) : ''; + url += (partnerData.cttl) ? '&cttl=' + encodeURIComponent(partnerData.cttl) : ''; + url += (partnerData.rrtt) ? '&rrtt=' + encodeURIComponent(partnerData.rrtt) : ''; const resp = function (callback) { const callbacks = { @@ -140,14 +148,30 @@ export const intentIqIdSubmodule = { // If response is a valid json and should save is true if (respJson && respJson.ls) { // Store pid field if found in response json + let shouldUpdateLs = false; if ('pid' in respJson) { firstPartyData.pid = respJson.pid; - storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData)); + shouldUpdateLs = true; + } + if ('cttl' in respJson) { + partnerData.cttl = respJson.cttl; + shouldUpdateLs = true; } - // If should save and data is empty, means we should save as INVALID_ID if (respJson.data == '') { respJson.data = INVALID_ID; + } else { + partnerData.data = respJson.data; + shouldUpdateLs = true; + } + if (rrttStrtTime && rrttStrtTime > 0) { + partnerData.rrtt = Date.now() - rrttStrtTime; + shouldUpdateLs = true; + } + if (shouldUpdateLs === true) { + partnerData.date = Date.now() + storeData(FIRST_PARTY_KEY, JSON.stringify(firstPartyData)); + storeData(FIRST_PARTY_DATA_KEY, JSON.stringify(partnerData)); } callback(respJson.data); } else { @@ -159,9 +183,13 @@ export const intentIqIdSubmodule = { callback(); } }; - ajax(url, callbacks, undefined, {method: 'GET', withCredentials: true}); + if (partnerData.date && partnerData.cttl && partnerData.data && + Date.now() - partnerData.date < partnerData.cttl) { callback(partnerData.data); } else { + rrttStrtTime = Date.now(); + ajax(url, callbacks, undefined, { method: 'GET', withCredentials: true }); + } }; - return {callback: resp}; + return { callback: resp }; } }; diff --git a/test/spec/modules/intentIqIdSystem_spec.js b/test/spec/modules/intentIqIdSystem_spec.js index 8ea30a6ba92..f9bfa577e3a 100644 --- a/test/spec/modules/intentIqIdSystem_spec.js +++ b/test/spec/modules/intentIqIdSystem_spec.js @@ -1,19 +1,40 @@ import { expect } from 'chai'; -import {intentIqIdSubmodule, readData, FIRST_PARTY_KEY} from 'modules/intentIqIdSystem.js'; +import { intentIqIdSubmodule, readData, FIRST_PARTY_KEY } from 'modules/intentIqIdSystem.js'; import * as utils from 'src/utils.js'; -import {server} from 'test/mocks/xhr.js'; +import { server } from 'test/mocks/xhr.js'; const partner = 10; const pai = '11'; const pcid = '12'; -const defaultConfigParams = { params: {partner: partner} }; -const paiConfigParams = { params: {partner: partner, pai: pai} }; -const pcidConfigParams = { params: {partner: partner, pcid: pcid} }; -const allConfigParams = { params: {partner: partner, pai: pai, pcid: pcid} }; -const responseHeader = {'Content-Type': 'application/json'} +const defaultConfigParams = { params: { partner: partner } }; +const paiConfigParams = { params: { partner: partner, pai: pai } }; +const pcidConfigParams = { params: { partner: partner, pcid: pcid } }; +const allConfigParams = { params: { partner: partner, pai: pai, pcid: pcid } }; +const responseHeader = { 'Content-Type': 'application/json' } describe('IntentIQ tests', function () { let logErrorStub; + let testLSValue = { + 'date': 1651945280759, + 'cttl': 2000, + 'rrtt': 123 + } + let testLSValueWithData = { + 'date': 1651945280759, + 'cttl': 9999999999999, + 'rrtt': 123, + 'data': 'previousTestData' + } + let testResponseWithValues = { + 'abPercentage': 90, + 'adt': 1, + 'ct': 2, + 'data': 'testdata', + 'dbsaved': 'false', + 'ls': true, + 'mde': true, + 'tc': 4 + } beforeEach(function () { logErrorStub = sinon.stub(utils, 'logError'); @@ -36,7 +57,7 @@ describe('IntentIQ tests', function () { }); it('should log an error if partner configParam was not a numeric value', function () { - let submodule = intentIqIdSubmodule.getId({ params: {partner: '10'} }); + let submodule = intentIqIdSubmodule.getId({ params: { partner: '10' } }); expect(logErrorStub.calledOnce).to.be.true; expect(submodule).to.be.undefined; }); @@ -143,7 +164,7 @@ describe('IntentIQ tests', function () { request.respond( 200, responseHeader, - JSON.stringify({pid: 'test_pid', data: 'test_personid', ls: true}) + JSON.stringify({ pid: 'test_pid', data: 'test_personid', ls: true }) ); expect(callBackSpy.calledOnce).to.be.true; expect(callBackSpy.args[0][0]).to.be.eq('test_personid'); @@ -158,7 +179,7 @@ describe('IntentIQ tests', function () { request.respond( 200, responseHeader, - JSON.stringify({pid: 'test_pid', data: 'test_personid', ls: false}) + JSON.stringify({ pid: 'test_pid', data: 'test_personid', ls: false }) ); expect(callBackSpy.calledOnce).to.be.true; expect(callBackSpy.args[0][0]).to.be.undefined; @@ -173,9 +194,38 @@ describe('IntentIQ tests', function () { request.respond( 200, responseHeader, - JSON.stringify({pid: 'test_pid', data: '', ls: true}) + JSON.stringify({ pid: 'test_pid', data: '', ls: true }) ); expect(callBackSpy.calledOnce).to.be.true; expect(callBackSpy.args[0][0]).to.be.eq('INVALID_ID'); }); + + it('send addition parameters if were found in localstorage', function () { + localStorage.setItem('_iiq_fdata_' + partner, JSON.stringify(testLSValue)) + let callBackSpy = sinon.spy(); + let submoduleCallback = intentIqIdSubmodule.getId(allConfigParams).callback; + submoduleCallback(callBackSpy); + let request = server.requests[0]; + + expect(request.url).to.contain('https://api.intentiq.com/profiles_engine/ProfilesEngineServlet?at=39&mi=10&dpi=10&pt=17&dpn=1&pcid=12&pai=11&iiqidtype=2&iiqpcid='); + expect(request.url).to.contain('cttl=' + testLSValue.cttl); + expect(request.url).to.contain('rrtt=' + testLSValue.rrtt); + request.respond( + 200, + responseHeader, + JSON.stringify(testResponseWithValues) + ); + expect(callBackSpy.calledOnce).to.be.true; + expect(callBackSpy.args[0][0]).to.be.eq(testResponseWithValues.data); + }); + + it('return data stored in local storage ', function () { + localStorage.setItem('_iiq_fdata_' + partner, JSON.stringify(testLSValueWithData)) + let callBackSpy = sinon.spy(); + let submoduleCallback = intentIqIdSubmodule.getId(allConfigParams).callback; + submoduleCallback(callBackSpy); + expect(server.requests.length).to.be.equal(0); + expect(callBackSpy.calledOnce).to.be.true; + expect(callBackSpy.args[0][0]).to.be.equal(testLSValueWithData.data); + }); });