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);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the responsibility ofd the parent module; we will not merging this.

});
}

/** @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
98 changes: 90 additions & 8 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 () {
const callBackSpy = sinon.spy();
const mockGamObject = mockGAM();
const customParamName = 'custom_gam_param';
let mockGamObject = mockGAM();
let customParamName = 'custom_gam_param';

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

const submoduleCallback = intentIqIdSubmodule.getId(defaultConfigParams).callback;
submoduleCallback(callBackSpy);
intentIqIdSubmodule.getId(defaultConfigParams)
mockGamObject.cmd.forEach(cb => cb());
const targetingKeys = mockGamObject.pubads().getTargetingKeys();
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 () {
const callBackSpy = sinon.spy();
const 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));

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