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

Add tapad id submodule #6167

Merged
merged 2 commits into from
Jan 18, 2021
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
3 changes: 2 additions & 1 deletion modules/.submodules.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"idxIdSystem",
"fabrickIdSystem",
"verizonMediaIdSystem",
"pubProvidedIdSystem"
"pubProvidedIdSystem",
"tapadIdSystem"
],
"adpod": [
"freeWheelAdserverVideo",
Expand Down
61 changes: 61 additions & 0 deletions modules/tapadIdSystem.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { uspDataHandler } from '../src/adapterManager.js';
import { submodule } from '../src/hook.js';
import * as ajax from '../src/ajax.js'
import * as utils from '../src/utils.js';

export const graphUrl = 'https://realtime-graph-access-zxvhwknfeq-uc.a.run.app/v1/graph';

export const tapadIdSubmodule = {
name: 'tapadId',
/**
* decode the stored id value for passing to bid requests
* @function
* @returns {{tapadId: string} | undefined}
*/
decode(id) {
return { tapadId: id };
},
/*
* @function
* @summary initiate Real Time Graph
* @param {SubmoduleParams} [configParams]
* @param {ConsentData} [consentData]
* @returns {IdResponse }}
*/
getId(config) {
const uspData = uspDataHandler.getConsentData();
if (uspData && uspData !== '1---') {
return { id: undefined };
}
const configParams = config.params || {};

if (configParams.companyId == null || isNaN(Number(configParams.companyId))) {
utils.logMessage('Please provide a valid Company Id. Contact prebid@tapad.com for assistance.');
}

return {
callback: (complete) => {
ajax.ajaxBuilder(10000)(
`${graphUrl}?company_id=${configParams.companyId}&tapad_id_type=TAPAD_ID`,
smenzer marked this conversation as resolved.
Show resolved Hide resolved
{
success: (response) => {
const responseJson = JSON.parse(response);
if (responseJson.hasOwnProperty('tapadId')) {
complete(responseJson.tapadId);
}
},
error: (_, e) => {
if (e.status === 404) {
complete(undefined);
}
if (e.status === 403) {
utils.logMessage('Invalid Company Id. Contact prebid@tapad.com for assistance.');
}
}
}
);
}
}
}
}
submodule('userId', tapadIdSubmodule);
4 changes: 4 additions & 0 deletions modules/userId/eids.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ const USER_IDS_CONFIG = {
'fabrickId': {
source: 'neustar.biz',
atype: 1
},
'tapadId': {
source: 'tapad.com',
atype: 1
}
};

Expand Down
7 changes: 7 additions & 0 deletions modules/userId/eids.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ userIdAsEids = [
id: 'some-random-id-value',
atype: 1
}]
},
{
source: 'tapad.com',
uids: [{
id: 'some-random-id-value',
atype: 1
}]
}
]
```
12 changes: 12 additions & 0 deletions test/spec/modules/eids_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,18 @@ describe('eids array generation for known sub-modules', function() {
});
});

it('tapadId', function() {
const userId = {
tapadId: 'some-random-id-value'
};
const newEids = createEidsArray(userId);
expect(newEids.length).to.equal(1);
expect(newEids[0]).to.deep.equal({
source: 'tapad.com',
uids: [{id: 'some-random-id-value', atype: 1}]
});
});

it('NetId', function() {
const userId = {
netId: 'some-random-id-value'
Expand Down
65 changes: 65 additions & 0 deletions test/spec/modules/tapadIdSystem_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { tapadIdSubmodule, graphUrl } from 'modules/tapadIdSystem.js';
import * as utils from 'src/utils.js';

import { server } from 'test/mocks/xhr.js';

describe('TapadIdSystem', function () {
describe('getId', function() {
const config = { params: { companyId: 12345 } };
it('should call to real time graph endpoint and handle valid response', function() {
const callbackSpy = sinon.spy();
const callback = tapadIdSubmodule.getId(config).callback;
callback(callbackSpy);

const request = server.requests[0];
expect(request.url).to.eq(`${graphUrl}?company_id=12345&tapad_id_type=TAPAD_ID`);

request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ tapadId: 'your-tapad-id' }));
expect(callbackSpy.lastCall.lastArg).to.eq('your-tapad-id');
});

it('should remove stored tapadId if not found', function() {
const callbackSpy = sinon.spy();
const callback = tapadIdSubmodule.getId(config).callback;
callback(callbackSpy);

const request = server.requests[0];

request.respond(404);
expect(callbackSpy.lastCall.lastArg).to.be.undefined;
});

it('should log message with invalid company id', function() {
smenzer marked this conversation as resolved.
Show resolved Hide resolved
const logMessageSpy = sinon.spy(utils, 'logMessage');
const callbackSpy = sinon.spy();
const callback = tapadIdSubmodule.getId(config).callback;
callback(callbackSpy);

const request = server.requests[0];

request.respond(403);
expect(logMessageSpy.lastCall.lastArg).to.eq('Invalid Company Id. Contact prebid@tapad.com for assistance.');
logMessageSpy.restore();
});

it('should log message if company id not given', function() {
const logMessageSpy = sinon.spy(utils, 'logMessage');
const callbackSpy = sinon.spy();
const callback = tapadIdSubmodule.getId({}).callback;
callback(callbackSpy);

expect(logMessageSpy.lastCall.lastArg).to.eq('Please provide a valid Company Id. Contact prebid@tapad.com for assistance.');
logMessageSpy.restore();
});

it('should log message if company id is incorrect format', function() {
const logMessageSpy = sinon.spy(utils, 'logMessage');
const callbackSpy = sinon.spy();
const callback = tapadIdSubmodule.getId({ params: { companyId: 'notANumber' } }).callback;
callback(callbackSpy);

expect(logMessageSpy.lastCall.lastArg).to.eq('Please provide a valid Company Id. Contact prebid@tapad.com for assistance.');
logMessageSpy.restore();
});
});
})
58 changes: 44 additions & 14 deletions test/spec/modules/userId_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {sharedIdSubmodule} from 'modules/sharedIdSystem.js';
import {haloIdSubmodule} from 'modules/haloIdSystem.js';
import {pubProvidedIdSubmodule} from 'modules/pubProvidedIdSystem.js';
import {criteoIdSubmodule} from 'modules/criteoIdSystem.js';
import {tapadIdSubmodule} from 'modules/tapadIdSystem.js';

let assert = require('chai').assert;
let expect = require('chai').expect;
Expand Down Expand Up @@ -454,22 +455,22 @@ describe('User ID', function () {
});

it('handles config with no usersync object', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig({});
// usersync is undefined, and no logInfo message for 'User ID - usersync config updated'
expect(typeof utils.logInfo.args[0]).to.equal('undefined');
});

it('handles config with empty usersync object', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig({userSync: {}});
expect(typeof utils.logInfo.args[0]).to.equal('undefined');
});

it('handles config with usersync and userIds that are empty objs', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig({
userSync: {
Expand All @@ -480,7 +481,7 @@ describe('User ID', function () {
});

it('handles config with usersync and userIds with empty names or that dont match a submodule.name', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, merkleIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig({
userSync: {
Expand All @@ -497,15 +498,15 @@ describe('User ID', function () {
});

it('config with 1 configurations should create 1 submodules', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig(getConfigMock(['unifiedId', 'unifiedid', 'cookie']));

expect(utils.logInfo.args[0][0]).to.exist.and.to.contain('User ID - usersync config updated for 1 submodules');
});

it('config with 13 configurations should result in 13 submodules add', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, liveIntentIdSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
it('config with 14 configurations should result in 14 submodules add', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, liveIntentIdSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig({
userSync: {
Expand Down Expand Up @@ -545,14 +546,17 @@ describe('User ID', function () {
name: 'zeotapIdPlus'
}, {
name: 'criteo'
}, {
name: 'tapadId',
storage: {name: 'tapad_id', type: 'cookie'}
}]
}
});
expect(utils.logInfo.args[0][0]).to.exist.and.to.contain('User ID - usersync config updated for 13 submodules');
expect(utils.logInfo.args[0][0]).to.exist.and.to.contain('User ID - usersync config updated for 14 submodules');
});

it('config syncDelay updates module correctly', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig({
userSync: {
Expand All @@ -567,7 +571,7 @@ describe('User ID', function () {
});

it('config auctionDelay updates module correctly', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig({
userSync: {
Expand All @@ -582,7 +586,7 @@ describe('User ID', function () {
});

it('config auctionDelay defaults to 0 if not a number', function () {
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, pubProvidedIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig({
userSync: {
Expand Down Expand Up @@ -984,6 +988,29 @@ describe('User ID', function () {
}, {adUnits});
});

it('test hook from tapadIdModule cookie', function (done) {
coreStorage.setCookie('tapad_id', 'test-tapad-id', (new Date(Date.now() + 100000).toUTCString()));

setSubmoduleRegistry([tapadIdSubmodule]);
init(config);
config.setConfig(getConfigMock(['tapadId', 'tapad_id', 'cookie']));

requestBidsHook(function () {
adUnits.forEach(unit => {
unit.bids.forEach(bid => {
expect(bid).to.have.deep.nested.property('userId.tapadId');
expect(bid.userId.tapadId).to.equal('test-tapad-id');
expect(bid.userIdAsEids[0]).to.deep.equal({
source: 'tapad.com',
uids: [{id: 'test-tapad-id', atype: 1}]
});
});
})
coreStorage.setCookie('tapad_id', '', EXPIRED_COOKIE_DATE);
done();
}, {adUnits});
});

it('test hook from liveIntentId html5', function (done) {
// simulate existing browser local storage values
localStorage.setItem('_li_pbid', JSON.stringify({'unifiedId': 'random-ls-identifier'}));
Expand Down Expand Up @@ -1481,7 +1508,7 @@ describe('User ID', function () {
coreStorage.setCookie('haloId', JSON.stringify({'haloId': 'testHaloId'}), (new Date(Date.now() + 5000).toUTCString()));
coreStorage.setCookie('storage_criteo', JSON.stringify({'criteoId': 'test_bidid'}), (new Date(Date.now() + 5000).toUTCString()));

setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, criteoIdSubmodule]);
setSubmoduleRegistry([pubCommonIdSubmodule, unifiedIdSubmodule, id5IdSubmodule, identityLinkSubmodule, britepoolIdSubmodule, netIdSubmodule, sharedIdSubmodule, intentIqIdSubmodule, zeotapIdPlusSubmodule, haloIdSubmodule, criteoIdSubmodule, tapadIdSubmodule]);
init(config);
config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'],
['unifiedId', 'unifiedid', 'cookie'],
Expand All @@ -1493,7 +1520,8 @@ describe('User ID', function () {
['intentIqId', 'intentIqId', 'cookie'],
['zeotapIdPlus', 'IDP', 'cookie'],
['haloId', 'haloId', 'cookie'],
['criteo', 'storage_criteo', 'cookie']));
['criteo', 'storage_criteo', 'cookie'],
['tapadId', 'tapad_id', 'cookie']));

requestBidsHook(function () {
adUnits.forEach(unit => {
Expand Down Expand Up @@ -1586,6 +1614,7 @@ describe('User ID', function () {
attachIdSystem(zeotapIdPlusSubmodule);
attachIdSystem(haloIdSubmodule);
attachIdSystem(criteoIdSubmodule);
attachIdSystem(tapadIdSubmodule);

config.setConfig(getConfigMock(['pubCommonId', 'pubcid', 'cookie'],
['unifiedId', 'unifiedid', 'cookie'],
Expand All @@ -1597,7 +1626,8 @@ describe('User ID', function () {
['intentIqId', 'intentIqId', 'cookie'],
['zeotapIdPlus', 'IDP', 'cookie'],
['haloId', 'haloId', 'cookie'],
['criteo', 'storage_criteo', 'cookie']));
['criteo', 'storage_criteo', 'cookie'],
['tapadId', 'tapad_id', 'cookie']));

requestBidsHook(function () {
adUnits.forEach(unit => {
Expand Down