From 8f339321fb77712638c4cdb69f8ba2c7941143fb Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Mon, 9 May 2022 16:41:37 -0400 Subject: [PATCH 01/15] initial creation of the buildRequests function --- modules/jwplayerBidAdapter.js | 92 ++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 37fa480b560..ca5a1197ed3 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -2,8 +2,11 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; // import { config } from 'src/config'; import { VIDEO } from '../src/mediaTypes.js'; +import { deepSetValue, isFn } from '../src/utils.js'; const BIDDER_CODE = 'jwplayer'; +const URL = 'https://ib.adnxs.com/openrtb2/prebid'; + const GVLID = 1046; const SUPPORTED_AD_TYPES = [VIDEO]; @@ -30,9 +33,24 @@ export const spec = { * Make a server request from the list of BidRequests. * * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. + * @param bidderRequest * @return ServerRequest Info describing the request to the server. */ - buildRequests: function(validBidRequests, bidderRequest) {}, + buildRequests: function(bidRequests, bidderRequest) { + if (!bidRequests) { + return; + } + + return bidRequests.map(bidRequest => { + const payload = buildRequest(bidRequest, bidderRequests); + + return { + method: 'POST', + url: URL, + data: payload + } + }); + }, /** * Unpack the response from the server into a list of bids. @@ -50,4 +68,76 @@ export const spec = { // onBidderError: function({ error, bidderRequest }) {} }; +function buildRequest(bidRequest, bidderRequest) { + const {params} = bidRequest; + + const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); + const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); + + const videoParams = { + ...videoAdUnit, + ...videoBidderParams + } + + const video = { + w: parseInt(videoParams.playerSize[0][0], 10), + h: parseInt(videoParams.playerSize[0][1], 10) + } + + // Bid FLoor + const bidFloorRequest = { + currency: bidRequest.params.cur || 'USD', + mediaType: 'video', + size: '*' + }; + + let floorData = bidRquest.params; + if (isFn(bidRequest.getFloor)) { + floorData = bidRequest.getFloor(bidFloorRequest); + } else { + if (params.bidfloor) { + floorData = {floor: params.bidfloor, currency: params.currency || 'USD'}; + } + } + + // Open RTB Request Object + const openrtbRequest = { + id: bidRequest.bidId, + imp: [ + { + id: '1', + video: video, + secure: isSecure() ? 1 : 0, + bidfloor: floorData.floor, + bidfloorcur: floorData.currency + } + ], + site: { + domain: window.location.hostname, + page: window.location.href, + ref: bidRequest.refererInfo ? bidRequest.refererInfo.referer || null : null + }, + ext: { + hb: 1, + prebidver: '$prebid.version$', + adapterver: spec.VERSION + } + } + + // content + + // Attaching GDPR Consent Params + if (bidderRequest.gdprConsent) { + deepSetValue(openrtbRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + deepSetValue(openrtbRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + } + + // CCPA + if (bidderRequest.uspConsent) { + deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); + } + + return JSON.stringify(openrtbRequest); +} + registerBidder(spec); From 220b341d2771ad94c265b26b2d5810c1de4c6eaa Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Thu, 12 May 2022 21:16:20 -0400 Subject: [PATCH 02/15] incorporated feedback from pr and refactored. --- modules/jwplayerBidAdapter.js | 187 ++++++++++++++++++++++++---------- 1 file changed, 136 insertions(+), 51 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index ca5a1197ed3..08f73ebab9d 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -10,6 +10,23 @@ const URL = 'https://ib.adnxs.com/openrtb2/prebid'; const GVLID = 1046; const SUPPORTED_AD_TYPES = [VIDEO]; +const VIDEO_ORTB_PARAMS = [ + 'mimes', + 'minduration', + 'maxduration', + 'placement', + 'protocols', + 'startdelay', + 'skip', + 'skipafter', + 'minbitrate', + 'maxbitrate', + 'delivery', + 'playbackmethod', + 'api', + 'linearity' +]; + export const spec = { code: BIDDER_CODE, gvlid: GVLID, @@ -32,7 +49,7 @@ export const spec = { /** * Make a server request from the list of BidRequests. * - * @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be sent to the Server. + * @param {BidRequest[]} bidRequests A non-empty list of bid requests, or ad units, which should be sent to the server. * @param bidderRequest * @return ServerRequest Info describing the request to the server. */ @@ -42,7 +59,7 @@ export const spec = { } return bidRequests.map(bidRequest => { - const payload = buildRequest(bidRequest, bidderRequests); + const payload = buildRequest(bidRequest, bidderRequest); return { method: 'POST', @@ -69,75 +86,143 @@ export const spec = { }; function buildRequest(bidRequest, bidderRequest) { - const {params} = bidRequest; + // bidRequest.mediaTypes.video + // bidRequest.params (bid parameters) - const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); - const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); + // bidderRequest.gdprConsent + // bidderRequest.uspConsent + + // Open RTB Request Object + const openrtbRequest = { + id: params.bidId, + imp: buildRequestImpression(bidRequest, bidderRequest), + site: buildRequestSite(), + device: buildRequestDevice() + }; - const videoParams = { - ...videoAdUnit, - ...videoBidderParams + // Attaching GDPR Consent Params + if (bidderRequest.gdprConsent) { + deepSetValue(openrtbRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); + deepSetValue(openrtbRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); + } + + // CCPA + if (bidderRequest.uspConsent) { + deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); } + return JSON.stringify(openrtbRequest);; +} + +function buildRequestImpression(bidRequest, bidderRequest) { + const impressions = []; + + const impressionObject = { + id: bidRequest.adUnitCode, + secure: isSecure() ? 1 : 0 + }; + + impressionObject.video = buildImpressionVideo(bidRequest); + + const bidFloorData = buildBidFloorData(bidRequest); + impressionObject.bidfloor = bidFloorData.floor; + impressionObject.bidfloorcur = bidFloorData.currency; + + impressionObject.ext = buildImpressionExtension(); // TODO: Complete + + impressions.push(impressionObject); + + return impressions; +} + +function buildImpressionVideo(bidRequest) { + const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); + + const playerSize = videoAdUnit.playerSize; + + const contentWidth = playerSize[0][0]; + const contentHeight = playerSize[0][1]; + const video = { - w: parseInt(videoParams.playerSize[0][0], 10), - h: parseInt(videoParams.playerSize[0][1], 10) + w: parseInt(contentWidth, 10), + h: parseInt(contentHeight, 10) + } + + // Obtain all ORTB params related video from Ad Unit + VIDEO_ORTB_PARAMS.forEach((param) => { + if (videoAdUnit.hasOwnProperty(param)) { + video[param] = videoAdUnit[param]; + } + }); + + // Placement Inference Rules: + // - If no placement is defined then default to 1 (In Stream) + video.placement = video.placement || 2; + + // - If product is instream (for instream context) then override placement to 1 + if (params.context === 'instream') { + video.startdelay = video.startdelay || 0; + video.placement = 1; } +} - // Bid FLoor +function buildBidFloorData(bidRequest) { + const {params} = bidRequest; + // Bid Floor const bidFloorRequest = { - currency: bidRequest.params.cur || 'USD', + currency: params.currency || 'USD', mediaType: 'video', size: '*' }; - let floorData = bidRquest.params; + let floorData; if (isFn(bidRequest.getFloor)) { floorData = bidRequest.getFloor(bidFloorRequest); - } else { - if (params.bidfloor) { - floorData = {floor: params.bidfloor, currency: params.currency || 'USD'}; - } - } - - // Open RTB Request Object - const openrtbRequest = { - id: bidRequest.bidId, - imp: [ - { - id: '1', - video: video, - secure: isSecure() ? 1 : 0, - bidfloor: floorData.floor, - bidfloorcur: floorData.currency - } - ], - site: { - domain: window.location.hostname, - page: window.location.href, - ref: bidRequest.refererInfo ? bidRequest.refererInfo.referer || null : null - }, - ext: { - hb: 1, - prebidver: '$prebid.version$', - adapterver: spec.VERSION - } + } else if (params.bidfloor) { + floorData = {floor: params.bidfloor, currency: params.currency || 'USD'}; } - // content + return floorData; +} - // Attaching GDPR Consent Params - if (bidderRequest.gdprConsent) { - deepSetValue(openrtbRequest, 'user.ext.consent', bidderRequest.gdprConsent.consentString); - deepSetValue(openrtbRequest, 'regs.ext.gdpr', (bidderRequest.gdprConsent.gdprApplies ? 1 : 0)); - } +function buildRequestSite(bidRequest) { + const site = { + domain: window.location.hostname, + page: window.location.href, + ref: bidRequest.refererInfo ? bidRequest.refererInfo.referer || null : null + }; - // CCPA - if (bidderRequest.uspConsent) { - deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); + // Site Content + /* + if (videoAdUnit.content && isPlainObject(videoAdUnit.content)) { + openrtbRequest.site.content = {}; + const contentStringKeys = ['id', 'title', 'series', 'season', 'genre', 'contentrating', 'language', 'url']; + const contentNumberkeys = ['episode', 'prodq', 'context', 'livestream', 'len']; + const contentArrayKeys = ['cat']; + const contentObjectKeys = ['ext']; + for (const contentKey in videoBidderParams.content) { + if ( + (contentStringKeys.indexOf(contentKey) > -1 && isStr(videoAdUnit.content[contentKey])) || + (contentNumberkeys.indexOf(contentKey) > -1 && isNumber(videoAdUnit.content[contentKey])) || + (contentObjectKeys.indexOf(contentKey) > -1 && isPlainObject(videoAdUnit.content[contentKey])) || + (contentArrayKeys.indexOf(contentKey) > -1 && isArray(videoAdUnit.content[contentKey]) && + videoAdUnit.content[contentKey].every(catStr => isStr(catStr)))) { + site.content[contentKey] = videoAdUnit.content[contentKey]; + } else { + logMessage('JWPlayer bid adapter validation error: ', contentKey, ' is either not supported is OpenRTB V2.5 or value is undefined'); + } + } } + */ - return JSON.stringify(openrtbRequest); + return site; +} + +function buildRequestDevice() { + return { + ua: navigator.userAgent, + ip: '' + }; } registerBidder(spec); From 163e165d3d23d97462e1b001443adcd4f50d3113 Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Thu, 19 May 2022 10:16:44 -0400 Subject: [PATCH 03/15] added video object, impExt object, and site content object to jwplayerBidAdapter --- modules/jwplayerBidAdapter.js | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 08f73ebab9d..574c329f449 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -128,7 +128,7 @@ function buildRequestImpression(bidRequest, bidderRequest) { impressionObject.bidfloor = bidFloorData.floor; impressionObject.bidfloorcur = bidFloorData.currency; - impressionObject.ext = buildImpressionExtension(); // TODO: Complete + impressionObject.ext = buildImpressionExtension(bidRequest); impressions.push(impressionObject); @@ -164,6 +164,16 @@ function buildImpressionVideo(bidRequest) { video.startdelay = video.startdelay || 0; video.placement = 1; } + + return video; +} + +function buildImpressionExtension(bidRequest) { + return { + appnexus: { + placement_id: bidRequest.params.placementId + } + }; } function buildBidFloorData(bidRequest) { @@ -192,9 +202,10 @@ function buildRequestSite(bidRequest) { ref: bidRequest.refererInfo ? bidRequest.refererInfo.referer || null : null }; + const videoParams = deepAccess(bidRequest, 'mediaTypes.video', {}); + // Site Content - /* - if (videoAdUnit.content && isPlainObject(videoAdUnit.content)) { + if (videoParams.content && isPlainObject(videoParams.content)) { openrtbRequest.site.content = {}; const contentStringKeys = ['id', 'title', 'series', 'season', 'genre', 'contentrating', 'language', 'url']; const contentNumberkeys = ['episode', 'prodq', 'context', 'livestream', 'len']; @@ -202,19 +213,17 @@ function buildRequestSite(bidRequest) { const contentObjectKeys = ['ext']; for (const contentKey in videoBidderParams.content) { if ( - (contentStringKeys.indexOf(contentKey) > -1 && isStr(videoAdUnit.content[contentKey])) || - (contentNumberkeys.indexOf(contentKey) > -1 && isNumber(videoAdUnit.content[contentKey])) || - (contentObjectKeys.indexOf(contentKey) > -1 && isPlainObject(videoAdUnit.content[contentKey])) || - (contentArrayKeys.indexOf(contentKey) > -1 && isArray(videoAdUnit.content[contentKey]) && - videoAdUnit.content[contentKey].every(catStr => isStr(catStr)))) { - site.content[contentKey] = videoAdUnit.content[contentKey]; + (contentStringKeys.indexOf(contentKey) > -1 && isStr(videoParams.content[contentKey])) || + (contentNumberkeys.indexOf(contentKey) > -1 && isNumber(videoParams.content[contentKey])) || + (contentObjectKeys.indexOf(contentKey) > -1 && isPlainObject(videoParams.content[contentKey])) || + (contentArrayKeys.indexOf(contentKey) > -1 && isArray(videoParams.content[contentKey]) && + videoParams.content[contentKey].every(catStr => isStr(catStr)))) { + site.content[contentKey] = videoParams.content[contentKey]; } else { logMessage('JWPlayer bid adapter validation error: ', contentKey, ' is either not supported is OpenRTB V2.5 or value is undefined'); } } } - */ - return site; } From 05528442a85071e984da1a405aaa5f11dbf6a3f6 Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Thu, 19 May 2022 10:21:39 -0400 Subject: [PATCH 04/15] added feedback from pr --- modules/jwplayerBidAdapter.js | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 574c329f449..afefc5fa4f6 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -10,13 +10,15 @@ const URL = 'https://ib.adnxs.com/openrtb2/prebid'; const GVLID = 1046; const SUPPORTED_AD_TYPES = [VIDEO]; +// Video Parameters +// https://docs.prebid.org/dev-docs/bidder-adaptor.html#step-2-accept-video-parameters-and-pass-them-to-your-server const VIDEO_ORTB_PARAMS = [ 'mimes', 'minduration', 'maxduration', - 'placement', 'protocols', 'startdelay', + 'placement', 'skip', 'skipafter', 'minbitrate', @@ -136,35 +138,17 @@ function buildRequestImpression(bidRequest, bidderRequest) { } function buildImpressionVideo(bidRequest) { - const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); - - const playerSize = videoAdUnit.playerSize; + const videoParams = deepAccess(bidRequest, 'mediaTypes.video', {}); - const contentWidth = playerSize[0][0]; - const contentHeight = playerSize[0][1]; - - const video = { - w: parseInt(contentWidth, 10), - h: parseInt(contentHeight, 10) - } + const video = {}; // Obtain all ORTB params related video from Ad Unit VIDEO_ORTB_PARAMS.forEach((param) => { - if (videoAdUnit.hasOwnProperty(param)) { - video[param] = videoAdUnit[param]; + if (videoParams.hasOwnProperty(param)) { + video[param] = videoParams[param]; } }); - // Placement Inference Rules: - // - If no placement is defined then default to 1 (In Stream) - video.placement = video.placement || 2; - - // - If product is instream (for instream context) then override placement to 1 - if (params.context === 'instream') { - video.startdelay = video.startdelay || 0; - video.placement = 1; - } - return video; } From 4c9ff21551e3236e228f9356b0de66b0ce86c3ea Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Wed, 25 May 2022 15:32:17 -0400 Subject: [PATCH 05/15] fixed parameters for methods in jwplayerBidAdapter --- modules/jwplayerBidAdapter.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index afefc5fa4f6..41f6535bec8 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -88,17 +88,11 @@ export const spec = { }; function buildRequest(bidRequest, bidderRequest) { - // bidRequest.mediaTypes.video - // bidRequest.params (bid parameters) - - // bidderRequest.gdprConsent - // bidderRequest.uspConsent - // Open RTB Request Object const openrtbRequest = { - id: params.bidId, + id: bidRequest.params.bidId, imp: buildRequestImpression(bidRequest, bidderRequest), - site: buildRequestSite(), + site: buildRequestSite(bidRequest), device: buildRequestDevice() }; @@ -116,7 +110,7 @@ function buildRequest(bidRequest, bidderRequest) { return JSON.stringify(openrtbRequest);; } -function buildRequestImpression(bidRequest, bidderRequest) { +function buildRequestImpression(bidRequest) { const impressions = []; const impressionObject = { From 2c45a9bd42da06ea8f00764cfdd36c56a9c27446 Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Thu, 2 Jun 2022 18:20:48 -0400 Subject: [PATCH 06/15] added feedback from pr and unit tests --- modules/jwplayerBidAdapter.js | 61 +++++++++---------- test/spec/modules/jwplayerBidAdapter_spec.js | 64 +++++++++++++++++++- 2 files changed, 91 insertions(+), 34 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 41f6535bec8..17b2e83ff34 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -2,7 +2,14 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; // import { config } from 'src/config'; import { VIDEO } from '../src/mediaTypes.js'; -import { deepSetValue, isFn } from '../src/utils.js'; +import { isStr, + isPlainObject, + isNumber, + isArray, + isFn, + deepAccess, + deepSetValue, + logMessage } from '../src/utils.js'; const BIDDER_CODE = 'jwplayer'; const URL = 'https://ib.adnxs.com/openrtb2/prebid'; @@ -10,7 +17,7 @@ const URL = 'https://ib.adnxs.com/openrtb2/prebid'; const GVLID = 1046; const SUPPORTED_AD_TYPES = [VIDEO]; -// Video Parameters +// Video Parameters // https://docs.prebid.org/dev-docs/bidder-adaptor.html#step-2-accept-video-parameters-and-pass-them-to-your-server const VIDEO_ORTB_PARAMS = [ 'mimes', @@ -90,7 +97,7 @@ export const spec = { function buildRequest(bidRequest, bidderRequest) { // Open RTB Request Object const openrtbRequest = { - id: bidRequest.params.bidId, + id: bidRequest.bidId, imp: buildRequestImpression(bidRequest, bidderRequest), site: buildRequestSite(bidRequest), device: buildRequestDevice() @@ -107,7 +114,7 @@ function buildRequest(bidRequest, bidderRequest) { deepSetValue(openrtbRequest, 'regs.ext.us_privacy', bidderRequest.uspConsent); } - return JSON.stringify(openrtbRequest);; + return JSON.stringify(openrtbRequest); } function buildRequestImpression(bidRequest) { @@ -115,15 +122,16 @@ function buildRequestImpression(bidRequest) { const impressionObject = { id: bidRequest.adUnitCode, - secure: isSecure() ? 1 : 0 }; impressionObject.video = buildImpressionVideo(bidRequest); const bidFloorData = buildBidFloorData(bidRequest); - impressionObject.bidfloor = bidFloorData.floor; - impressionObject.bidfloorcur = bidFloorData.currency; - + if (bidFloorData) { + impressionObject.bidfloor = bidFloorData.floor; + impressionObject.bidfloorcur = bidFloorData.currency; + } + impressionObject.ext = buildImpressionExtension(bidRequest); impressions.push(impressionObject); @@ -156,18 +164,19 @@ function buildImpressionExtension(bidRequest) { function buildBidFloorData(bidRequest) { const {params} = bidRequest; - // Bid Floor - const bidFloorRequest = { - currency: params.currency || 'USD', - mediaType: 'video', - size: '*' - }; + const currency = params.currency || 'USD'; let floorData; if (isFn(bidRequest.getFloor)) { + // Bid Floor + const bidFloorRequest = { + currency: currency, + mediaType: 'video', + size: '*' + }; floorData = bidRequest.getFloor(bidFloorRequest); } else if (params.bidfloor) { - floorData = {floor: params.bidfloor, currency: params.currency || 'USD'}; + floorData = {floor: params.bidfloor, currency: currency}; } return floorData; @@ -184,22 +193,9 @@ function buildRequestSite(bidRequest) { // Site Content if (videoParams.content && isPlainObject(videoParams.content)) { - openrtbRequest.site.content = {}; - const contentStringKeys = ['id', 'title', 'series', 'season', 'genre', 'contentrating', 'language', 'url']; - const contentNumberkeys = ['episode', 'prodq', 'context', 'livestream', 'len']; - const contentArrayKeys = ['cat']; - const contentObjectKeys = ['ext']; - for (const contentKey in videoBidderParams.content) { - if ( - (contentStringKeys.indexOf(contentKey) > -1 && isStr(videoParams.content[contentKey])) || - (contentNumberkeys.indexOf(contentKey) > -1 && isNumber(videoParams.content[contentKey])) || - (contentObjectKeys.indexOf(contentKey) > -1 && isPlainObject(videoParams.content[contentKey])) || - (contentArrayKeys.indexOf(contentKey) > -1 && isArray(videoParams.content[contentKey]) && - videoParams.content[contentKey].every(catStr => isStr(catStr)))) { - site.content[contentKey] = videoParams.content[contentKey]; - } else { - logMessage('JWPlayer bid adapter validation error: ', contentKey, ' is either not supported is OpenRTB V2.5 or value is undefined'); - } + site.content = {}; + for (const contentKey in videoParams.content) { + site.content[contentKey] = videoParams.content[contentKey]; } } return site; @@ -207,8 +203,7 @@ function buildRequestSite(bidRequest) { function buildRequestDevice() { return { - ua: navigator.userAgent, - ip: '' + ua: navigator.userAgent }; } diff --git a/test/spec/modules/jwplayerBidAdapter_spec.js b/test/spec/modules/jwplayerBidAdapter_spec.js index 5abf6b7e8c7..62e34c32b47 100644 --- a/test/spec/modules/jwplayerBidAdapter_spec.js +++ b/test/spec/modules/jwplayerBidAdapter_spec.js @@ -6,6 +6,14 @@ describe('jwplayer adapter tests', function() { var sandbox, clock, frozenNow = new Date(); beforeEach(function() { + this.defaultBidderRequest = { + 'gdprConsent': { + 'consentString': '', + 'gdprApplies': true + }, + 'uspConsent': true + } + sandbox = sinon.sandbox.create(); clock = sinon.useFakeTimers(frozenNow.getTime()); }); @@ -37,7 +45,61 @@ describe('jwplayer adapter tests', function() { }); }); - describe('buildRequests for video', function() {}); + describe('buildRequests for video', function() { + it('buildRequests works', function() { + const bidRequests = [ + { + 'bidder': 'jwplayer', + 'params': { + 'placementId': 12345 + }, + 'mediaTypes': { + 'video': { + 'playerSize': [640, 480], + 'content': {} + } + }, + 'bidRequestsCount': 1, + 'adUnitCode': 'testAdUnitCode', + 'bidId': 'testBidId' + } + ] + + const serverRequests = spec.buildRequests(bidRequests, this.defaultBidderRequest); + + /* eslint-disable no-console */ + + serverRequests.forEach(serverRequest => { + expect(serverRequest.url).to.have.string('https://ib.adnxs.com/openrtb2/prebid'); + expect(serverRequest.method).to.equal('POST'); + + const openrtbRequest = JSON.parse(serverRequest.data); + console.log(openrtbRequest); + expect(openrtbRequest.id).to.not.equal(null); + expect(openrtbRequest.id).to.have.string('testBidId'); + + expect(openrtbRequest.site).to.not.equal(null); + expect(openrtbRequest.device).to.not.equal(null); + expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); + + expect(openrtbRequest.imp).to.not.equal(null); + expect(openrtbRequest.imp[0]).to.not.equal(null); + expect(openrtbRequest.imp[0].video).to.not.equal(null); + expect(openrtbRequest.imp[0].ext).to.not.equal(null); + expect(openrtbRequest.imp[0].ext.appnexus).to.not.equal(null); + expect(openrtbRequest.imp[0].ext.appnexus.placement_id).to.not.equal(null); + expect(openrtbRequest.imp[0].ext.appnexus.placement_id).to.equal(12345); + + expect(openrtbRequest.user).to.not.equal(null); + expect(openrtbRequest.user.ext).to.not.equal(null); + + expect(openrtbRequest.regs).to.not.equal(null); + expect(openrtbRequest.regs.ext).to.not.equal(null); + expect(openrtbRequest.regs.ext.gdpr).to.equal(1); + expect(openrtbRequest.regs.ext.us_privacy).to.equal(true); + }) + }); + }); describe('interpretResponse for video', function() {}); From 913c588816e39b9c07d49af36e7a5cd57d8bab1a Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Thu, 2 Jun 2022 19:16:46 -0400 Subject: [PATCH 07/15] removed superfluous array --- modules/jwplayerBidAdapter.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 17b2e83ff34..f6421b3a0f1 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -118,8 +118,6 @@ function buildRequest(bidRequest, bidderRequest) { } function buildRequestImpression(bidRequest) { - const impressions = []; - const impressionObject = { id: bidRequest.adUnitCode, }; @@ -134,9 +132,7 @@ function buildRequestImpression(bidRequest) { impressionObject.ext = buildImpressionExtension(bidRequest); - impressions.push(impressionObject); - - return impressions; + return [impressionObject]; } function buildImpressionVideo(bidRequest) { From c56819daea71f0de7a1909ea637680bb4c4a3421 Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Tue, 7 Jun 2022 14:50:06 -0400 Subject: [PATCH 08/15] fixed nits --- modules/jwplayerBidAdapter.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index f6421b3a0f1..f1283e50b58 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -95,7 +95,6 @@ export const spec = { }; function buildRequest(bidRequest, bidderRequest) { - // Open RTB Request Object const openrtbRequest = { id: bidRequest.bidId, imp: buildRequestImpression(bidRequest, bidderRequest), @@ -140,7 +139,6 @@ function buildImpressionVideo(bidRequest) { const video = {}; - // Obtain all ORTB params related video from Ad Unit VIDEO_ORTB_PARAMS.forEach((param) => { if (videoParams.hasOwnProperty(param)) { video[param] = videoParams[param]; @@ -164,10 +162,9 @@ function buildBidFloorData(bidRequest) { let floorData; if (isFn(bidRequest.getFloor)) { - // Bid Floor const bidFloorRequest = { currency: currency, - mediaType: 'video', + mediaType: VIDEO, size: '*' }; floorData = bidRequest.getFloor(bidFloorRequest); From 6090353e160f89e305fd3e1fdb3bad550eba9c39 Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Wed, 8 Jun 2022 14:50:10 -0400 Subject: [PATCH 09/15] added feedback to jw adapter and tests for buildRequests --- modules/jwplayerBidAdapter.js | 24 ++++++++------------ test/spec/modules/jwplayerBidAdapter_spec.js | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index f1283e50b58..7fe74dec7ee 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -1,15 +1,11 @@ -// import * as utils from 'src/utils'; import { registerBidder } from '../src/adapters/bidderFactory.js'; -// import { config } from 'src/config'; import { VIDEO } from '../src/mediaTypes.js'; -import { isStr, +import { isPlainObject, - isNumber, - isArray, isFn, deepAccess, - deepSetValue, - logMessage } from '../src/utils.js'; + deepSetValue } from '../src/utils.js'; +import { config } from '../src/config.js'; const BIDDER_CODE = 'jwplayer'; const URL = 'https://ib.adnxs.com/openrtb2/prebid'; @@ -176,19 +172,19 @@ function buildBidFloorData(bidRequest) { } function buildRequestSite(bidRequest) { + const configSite = config.getConfig('ortb2.site'); + const site = { - domain: window.location.hostname, - page: window.location.href, + domain: (configSite && configSite.domain) ? configSite.domain : window.location.hostname, + page: (configSite && configSite.page) ? configSite.page : window.location.href, ref: bidRequest.refererInfo ? bidRequest.refererInfo.referer || null : null }; - const videoParams = deepAccess(bidRequest, 'mediaTypes.video', {}); - // Site Content - if (videoParams.content && isPlainObject(videoParams.content)) { + if (configSite && configSite.content && isPlainObject(configSite.content)) { site.content = {}; - for (const contentKey in videoParams.content) { - site.content[contentKey] = videoParams.content[contentKey]; + for (const contentKey in configSite.content) { + site.content[contentKey] = configSite.content[contentKey]; } } return site; diff --git a/test/spec/modules/jwplayerBidAdapter_spec.js b/test/spec/modules/jwplayerBidAdapter_spec.js index 62e34c32b47..5b461e952c3 100644 --- a/test/spec/modules/jwplayerBidAdapter_spec.js +++ b/test/spec/modules/jwplayerBidAdapter_spec.js @@ -74,7 +74,7 @@ describe('jwplayer adapter tests', function() { expect(serverRequest.method).to.equal('POST'); const openrtbRequest = JSON.parse(serverRequest.data); - console.log(openrtbRequest); + expect(openrtbRequest.id).to.not.equal(null); expect(openrtbRequest.id).to.have.string('testBidId'); From fd5a3dd2619bde9276b73150a4ebf50b5f0dc638 Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Fri, 10 Jun 2022 14:58:13 -0400 Subject: [PATCH 10/15] added feedback --- modules/jwplayerBidAdapter.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 7fe74dec7ee..fb9e8b24ace 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -172,20 +172,18 @@ function buildBidFloorData(bidRequest) { } function buildRequestSite(bidRequest) { - const configSite = config.getConfig('ortb2.site'); + const configSite = config.getConfig('ortb2.site') || {}; const site = { - domain: (configSite && configSite.domain) ? configSite.domain : window.location.hostname, - page: (configSite && configSite.page) ? configSite.page : window.location.href, + domain: config.publisherDomain || configSite.domain || window.location.hostname, + page: config.pageUrl || configSite.page || window.location.href, ref: bidRequest.refererInfo ? bidRequest.refererInfo.referer || null : null }; // Site Content if (configSite && configSite.content && isPlainObject(configSite.content)) { site.content = {}; - for (const contentKey in configSite.content) { - site.content[contentKey] = configSite.content[contentKey]; - } + site.content = configSite.content; } return site; } From da4edf4912d00b40a3e11ad2a19f9e32efb4899c Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Fri, 10 Jun 2022 16:28:31 -0400 Subject: [PATCH 11/15] one last feedback for request site --- modules/jwplayerBidAdapter.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index fb9e8b24ace..20df594fe28 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -177,12 +177,15 @@ function buildRequestSite(bidRequest) { const site = { domain: config.publisherDomain || configSite.domain || window.location.hostname, page: config.pageUrl || configSite.page || window.location.href, - ref: bidRequest.refererInfo ? bidRequest.refererInfo.referer || null : null }; + const referer = bidRequest.refererInfo && bidRequest.refererInfo.referer; + if (referer) { + site.ref = referer; + } + // Site Content if (configSite && configSite.content && isPlainObject(configSite.content)) { - site.content = {}; site.content = configSite.content; } return site; From 7587eb323a74b05c473a682e3f26aafd2c6743be Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Fri, 10 Jun 2022 16:38:39 -0400 Subject: [PATCH 12/15] added site object unit test --- modules/jwplayerBidAdapter.js | 2 +- test/spec/modules/jwplayerBidAdapter_spec.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 20df594fe28..0649e6c6dfd 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -181,7 +181,7 @@ function buildRequestSite(bidRequest) { const referer = bidRequest.refererInfo && bidRequest.refererInfo.referer; if (referer) { - site.ref = referer; + site.ref = referer; } // Site Content diff --git a/test/spec/modules/jwplayerBidAdapter_spec.js b/test/spec/modules/jwplayerBidAdapter_spec.js index 5b461e952c3..8bd0cc7a01e 100644 --- a/test/spec/modules/jwplayerBidAdapter_spec.js +++ b/test/spec/modules/jwplayerBidAdapter_spec.js @@ -79,6 +79,7 @@ describe('jwplayer adapter tests', function() { expect(openrtbRequest.id).to.have.string('testBidId'); expect(openrtbRequest.site).to.not.equal(null); + expect(openrtbRequest.site).to.be.an('object'); expect(openrtbRequest.device).to.not.equal(null); expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); From 0e084df8ee842ee665e0853161b3fbe141e8f0ed Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Mon, 20 Jun 2022 16:50:27 -0400 Subject: [PATCH 13/15] fixed buildRequestSite object --- modules/jwplayerBidAdapter.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 0649e6c6dfd..a66e6e7276d 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -172,22 +172,16 @@ function buildBidFloorData(bidRequest) { } function buildRequestSite(bidRequest) { - const configSite = config.getConfig('ortb2.site') || {}; + const site = config.getConfig('ortb2.site') || {}; - const site = { - domain: config.publisherDomain || configSite.domain || window.location.hostname, - page: config.pageUrl || configSite.page || window.location.href, - }; + site.domain = site.domain || config.publisherDomain || window.location.hostname; + site.page = site.page || config.pageUrl || window.location.href; const referer = bidRequest.refererInfo && bidRequest.refererInfo.referer; - if (referer) { + if (!site.ref && referer) { site.ref = referer; } - // Site Content - if (configSite && configSite.content && isPlainObject(configSite.content)) { - site.content = configSite.content; - } return site; } From 9aea3bcdae2dffaeeb720600abad798b1864722e Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Mon, 20 Jun 2022 17:47:43 -0400 Subject: [PATCH 14/15] added unit tests for site object --- modules/jwplayerBidAdapter.js | 3 +- test/spec/modules/jwplayerBidAdapter_spec.js | 35 ++++++++++++++------ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index a66e6e7276d..2bd13a41d37 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -1,7 +1,6 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { VIDEO } from '../src/mediaTypes.js'; import { - isPlainObject, isFn, deepAccess, deepSetValue } from '../src/utils.js'; @@ -172,7 +171,9 @@ function buildBidFloorData(bidRequest) { } function buildRequestSite(bidRequest) { + /* eslint-disable no-console */ const site = config.getConfig('ortb2.site') || {}; + console.log(site); site.domain = site.domain || config.publisherDomain || window.location.hostname; site.page = site.page || config.pageUrl || window.location.href; diff --git a/test/spec/modules/jwplayerBidAdapter_spec.js b/test/spec/modules/jwplayerBidAdapter_spec.js index 8bd0cc7a01e..d4fa08d29d3 100644 --- a/test/spec/modules/jwplayerBidAdapter_spec.js +++ b/test/spec/modules/jwplayerBidAdapter_spec.js @@ -3,24 +3,17 @@ import { spec } from 'modules/jwplayerBidAdapter.js'; import { config } from 'src/config.js'; describe('jwplayer adapter tests', function() { - var sandbox, clock, frozenNow = new Date(); - beforeEach(function() { this.defaultBidderRequest = { 'gdprConsent': { 'consentString': '', 'gdprApplies': true }, - 'uspConsent': true + 'uspConsent': true, + 'refererInfo': { + 'referer': 'https://example.com' + } } - - sandbox = sinon.sandbox.create(); - clock = sinon.useFakeTimers(frozenNow.getTime()); - }); - - afterEach(function() { - sandbox.restore(); - clock.restore(); }); describe('isBidRequestValid', function() { @@ -65,6 +58,19 @@ describe('jwplayer adapter tests', function() { } ] + let sandbox = sinon.sandbox.create(); + sandbox.stub(config, 'getConfig').callsFake((key) => { + const config = { + 'ortb2': { + site: { + domain: 'page.example.com', + page: 'https://examplepage.com' + } + } + }; + return config[key]; + }) + const serverRequests = spec.buildRequests(bidRequests, this.defaultBidderRequest); /* eslint-disable no-console */ @@ -80,6 +86,13 @@ describe('jwplayer adapter tests', function() { expect(openrtbRequest.site).to.not.equal(null); expect(openrtbRequest.site).to.be.an('object'); + expect(openrtbRequest.site.domain).to.be.a('string'); + expect(openrtbRequest.site.domain).to.equal('page.example.com'); + expect(openrtbRequest.site.page).to.be.a('string'); + expect(openrtbRequest.site.page).to.equal('https://examplepage.com'); + expect(openrtbRequest.site.ref).to.be.a('string'); + expect(openrtbRequest.site.ref).to.equal('https://example.com'); + expect(openrtbRequest.device).to.not.equal(null); expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); From dc2e4db85e9c19cf5f195edfbd0b97ef67888615 Mon Sep 17 00:00:00 2001 From: Jorge Rocha Date: Tue, 28 Jun 2022 17:18:58 -0400 Subject: [PATCH 15/15] fixed unit tests for buildRequestSite --- modules/jwplayerBidAdapter.js | 8 +++---- test/spec/modules/jwplayerBidAdapter_spec.js | 22 +++++++++----------- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/modules/jwplayerBidAdapter.js b/modules/jwplayerBidAdapter.js index 2bd13a41d37..21c68b1f712 100644 --- a/modules/jwplayerBidAdapter.js +++ b/modules/jwplayerBidAdapter.js @@ -93,7 +93,7 @@ function buildRequest(bidRequest, bidderRequest) { const openrtbRequest = { id: bidRequest.bidId, imp: buildRequestImpression(bidRequest, bidderRequest), - site: buildRequestSite(bidRequest), + site: buildRequestSite(bidderRequest), device: buildRequestDevice() }; @@ -170,15 +170,13 @@ function buildBidFloorData(bidRequest) { return floorData; } -function buildRequestSite(bidRequest) { - /* eslint-disable no-console */ +function buildRequestSite(bidderRequest) { const site = config.getConfig('ortb2.site') || {}; - console.log(site); site.domain = site.domain || config.publisherDomain || window.location.hostname; site.page = site.page || config.pageUrl || window.location.href; - const referer = bidRequest.refererInfo && bidRequest.refererInfo.referer; + const referer = bidderRequest.refererInfo && bidderRequest.refererInfo.referer; if (!site.ref && referer) { site.ref = referer; } diff --git a/test/spec/modules/jwplayerBidAdapter_spec.js b/test/spec/modules/jwplayerBidAdapter_spec.js index d4fa08d29d3..9f443e62654 100644 --- a/test/spec/modules/jwplayerBidAdapter_spec.js +++ b/test/spec/modules/jwplayerBidAdapter_spec.js @@ -61,20 +61,16 @@ describe('jwplayer adapter tests', function() { let sandbox = sinon.sandbox.create(); sandbox.stub(config, 'getConfig').callsFake((key) => { const config = { - 'ortb2': { - site: { - domain: 'page.example.com', - page: 'https://examplepage.com' - } + 'ortb2.site': { + domain: 'page.example.com', + page: 'https://examplepage.com' } }; return config[key]; - }) + }); const serverRequests = spec.buildRequests(bidRequests, this.defaultBidderRequest); - /* eslint-disable no-console */ - serverRequests.forEach(serverRequest => { expect(serverRequest.url).to.have.string('https://ib.adnxs.com/openrtb2/prebid'); expect(serverRequest.method).to.equal('POST'); @@ -87,11 +83,11 @@ describe('jwplayer adapter tests', function() { expect(openrtbRequest.site).to.not.equal(null); expect(openrtbRequest.site).to.be.an('object'); expect(openrtbRequest.site.domain).to.be.a('string'); - expect(openrtbRequest.site.domain).to.equal('page.example.com'); + expect(openrtbRequest.site.domain).to.have.string('page.example.com'); expect(openrtbRequest.site.page).to.be.a('string'); - expect(openrtbRequest.site.page).to.equal('https://examplepage.com'); + expect(openrtbRequest.site.page).to.have.string('https://examplepage.com'); expect(openrtbRequest.site.ref).to.be.a('string'); - expect(openrtbRequest.site.ref).to.equal('https://example.com'); + expect(openrtbRequest.site.ref).to.have.string('https://example.com'); expect(openrtbRequest.device).to.not.equal(null); expect(openrtbRequest.device.ua).to.equal(navigator.userAgent); @@ -111,7 +107,9 @@ describe('jwplayer adapter tests', function() { expect(openrtbRequest.regs.ext).to.not.equal(null); expect(openrtbRequest.regs.ext.gdpr).to.equal(1); expect(openrtbRequest.regs.ext.us_privacy).to.equal(true); - }) + }); + + sandbox.restore(); }); });