Skip to content

Commit 88a3a64

Browse files
shikharsharma-zeotapBrightMountainMedia
authored and
BrightMountainMedia
committed
Zeotap ID+ submodule (prebid#5640)
* IDU-117 IDU-119 Add zeotap submodule * IDU-117 IDU-119 Add tests for zeotapId+ module * add zeotapId+ module spec * Add IDP base64 decode logic * remove unwanted file changes * rename zeotapId+ to zeotapIdPlus * add zeotapIdPlus submodule to submodules.json * refactor code for requested changes: remove storage from configParams * add tests to eids_spec * rebase n resolve conflicts
1 parent 32bd6bf commit 88a3a64

File tree

8 files changed

+292
-22
lines changed

8 files changed

+292
-22
lines changed

integrationExamples/gpt/userId_example.html

+3
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,9 @@
230230
name: "_li_pbid",
231231
expires: 28
232232
}
233+
},
234+
{
235+
name: "zeotapIdPlus"
233236
}],
234237
syncDelay: 5000,
235238
auctionDelay: 1000

modules/.submodules.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
"netIdSystem",
1313
"identityLinkIdSystem",
1414
"sharedIdSystem",
15-
"intentIqIdSystem"
15+
"intentIqIdSystem",
16+
"zeotapIdPlusIdSystem"
1617
],
1718
"adpod": [
1819
"freeWheelAdserverVideo",

modules/userId/eids.js

+5
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ const USER_IDS_CONFIG = {
123123
third: data.third
124124
} : undefined;
125125
}
126+
},
127+
// zeotapIdPlus
128+
'IDP': {
129+
source: 'zeotap.com',
130+
atype: 1
126131
}
127132
};
128133

