Skip to content
Closed
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
2 changes: 1 addition & 1 deletion libraries/intentIqConstants/intentIqConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const BLACK_LIST = 'L';
export const CLIENT_HINTS_KEY = '_iiq_ch';
export const EMPTY = 'EMPTY';
export const GVLID = '1323';
export const VERSION = 0.29;
export const VERSION = 0.30;
export const PREBID = 'pbjs';
export const HOURS_24 = 86400000;

Expand Down
16 changes: 16 additions & 0 deletions modules/intentIqIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,20 @@ function storeCounters(storage, partnerData) {
storeData(PARTNER_DATA_KEY, JSON.stringify(partnerData), storage, firstPartyData);
}

export function setPPID(gamObjectReference, shouldSetPPID, eids) {
if (!shouldSetPPID || !isPlainObject(gamObjectReference) || !Array.isArray(eids)) return;

const intentIqEid = eids.find(eid => eid.source === 'intentiq.com');
if (!intentIqEid?.uids?.length) return;

const ppuid = intentIqEid.uids.find(uid => uid.ext?.stype === 'ppuid')?.id;
if (!ppuid) return;

gamObjectReference.cmd?.push(() => {
gamObjectReference.pubads().setPublisherProvidedId(ppuid);
});
}

/** @type {Submodule} */
export const intentIqIdSubmodule = {
/**
Expand Down Expand Up @@ -444,6 +458,7 @@ export const intentIqIdSubmodule = {
if (partnerData.data.length) { // encrypted data
decryptedData = tryParse(decryptData(partnerData.data));
runtimeEids = decryptedData;
setPPID(gamObjectReference, configParams.shouldSetPPID, runtimeEids.eids);
}
}

Expand Down Expand Up @@ -611,6 +626,7 @@ export const intentIqIdSubmodule = {

if (respJson.data?.eids) {
runtimeEids = respJson.data
setPPID(gamObjectReference, configParams.shouldSetPPID, runtimeEids.eids);
callback(respJson.data.eids);
firePartnerCallback()
const encryptedData = encryptData(JSON.stringify(respJson.data))
Expand Down
2 changes: 2 additions & 0 deletions modules/intentIqIdSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Please find below list of parameters that could be used in configuring Intent IQ
| params.additionalParameters [0].parameterName | Required | String | Name of the custom parameter. This will be sent as a query parameter. | `"abc"` |
| params.additionalParameters [0].parameterValue | Required | String / Number | Value to assign to the parameter. | `123` |
| params.additionalParameters [0].destination | Required | Array | Array of numbers either `1` or `0`. Controls where this parameter is sent `[sendWithSync, sendWithVr, winreport]`. | `[1, 0, 0]` |
| params.shouldSetPPID | Optional | Boolean | Enables the Intent IQ ID to be sent to Google Ad Manager as a Publisher Provided ID (PPID). Requires `gamObjectReference` to be provided in the configuration. | `true` |

### Configuration example

Expand All @@ -81,6 +82,7 @@ pbjs.setConfig({
sourceMetaData: "123.123.123.123", // Optional parameter
sourceMetaDataExternal: 123456, // Optional parameter
reportMethod: "GET", // Optional parameter
shouldSetPPID: true, // Optional parameter
additionalParameters: [ // Optional parameter
{
parameterName: "abc",
Expand Down
92 changes: 87 additions & 5 deletions test/spec/modules/intentIqIdSystem_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export const testClientHints = {
const testAPILink = 'https://new-test-api.intentiq.com'
const syncTestAPILink = 'https://new-test-sync.intentiq.com'

const mockGAM = () => {
const mockGAM = (ppidSpy = sinon.spy()) => {
const targetingObject = {};
return {
cmd: [],
Expand All @@ -71,7 +71,8 @@ const mockGAM = () => {
},
getTargetingKeys: () => {
return Object.keys(targetingObject);
}
},
setPublisherProvidedId: ppidSpy
})
};
};
Expand Down Expand Up @@ -302,21 +303,101 @@ describe('IntentIQ tests', function () {
});

it('should use the provided gamParameterName from configParams', function () {
let callBackSpy = sinon.spy();
let mockGamObject = mockGAM();
let customParamName = 'custom_gam_param';

defaultConfigParams.params.gamObjectReference = mockGamObject;
defaultConfigParams.params.gamParameterName = customParamName;

let submoduleCallback = intentIqIdSubmodule.getId(defaultConfigParams).callback;
submoduleCallback(callBackSpy);
intentIqIdSubmodule.getId(defaultConfigParams)
mockGamObject.cmd.forEach(cb => cb());
let targetingKeys = mockGamObject.pubads().getTargetingKeys();

expect(targetingKeys).to.include(customParamName);
});

it('should call setPublisherProvidedId if shouldSetPPID=true', function () {
const ppidSpy = sinon.spy();
const gam = mockGAM(ppidSpy);

defaultConfigParams.params.gamObjectReference = gam;
defaultConfigParams.params.shouldSetPPID = true;

intentIqIdSubmodule.getId(defaultConfigParams).callback(() => {});

const request = server.requests[0];
request.respond(200, responseHeader, JSON.stringify({
data: {
eids: [
{
source: 'intentiq.com',
uids: [
{
id: 'test_id',
ext: { stype: 'ppuid' }
}
]
}
]
}
})
);

gam.cmd.forEach(cb => cb());

expect(request.url).to.contain('at=39');
expect(ppidSpy.calledOnce).to.be.true;
expect(ppidSpy.firstCall.args[0]).to.equal('test_id');
});

it('should call setPublisherProvidedId if shouldSetPPID=true and ids are present in LS', function () {
const ppidSpy = sinon.spy();
const gam = mockGAM(ppidSpy);

defaultConfigParams.params.gamObjectReference = gam;
defaultConfigParams.params.shouldSetPPID = true;

localStorage.setItem('_iiq_fdata_' + partner, JSON.stringify(testLSValueWithData));

intentIqIdSubmodule.getId(defaultConfigParams);
gam.cmd.forEach(fn => typeof fn === 'function' && fn());

const expectedEid = JSON.parse(decryptData(testLSValueWithData.data)).eids[0].uids[0].id;
expect(ppidSpy.calledOnce).to.be.true;
expect(ppidSpy.firstCall.args[0]).to.equal(expectedEid);
});

it('should NOT call setPublisherProvidedId if shouldSetPPID=false', function () {
const ppidSpy = sinon.spy();
const gam = {
cmd: [],
pubads: () => ({
setTargeting: sinon.spy(),
setPublisherProvidedId: ppidSpy
})
};
defaultConfigParams.params.gamObjectReference = gam;
defaultConfigParams.params.shouldSetPPID = false;
intentIqIdSubmodule.getId(defaultConfigParams).callback(() => {});

const request = server.requests[0];
request.respond(200, responseHeader, JSON.stringify({
data: {
eids: [{
source: 'intentiq.com',
uids: [{
id: 'test_id',
ext: { stype: 'ppuid' }
}]
}]
}
}));

gam.cmd.forEach(cb => cb());
expect(request.url).to.contain('at=39');
expect(ppidSpy.called).to.be.false;
});

it('should not throw Uncaught TypeError when IntentIQ endpoint returns empty response', function () {
let callBackSpy = sinon.spy();
let submoduleCallback = intentIqIdSubmodule.getId(defaultConfigParams).callback;
Expand Down Expand Up @@ -395,6 +476,7 @@ describe('IntentIQ tests', function () {

it('return data stored in local storage ', function () {
localStorage.setItem('_iiq_fdata_' + partner, JSON.stringify(testLSValueWithData));

let returnedValue = intentIqIdSubmodule.getId(allConfigParams);
expect(returnedValue.id).to.deep.equal(JSON.parse(decryptData(testLSValueWithData.data)).eids);
});
Expand Down
Loading