Skip to content

Commit 11e3c90

Browse files
Merge branch 'UOE-10758' of https://github.com/pm-nitin-shirsat/Prebid.js into UOE-10758
2 parents cb85e20 + 26a9bde commit 11e3c90

8 files changed

+225
-44
lines changed

modules/anonymisedRtdProvider.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ import {getStorageManager} from '../src/storageManager.js';
99
import {submodule} from '../src/hook.js';
1010
import {isPlainObject, mergeDeep, logMessage, logError} from '../src/utils.js';
1111
import {MODULE_TYPE_RTD} from '../src/activities/modules.js';
12-
12+
/**
13+
* @typedef {import('../modules/rtdModule/index.js').RtdSubmodule} RtdSubmodule
14+
*/
1315
export function createRtdProvider(moduleName) {
1416
const MODULE_NAME = 'realTimeData';
1517
const SUBMODULE_NAME = moduleName;
18+
const GVLID = 1116;
1619

1720
const storage = getStorageManager({ moduleType: MODULE_TYPE_RTD, moduleName: SUBMODULE_NAME });
1821
/**
@@ -106,6 +109,7 @@ export function createRtdProvider(moduleName) {
106109
/** @type {RtdSubmodule} */
107110
const rtdSubmodule = {
108111
name: SUBMODULE_NAME,
112+
gvlid: GVLID,
109113
getBidRequestData: getRealTimeData,
110114
init: init
111115
};

modules/anonymisedRtdProvider.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Anonymised’s Real-time Data Provider automatically obtains segment IDs from th
88
- Build the anonymisedRtd module into the Prebid.js package with:
99

1010
```bash
11-
gulp build --modules=anonymisedRtdProvider,...
11+
gulp build --modules=rtdModule,anonymisedRtdProvider,...
1212
```
1313

1414
- Use `setConfig` to instruct Prebid.js to initilaize the anonymisedRtdProvider module, as specified below.

modules/jwplayerRtdProvider.js

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import {submodule} from '../src/hook.js';
1313
import {config} from '../src/config.js';
1414
import {ajaxBuilder} from '../src/ajax.js';
15-
import {deepAccess, logError} from '../src/utils.js';
15+
import { deepAccess, logError, logWarn } from '../src/utils.js'
1616
import {find} from '../src/polyfill.js';
1717
import {getGlobal} from '../src/prebidGlobal.js';
1818

@@ -429,17 +429,37 @@ export function addTargetingToBid(bid, targeting) {
429429
bid.rtd = Object.assign({}, rtd, jwRtd);
430430
}
431431

432-
function getPlayer(playerDivId) {
432+
export function getPlayer(playerDivId) {
433433
const jwplayer = window.jwplayer;
434434
if (!jwplayer) {
435435
logError(SUBMODULE_NAME + '.js was not found on page');
436436
return;
437437
}
438438

439-
const player = jwplayer(playerDivId);
440-
if (!player || !player.getPlaylist) {
441-
logError('player ID did not match any players');
439+
let player = jwplayer(playerDivId);
440+
if (player && player.getPlaylist) {
441+
return player;
442+
}
443+
444+
const playerOnPageCount = document.getElementsByClassName('jwplayer').length;
445+
if (playerOnPageCount === 0) {
446+
logError('No JWPlayer instances have been detected on the page');
442447
return;
443448
}
444-
return player;
449+
450+
let errorMessage = `player Div ID ${playerDivId} did not match any players.`;
451+
452+
// If there are multiple instances on the page, we cannot guess which one should be targeted.
453+
if (playerOnPageCount > 1) {
454+
logError(errorMessage);
455+
return;
456+
}
457+
458+
player = jwplayer();
459+
if (player && player.getPlaylist) {
460+
logWarn(`${errorMessage} Targeting player Div ID ${player.id} instead`);
461+
return player;
462+
}
463+
464+
logError(errorMessage);
445465
}

modules/mgidBidAdapter.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ _each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_ID_TO_KEY_MAP[anAsset.ID] = anAs
8686
_each(NATIVE_ASSETS, anAsset => { _NATIVE_ASSET_KEY_TO_ASSET_MAP[anAsset.KEY] = anAsset });
8787

8888
export const spec = {
89-
VERSION: '1.6',
89+
VERSION: '1.7',
9090
code: BIDDER_CODE,
9191
gvlid: GVLID,
9292
supportedMediaTypes: [BANNER, NATIVE],
@@ -167,6 +167,8 @@ export const spec = {
167167
tagid,
168168
secure,
169169
};
170+
const gpid = deepAccess(bid, 'ortb2Imp.ext.gpid');
171+
gpid && isStr(gpid) && deepSetValue(impObj, `ext.gpid`, gpid);
170172
const floorData = getBidFloor(bid, cur);
171173
if (floorData.floor) {
172174
impObj.bidfloor = floorData.floor;

modules/permutiveRtdProvider.js

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ export function getModuleConfig(customModuleConfig) {
9595
/**
9696
* Sets ortb2 config for ac bidders
9797
* @param {Object} bidderOrtb2 - The ortb2 object for the all bidders
98-
* @param {Object} customModuleConfig - Publisher config for module
98+
* @param {Object} moduleConfig - Publisher config for module
99+
* @param {Object} segmentData - Segment data grouped by bidder or type
99100
*/
100101
export function setBidderRtb (bidderOrtb2, moduleConfig, segmentData) {
101102
const acBidders = deepAccess(moduleConfig, 'params.acBidders')
@@ -129,13 +130,13 @@ export function setBidderRtb (bidderOrtb2, moduleConfig, segmentData) {
129130

130131
/**
131132
* Updates `user.data` object in existing bidder config with Permutive segments
132-
* @param string bidder - The bidder
133+
* @param {string} bidder - The bidder identifier
133134
* @param {Object} currConfig - Current bidder config
134-
* @param {Object[]} transformationConfigs - array of objects with `id` and `config` properties, used to determine
135-
* the transformations on user data to include the ORTB2 object
136135
* @param {string[]} segmentIDs - Permutive segment IDs
137136
* @param {string[]} sspSegmentIDs - Permutive SSP segment IDs
138137
* @param {Object} topics - Privacy Sandbox Topics, keyed by IAB taxonomy version (600, 601, etc.)
138+
* @param {Object[]} transformationConfigs - array of objects with `id` and `config` properties, used to determine
139+
* the transformations on user data to include the ORTB2 object
139140
* @param {Object} segmentData - The segments available for targeting
140141
* @return {Object} Merged ortb2 object
141142
*/
@@ -270,7 +271,7 @@ function setSegments (reqBidsConfigObj, moduleConfig, segmentData) {
270271
*/
271272
function makeSafe (fn) {
272273
try {
273-
fn()
274+
return fn()
274275
} catch (e) {
275276
logError(e)
276277
}
@@ -310,23 +311,71 @@ export function isPermutiveOnPage () {
310311
* @param {number} maxSegs - Maximum number of segments to be included
311312
* @return {Object}
312313
*/
313-
export function getSegments (maxSegs) {
314-
const legacySegs = readSegments('_psegs', []).map(Number).filter(seg => seg >= 1000000).map(String)
315-
const _ppam = readSegments('_ppam', [])
316-
const _pcrprs = readSegments('_pcrprs', [])
317-
314+
export function getSegments(maxSegs) {
318315
const segments = {
319-
ac: [..._pcrprs, ..._ppam, ...legacySegs],
320-
ix: readSegments('_pindexs', []),
321-
rubicon: readSegments('_prubicons', []),
322-
appnexus: readSegments('_papns', []),
323-
gam: readSegments('_pdfps', []),
324-
ssp: readSegments('_pssps', {
325-
cohorts: [],
326-
ssps: []
316+
ac:
317+
makeSafe(() => {
318+
const legacySegs =
319+
makeSafe(() =>
320+
readSegments('_psegs', [])
321+
.map(Number)
322+
.filter((seg) => seg >= 1000000)
323+
.map(String),
324+
) || [];
325+
const _ppam = makeSafe(() => readSegments('_ppam', []).map(String)) || [];
326+
const _pcrprs = makeSafe(() => readSegments('_pcrprs', []).map(String)) || [];
327+
328+
return [..._pcrprs, ..._ppam, ...legacySegs];
329+
}) || [],
330+
331+
ix:
332+
makeSafe(() => {
333+
const _pindexs = readSegments('_pindexs', []);
334+
return _pindexs.map(String);
335+
}) || [],
336+
337+
rubicon:
338+
makeSafe(() => {
339+
const _prubicons = readSegments('_prubicons', []);
340+
return _prubicons.map(String);
341+
}) || [],
342+
343+
appnexus:
344+
makeSafe(() => {
345+
const _papns = readSegments('_papns', []);
346+
return _papns.map(String);
347+
}) || [],
348+
349+
gam:
350+
makeSafe(() => {
351+
const _pdfps = readSegments('_pdfps', []);
352+
return _pdfps.map(String);
353+
}) || [],
354+
355+
ssp: makeSafe(() => {
356+
const _pssps = readSegments('_pssps', {
357+
cohorts: [],
358+
ssps: [],
359+
});
360+
361+
return {
362+
cohorts: makeSafe(() => _pssps.cohorts.map(String)) || [],
363+
ssps: makeSafe(() => _pssps.ssps.map(String)) || [],
364+
};
327365
}),
328-
topics: readSegments('_ppsts', {}),
329-
}
366+
367+
topics:
368+
makeSafe(() => {
369+
const _ppsts = readSegments('_ppsts', {});
370+
371+
const topics = {};
372+
for (const [k, value] of Object.entries(_ppsts)) {
373+
topics[k] = makeSafe(() => value.map(String)) || [];
374+
}
375+
376+
return topics;
377+
}) || {},
378+
};
330379

331380
for (const bidder in segments) {
332381
if (bidder === 'ssp') {
@@ -342,7 +391,8 @@ export function getSegments (maxSegs) {
342391
}
343392
}
344393

345-
return segments
394+
logger.logInfo(`Read segments`, segments)
395+
return segments;
346396
}
347397

348398
/**
@@ -393,7 +443,7 @@ function iabSegmentId(permutiveSegmentId, iabIds) {
393443
* Pull the latest configuration and cohort information and update accordingly.
394444
*
395445
* @param reqBidsConfigObj - Bidder provided config for request
396-
* @param customModuleConfig - Publisher provide config
446+
* @param moduleConfig - Publisher provided config
397447
*/
398448
export function readAndSetCohorts(reqBidsConfigObj, moduleConfig) {
399449
const segmentData = getSegments(deepAccess(moduleConfig, 'params.maxSegs'))

test/spec/modules/jwplayerRtdProvider_spec.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
getVatFromCache,
1313
getVatFromPlayer,
1414
setOverrides,
15+
getPlayer,
1516
jwplayerSubmodule
1617
} from 'modules/jwplayerRtdProvider.js';
1718
import {server} from 'test/mocks/xhr.js';
@@ -1603,6 +1604,66 @@ describe('jwplayerRtdProvider', function() {
16031604
});
16041605
});
16051606

1607+
describe('Player detection', function () {
1608+
const playerInstanceMock = {
1609+
getPlaylist: () => [],
1610+
getPlaylistItem: () => ({})
1611+
};
1612+
1613+
beforeEach(function () {
1614+
window.jwplayer = sinon.stub();
1615+
});
1616+
1617+
afterEach(function () {
1618+
delete window.jwplayer;
1619+
});
1620+
1621+
it('should fail if jwplayer global does not exist', function () {
1622+
delete window.jwplayer;
1623+
expect(getPlayer('divId')).to.be.undefined;
1624+
});
1625+
1626+
it('should return the player instance for the specified div id', function () {
1627+
window.jwplayer.returns(playerInstanceMock);
1628+
const player = getPlayer('divId');
1629+
expect(player).to.deep.equal(playerInstanceMock);
1630+
});
1631+
1632+
it('should request a player when the div id does not match a player on the page and only 1 player is in the DOM', function () {
1633+
const playerDomElement = document.createElement('div');
1634+
playerDomElement.className = 'jwplayer';
1635+
document.body.appendChild(playerDomElement);
1636+
1637+
window.jwplayer.withArgs('invalidDivId').returns(undefined);
1638+
window.jwplayer.returns(playerInstanceMock);
1639+
1640+
const playerInstance = getPlayer('invalidDivId');
1641+
1642+
expect(playerInstance).to.deep.equal(playerInstanceMock);
1643+
1644+
document.body.removeChild(playerDomElement);
1645+
});
1646+
1647+
it('should fail when the div id does not match a player on the page, and multiple players are instantiated', function () {
1648+
const firstPlayerDomElement = document.createElement('div');
1649+
const secondPlayerDomElement = document.createElement('div');
1650+
firstPlayerDomElement.className = 'jwplayer';
1651+
secondPlayerDomElement.className = 'jwplayer';
1652+
document.body.appendChild(firstPlayerDomElement);
1653+
document.body.appendChild(secondPlayerDomElement);
1654+
1655+
window.jwplayer.withArgs('invalidDivId').returns(undefined);
1656+
window.jwplayer.returns(playerInstanceMock);
1657+
1658+
const playerInstance = getPlayer('invalidDivId');
1659+
1660+
expect(playerInstance).to.be.undefined;
1661+
1662+
document.body.removeChild(firstPlayerDomElement);
1663+
document.body.removeChild(secondPlayerDomElement);
1664+
});
1665+
});
1666+
16061667
describe('jwplayerSubmodule', function () {
16071668
it('successfully instantiates', function () {
16081669
expect(jwplayerSubmodule.init()).to.equal(true);

test/spec/modules/mgidBidAdapter_spec.js

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,14 @@ describe('Mgid bid adapter', function () {
320320
let abid = {
321321
adUnitCode: 'div',
322322
bidder: 'mgid',
323+
ortb2Imp: {
324+
ext: {
325+
gpid: '/1111/gpid',
326+
data: {
327+
pbadslot: '/1111/gpid',
328+
}
329+
}
330+
},
323331
params: {
324332
accountId: '1',
325333
placementId: '2',
@@ -447,12 +455,13 @@ describe('Mgid bid adapter', function () {
447455
expect(data.device.w).equal(screenWidth);
448456
expect(data.device.language).to.deep.equal(lang);
449457
expect(data.imp[0].tagid).to.deep.equal('2/div');
458+
expect(data.imp[0].ext.gpid).to.deep.equal('/1111/gpid');
450459
expect(data.imp[0].banner).to.deep.equal({w: 300, h: 250});
451460
expect(data.imp[0].secure).to.deep.equal(secure);
452461
expect(request).to.deep.equal({
453462
'method': 'POST',
454463
'url': 'https://prebid.mgid.com/prebid/1',
455-
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"banner":{"w":300,"h":250}}],"tmax":3000}`,
464+
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"ext":{"gpid":"/1111/gpid"},"banner":{"w":300,"h":250}}],"tmax":3000}`,
456465
});
457466
});
458467
it('should not return native imp if minimum asset list not requested', function () {
@@ -496,12 +505,13 @@ describe('Mgid bid adapter', function () {
496505
expect(data.device.w).equal(screenWidth);
497506
expect(data.device.language).to.deep.equal(lang);
498507
expect(data.imp[0].tagid).to.deep.equal('2/div');
508+
expect(data.imp[0].ext.gpid).to.deep.equal('/1111/gpid');
499509
expect(data.imp[0].native).is.a('object').and.to.deep.equal({'request': {'assets': [{'id': 1, 'required': 1, 'title': {'len': 80}}, {'id': 2, 'img': {'h': 80, 'type': 3, 'w': 80}, 'required': 0}, {'data': {'type': 1}, 'id': 11, 'required': 0}], 'plcmtcnt': 1}});
500510
expect(data.imp[0].secure).to.deep.equal(secure);
501511
expect(request).to.deep.equal({
502512
'method': 'POST',
503513
'url': 'https://prebid.mgid.com/prebid/1',
504-
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":0,"img":{"type":3,"w":80,"h":80}},{"id":11,"required":0,"data":{"type":1}}]}}}],"tmax":3000}`,
514+
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"ext":{"gpid":"/1111/gpid"},"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":0,"img":{"type":3,"w":80,"h":80}},{"id":11,"required":0,"data":{"type":1}}]}}}],"tmax":3000}`,
505515
});
506516
});
507517
it('should return proper native imp with image altered', function () {
@@ -538,7 +548,7 @@ describe('Mgid bid adapter', function () {
538548
expect(request).to.deep.equal({
539549
'method': 'POST',
540550
'url': 'https://prebid.mgid.com/prebid/1',
541-
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":1,"img":{"type":3,"w":492,"h":328,"wmin":50,"hmin":50}},{"id":3,"required":0,"img":{"type":1,"w":50,"h":50}},{"id":11,"required":0,"data":{"type":1}}]}}}],"tmax":3000}`,
551+
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"ext":{"gpid":"/1111/gpid"},"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":1,"img":{"type":3,"w":492,"h":328,"wmin":50,"hmin":50}},{"id":3,"required":0,"img":{"type":1,"w":50,"h":50}},{"id":11,"required":0,"data":{"type":1}}]}}}],"tmax":3000}`,
542552
});
543553
});
544554
it('should return proper native imp with sponsoredBy', function () {
@@ -574,7 +584,7 @@ describe('Mgid bid adapter', function () {
574584
expect(request).to.deep.equal({
575585
'method': 'POST',
576586
'url': 'https://prebid.mgid.com/prebid/1',
577-
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":0,"img":{"type":3,"w":80,"h":80}},{"id":4,"required":0,"data":{"type":1}}]}}}],"tmax":3000}`,
587+
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"ext":{"gpid":"/1111/gpid"},"native":{"request":{"plcmtcnt":1,"assets":[{"id":1,"required":1,"title":{"len":80}},{"id":2,"required":0,"img":{"type":3,"w":80,"h":80}},{"id":4,"required":0,"data":{"type":1}}]}}}],"tmax":3000}`,
578588
});
579589
});
580590
it('should return proper banner request', function () {
@@ -608,7 +618,7 @@ describe('Mgid bid adapter', function () {
608618
expect(request).to.deep.equal({
609619
'method': 'POST',
610620
'url': 'https://prebid.mgid.com/prebid/1',
611-
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"banner":{"w":300,"h":600,"format":[{"w":300,"h":600},{"w":300,"h":250}],"pos":1}}],"tmax":3000}`,
621+
'data': `{"site":{"domain":"${domain}","page":"${page}"},"cur":["USD"],"geo":{"utcoffset":${utcOffset}},"device":{"ua":"${ua}","js":1,"dnt":${dnt},"h":${screenHeight},"w":${screenWidth},"language":"${lang}"},"ext":{"mgid_ver":"${mgid_ver}","prebid_ver":"${version}"},"imp":[{"tagid":"2/div","secure":${secure},"ext":{"gpid":"/1111/gpid"},"banner":{"w":300,"h":600,"format":[{"w":300,"h":600},{"w":300,"h":250}],"pos":1}}],"tmax":3000}`,
612622
});
613623
});
614624
it('should proper handle ortb2 data', function () {

0 commit comments

Comments
 (0)