modules/userId/eids.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ userIdAsEids = [
9595
third: 'some-random-id-value'
9696
}
9797
}]
98-
}
98+
},
99+
{
100+
source: 'zeotap.com',
101+
uids: [{
102+
id: 'some-random-id-value',
103+
atype: 1
104+
}]
105+
},
99106
]
100107
```

modules/zeotapIdPlusIdSystem.js

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/**
2+
* This module adds Zeotap to the User ID module
3+
* The {@link module:modules/userId} module is required
4+
* @module modules/zeotapIdPlusIdSystem
5+
* @requires module:modules/userId
6+
*/
7+
import * as utils from '../src/utils.js'
8+
import {submodule} from '../src/hook.js';
9+
import { getStorageManager } from '../src/storageManager.js';
10+
11+
const ZEOTAP_COOKIE_NAME = 'IDP';
12+
const storage = getStorageManager();
13+
14+
function readCookie() {
15+
return storage.cookiesAreEnabled ? storage.getCookie(ZEOTAP_COOKIE_NAME) : null;
16+
}
17+
18+
function readFromLocalStorage() {
19+
return storage.localStorageIsEnabled ? storage.getDataFromLocalStorage(ZEOTAP_COOKIE_NAME) : null;
20+
}
21+
22+
/** @type {Submodule} */
23+
export const zeotapIdPlusSubmodule = {
24+
/**
25+
* used to link submodule with config
26+
* @type {string}
27+
*/
28+
name: 'zeotapIdPlus',
29+
/**
30+
* decode the stored id value for passing to bid requests
31+
* @function
32+
* @param { Object | string | undefined } value
33+
* @return { Object | string | undefined }
34+
*/
35+
decode(value) {
36+
const id = value ? utils.isStr(value) ? value : utils.isPlainObject(value) ? value.id : undefined : undefined;
37+
return id ? {
38+
'IDP': JSON.parse(atob(id))
39+
} : undefined;
40+
},
41+
/**
42+
* performs action to obtain id and return a value in the callback's response argument
43+
* @function
44+
* @param {SubmoduleParams} configParams
45+
* @return {{id: string | undefined} | undefined}
46+
*/
47+
getId() {
48+
const id = readCookie() || readFromLocalStorage();
49+
return id ? { id } : undefined;
50+
}
51+
};
52+
submodule('userId', zeotapIdPlusSubmodule);

test/spec/modules/eids_spec.js

+14
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,20 @@ describe('eids array generation for known sub-modules', function() {
192192
}]
193193
});
194194
});
195+
it('zeotapIdPlus', function() {
196+
const userId = {
197+
IDP: 'some-random-id-value'
198+
};
199+
const newEids = createEidsArray(userId);
200+
expect(newEids.length).to.equal(1);
201+
expect(newEids[0]).to.deep.equal({
202+
source: 'zeotap.com',
203+
uids: [{
204+
id: 'some-random-id-value',
205+
atype: 1
206+
}]
207+
});
208+
});
195209
});
196210

197211
describe('Negative case', function() {

test/spec/modules/userId_spec.js

+67-20
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { expect } from 'chai';
2+
import find from 'core-js-pure/features/array/find.js';
3+
import { config } from 'src/config.js';
4+
import { newStorageManager } from 'src/storageManager.js';
5+
import { init, requestBidsHook, setSubmoduleRegistry } from 'modules/userId/index.js';
6+
import { zeotapIdPlusSubmodule } from 'modules/zeotapIdPlusIdSystem.js';
7+
8+
const storage = newStorageManager();
9+
10+
const ZEOTAP_COOKIE_NAME = 'IDP';
11+
const ZEOTAP_COOKIE = 'THIS-IS-A-DUMMY-COOKIE';
12+
const ENCODED_ZEOTAP_COOKIE = btoa(JSON.stringify(ZEOTAP_COOKIE));
13+
14+
function getConfigMock() {
15+
return {
16+
userSync: {
17+
syncDelay: 0,
18+
userIds: [{
19+
name: 'zeotapIdPlus'
20+
}]
21+
}
22+
}
23+
}
24+
25+
function getAdUnitMock(code = 'adUnit-code') {
26+
return {
27+
code,
28+
mediaTypes: {banner: {}, native: {}},
29+
sizes: [
30+
[300, 200],
31+
[300, 600]
32+
],
33+
bids: [{
34+
bidder: 'sampleBidder',
35+
params: { placementId: 'banner-only-bidder' }
36+
}]
37+
};
38+
}
39+
40+
function unsetCookie() {
41+
storage.setCookie(ZEOTAP_COOKIE_NAME, '');
42+
}
43+
44+
function unsetLocalStorage() {
45+
storage.setDataInLocalStorage(ZEOTAP_COOKIE_NAME, '');
46+
}
47+
48+
describe('Zeotap ID System', function() {
49+
describe('test method: getId', function() {
50+
afterEach(() => {
51+
unsetCookie();
52+
unsetLocalStorage();
53+
})
54+
55+
it('provides the stored Zeotap id if a cookie exists', function() {
56+
storage.setCookie(
57+
ZEOTAP_COOKIE_NAME,
58+
ENCODED_ZEOTAP_COOKIE,
59+
(new Date(Date.now() + 5000).toUTCString()),
60+
);
61+
let id = zeotapIdPlusSubmodule.getId();
62+
expect(id).to.deep.equal({
63+
id: ENCODED_ZEOTAP_COOKIE
64+
});
65+
});
66+
67+
it('provides the stored Zeotap id if cookie is absent but present in local storage', function() {
68+
storage.setDataInLocalStorage(ZEOTAP_COOKIE_NAME, ENCODED_ZEOTAP_COOKIE);
69+
let id = zeotapIdPlusSubmodule.getId();
70+
expect(id).to.deep.equal({
71+
id: ENCODED_ZEOTAP_COOKIE
72+
});
73+
});
74+
75+
it('returns undefined if both cookie and local storage are empty', function() {
76+
let id = zeotapIdPlusSubmodule.getId();
77+
expect(id).to.be.undefined
78+
})
79+
});
80+
81+
describe('test method: decode', function() {
82+
it('provides the Zeotap ID (IDP) from a stored object', function() {
83+
let zeotapId = {
84+
id: ENCODED_ZEOTAP_COOKIE,
85+
};
86+
87+
expect(zeotapIdPlusSubmodule.decode(zeotapId)).to.deep.equal({
88+
IDP: ZEOTAP_COOKIE
89+
});
90+
});
91+
92+
it('provides the Zeotap ID (IDP) from a stored string', function() {
93+
let zeotapId = ENCODED_ZEOTAP_COOKIE;
94+
95+
expect(zeotapIdPlusSubmodule.decode(zeotapId)).to.deep.equal({
96+
IDP: ZEOTAP_COOKIE
97+
});
98+
});
99+
});
100+
101+
describe('requestBids hook', function() {
102+
let adUnits;
103+
104+
beforeEach(function() {
105+
adUnits = [getAdUnitMock()];
106+
storage.setCookie(
107+
ZEOTAP_COOKIE_NAME,
108+
ENCODED_ZEOTAP_COOKIE,
109+
(new Date(Date.now() + 5000).toUTCString()),
110+
);
111+
setSubmoduleRegistry([zeotapIdPlusSubmodule]);
112+
init(config);
113+
config.setConfig(getConfigMock());
114+
});
115+
116+
afterEach(function() {
117+
unsetCookie();
118+
unsetLocalStorage();
119+
});
120+
121+
it('when a stored Zeotap ID exists it is added to bids', function(done) {
122+
requestBidsHook(function() {
123+
adUnits.forEach(unit => {
124+
unit.bids.forEach(bid => {
125+
expect(bid).to.have.deep.nested.property('userId.IDP');
126+
expect(bid.userId.IDP).to.equal(ZEOTAP_COOKIE);
127+
const zeotapIdAsEid = find(bid.userIdAsEids, e => e.source == 'zeotap.com');
128+
expect(zeotapIdAsEid).to.deep.equal({
129+
source: 'zeotap.com',
130+
uids: [{
131+
id: ZEOTAP_COOKIE,
132+
atype: 1,
133+
}]
134+
});
135+
});
136+
});
137+
done();
138+
}, { adUnits });
139+
});
140+
});
141+
});

0 commit comments

Comments
 (0)