Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intentiq module: adding dynamic ttl and rtt and storing data in localstorate #8384

Merged
merged 2 commits into from
May 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 36 additions & 8 deletions modules/intentIqIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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));
Expand All @@ -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 = {
Expand All @@ -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 {
Expand All @@ -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 };
}
};

Expand Down
72 changes: 61 additions & 11 deletions test/spec/modules/intentIqIdSystem_spec.js
Original file line number Diff line number Diff line change
@@ -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');
Expand All @@ -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;
});
Expand Down Expand Up @@ -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');
Expand All @@ -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;
Expand All @@ -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);
});
});