From 10a1d53216b48da17386aecf75a75498a0814bc1 Mon Sep 17 00:00:00 2001 From: karimJWP Date: Thu, 22 Oct 2020 17:56:45 -0400 Subject: [PATCH 1/5] reads jwTargeting from fpd --- .../gpt/jwplayerRtdProvider_example.html | 17 ++- modules/jwplayerRtdProvider.js | 7 +- test/spec/modules/jwplayerRtdProvider_spec.js | 103 ++++++++++++++---- 3 files changed, 99 insertions(+), 28 deletions(-) diff --git a/integrationExamples/gpt/jwplayerRtdProvider_example.html b/integrationExamples/gpt/jwplayerRtdProvider_example.html index e47f3ca45ec..c85a549dbcf 100644 --- a/integrationExamples/gpt/jwplayerRtdProvider_example.html +++ b/integrationExamples/gpt/jwplayerRtdProvider_example.html @@ -11,11 +11,18 @@ var adUnits = [{ code: 'div-gpt-ad-1460505748561-0', - jwTargeting: { - // Note: the following Ids are placeholders and should be replaced with your Ids. - playerID: '123', - mediaID: 'abc' + fpd: { + context: { + data: { + jwTargeting: { + // Note: the following Ids are placeholders and should be replaced with your Ids. + playerID: '123', + mediaID: 'abc' + } + }, + } }, + mediaTypes: { banner: { sizes: [[300, 250], [300,600]], @@ -45,7 +52,7 @@ pbjs.que.push(function() { pbjs.setConfig({ realTimeData: { - auctionDelay: 5000, + auctionDelay: 500, dataProviders: [{ name: "jwplayer", waitForIt: true, diff --git a/modules/jwplayerRtdProvider.js b/modules/jwplayerRtdProvider.js index 2262d39ff3a..ea781641cab 100644 --- a/modules/jwplayerRtdProvider.js +++ b/modules/jwplayerRtdProvider.js @@ -144,6 +144,7 @@ function enrichBidRequest(bidReqConfig, onDone) { * @param {function} onDone */ export function enrichAdUnits(adUnits) { + const jwTargetingFallback = config.getConfig('fpd.context.data.jwTargeting'); adUnits.forEach(adUnit => { const onVatResponse = function (vat) { if (!vat) { @@ -153,12 +154,14 @@ export function enrichAdUnits(adUnits) { addTargetingToBids(adUnit.bids, targeting); }; - loadVat(adUnit.jwTargeting, onVatResponse); + const adUnitTargeting = adUnit.fpd && adUnit.fpd.context && adUnit.fpd.context.data && adUnit.fpd.context.data.jwTargeting; + const jwTargeting = Object.assign({}, jwTargetingFallback, adUnitTargeting); + loadVat(jwTargeting, onVatResponse); }); } function loadVat(params, onCompletion) { - if (!params) { + if (!params || !Object.keys(params).length) { return; } diff --git a/test/spec/modules/jwplayerRtdProvider_spec.js b/test/spec/modules/jwplayerRtdProvider_spec.js index 6e301e2a5a6..8cb2436c6f0 100644 --- a/test/spec/modules/jwplayerRtdProvider_spec.js +++ b/test/spec/modules/jwplayerRtdProvider_spec.js @@ -1,7 +1,8 @@ -import { fetchTargetingForMediaId, enrichBidRequest, - getVatFromCache, formatTargetingResponse, getVatFromPlayer, enrichAdUnits, +import { fetchTargetingForMediaId, getVatFromCache, + formatTargetingResponse, getVatFromPlayer, enrichAdUnits, fetchTargetingInformation, jwplayerSubmodule } from 'modules/jwplayerRtdProvider.js'; import { server } from 'test/mocks/xhr.js'; +import { config } from 'src/config.js'; describe('jwplayerRtdProvider', function() { const testIdForSuccess = 'test_id_for_success'; @@ -229,9 +230,15 @@ describe('jwplayerRtdProvider', function() { const bid = {}; const adUnit = { - jwTargeting: { - mediaID: mediaIdWithSegment, - playerID: validPlayerID + fpd: { + context: { + data: { + jwTargeting: { + mediaID: mediaIdWithSegment, + playerID: validPlayerID + } + } + } }, bids: [ bid @@ -292,8 +299,14 @@ describe('jwplayerRtdProvider', function() { } ]; const adUnit = { - jwTargeting: { - mediaID: testIdForSuccess + fpd: { + context: { + data: { + jwTargeting: { + mediaID: testIdForSuccess + } + } + } }, bids }; @@ -333,8 +346,14 @@ describe('jwplayerRtdProvider', function() { } ]; const adUnit = { - jwTargeting: { - mediaID: testIdForSuccess + fpd: { + context: { + data: { + jwTargeting: { + mediaID: testIdForSuccess + } + } + } }, bids }; @@ -374,8 +393,14 @@ describe('jwplayerRtdProvider', function() { } ]; const adUnit = { - jwTargeting: { - mediaID: testIdForFailure + fpd: { + context: { + data: { + jwTargeting: { + mediaID: testIdForFailure + } + } + } }, bids }; @@ -404,16 +429,28 @@ describe('jwplayerRtdProvider', function() { bidReqConfig = { adUnits: [ { - jwTargeting: { - mediaID: validMediaIDs[0] + fpd: { + context: { + data: { + jwTargeting: { + mediaID: validMediaIDs[0] + } + } + } }, bids: [ {}, {} ] }, { - jwTargeting: { - mediaID: validMediaIDs[1] + fpd: { + context: { + data: { + jwTargeting: { + mediaID: validMediaIDs[1] + } + } + } }, bids: [ {}, {} @@ -473,8 +510,14 @@ describe('jwplayerRtdProvider', function() { it('sets targeting data in proper structure', function () { const bid = {}; const adUnitWithMediaId = { - jwTargeting: { - mediaID: testIdForSuccess + fpd: { + context: { + data: { + jwTargeting: { + mediaID: testIdForSuccess + } + } + } }, bids: [ bid @@ -499,12 +542,18 @@ describe('jwplayerRtdProvider', function() { const adUnitCode = 'test_ad_unit'; const bid = {}; const adUnit = { - jwTargeting: { - mediaID: testIdForFailure + fpd: { + context: { + data: { + jwTargeting: { + mediaID: testIdForFailure + } + } + } }, bids: [ bid ] }; - const expectedContentId = 'jw_' + adUnit.jwTargeting.mediaID; + const expectedContentId = 'jw_' + adUnit.fpd.context.data.jwTargeting.mediaID; const expectedTargeting = { content: { id: expectedContentId @@ -522,6 +571,7 @@ describe('jwplayerRtdProvider', function() { const adUnitCode = 'test_ad_unit'; const bid1 = {}; const bid2 = {}; + const bid3 = {}; const adUnitWithMediaId = { code: adUnitCode, mediaID: testIdForSuccess, @@ -532,10 +582,21 @@ describe('jwplayerRtdProvider', function() { bids: [ bid2 ] }; - jwplayerSubmodule.getBidRequestData({ adUnits: [adUnitWithMediaId, adUnitEmpty] }, bidRequestSpy); + const adUnitEmptyfpd = { + code: 'test_ad_unit_empty_fpd', + fpd: { + context: { + id: 'sthg' + } + }, + bids: [ bid3 ] + }; + + jwplayerSubmodule.getBidRequestData({ adUnits: [adUnitWithMediaId, adUnitEmpty, adUnitEmptyfpd] }, bidRequestSpy); expect(bidRequestSpy.calledOnce).to.be.true; expect(bid1).to.not.have.property('jwTargeting'); expect(bid2).to.not.have.property('jwTargeting'); + expect(bid3).to.not.have.property('jwTargeting'); }); }); }); From 77878bbc9edc6638efcd7ccd92b2fbf0c0a4724b Mon Sep 17 00:00:00 2001 From: karimJWP Date: Thu, 22 Oct 2020 18:44:30 -0400 Subject: [PATCH 2/5] refactors param extraction --- modules/jwplayerRtdProvider.js | 13 +++-- test/spec/modules/jwplayerRtdProvider_spec.js | 47 ++++++++++++++++++- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/modules/jwplayerRtdProvider.js b/modules/jwplayerRtdProvider.js index ea781641cab..17cb978aea3 100644 --- a/modules/jwplayerRtdProvider.js +++ b/modules/jwplayerRtdProvider.js @@ -144,7 +144,7 @@ function enrichBidRequest(bidReqConfig, onDone) { * @param {function} onDone */ export function enrichAdUnits(adUnits) { - const jwTargetingFallback = config.getConfig('fpd.context.data.jwTargeting'); + const fpdFallback = config.getConfig('fpd.context.data.jwTargeting'); adUnits.forEach(adUnit => { const onVatResponse = function (vat) { if (!vat) { @@ -154,12 +154,19 @@ export function enrichAdUnits(adUnits) { addTargetingToBids(adUnit.bids, targeting); }; - const adUnitTargeting = adUnit.fpd && adUnit.fpd.context && adUnit.fpd.context.data && adUnit.fpd.context.data.jwTargeting; - const jwTargeting = Object.assign({}, jwTargetingFallback, adUnitTargeting); + const jwTargeting = extractPublisherParams(adUnit, fpdFallback); loadVat(jwTargeting, onVatResponse); }); } +export function extractPublisherParams(adUnit, fallback) { + let adUnitTargeting; + try { + adUnitTargeting = adUnit.fpd.context.data.jwTargeting; + } catch (e) {} + return Object.assign({}, fallback, adUnitTargeting); +} + function loadVat(params, onCompletion) { if (!params || !Object.keys(params).length) { return; diff --git a/test/spec/modules/jwplayerRtdProvider_spec.js b/test/spec/modules/jwplayerRtdProvider_spec.js index 8cb2436c6f0..6e0fd8eb8d7 100644 --- a/test/spec/modules/jwplayerRtdProvider_spec.js +++ b/test/spec/modules/jwplayerRtdProvider_spec.js @@ -1,8 +1,7 @@ -import { fetchTargetingForMediaId, getVatFromCache, +import { fetchTargetingForMediaId, getVatFromCache, extractPublisherParams, formatTargetingResponse, getVatFromPlayer, enrichAdUnits, fetchTargetingInformation, jwplayerSubmodule } from 'modules/jwplayerRtdProvider.js'; import { server } from 'test/mocks/xhr.js'; -import { config } from 'src/config.js'; describe('jwplayerRtdProvider', function() { const testIdForSuccess = 'test_id_for_success'; @@ -413,6 +412,50 @@ describe('jwplayerRtdProvider', function() { }); }); + describe(' Extract Publisher Params', function () { + it('should default to config', function () { + const config = { mediaID: 'test' }; + + const adUnit1 = { fpd: { context: {} } }; + const targeting1 = extractPublisherParams(adUnit1, config); + expect(targeting1).to.deep.equal(config); + + const adUnit2 = { fpd: { context: { data: { jwTargeting: {} } } } }; + const targeting2 = extractPublisherParams(adUnit2, config); + expect(targeting2).to.deep.equal(config); + + const targeting3 = extractPublisherParams(null, config); + expect(targeting3).to.deep.equal(config); + }); + + it('should prioritize adUnit properties ', function () { + const expectedMediaID = 'test_media_id'; + const expectedPlayerID = 'test_player_id'; + const config = { playerID: 'bad_id', mediaID: 'bad_id' }; + + const adUnit = { fpd: { context: { data: { jwTargeting: { mediaID: expectedMediaID, playerID: expectedPlayerID } } } } }; + const targeting = extractPublisherParams(adUnit, config); + expect(targeting).to.have.property('mediaID', expectedMediaID); + expect(targeting).to.have.property('playerID', expectedPlayerID); + }); + + it('should use config properties as fallbacks', function () { + const expectedMediaID = 'test_media_id'; + const expectedPlayerID = 'test_player_id'; + const config = { playerID: expectedPlayerID, mediaID: 'bad_id' }; + + const adUnit = { fpd: { context: { data: { jwTargeting: { mediaID: expectedMediaID } } } } }; + const targeting = extractPublisherParams(adUnit, config); + expect(targeting).to.have.property('mediaID', expectedMediaID); + expect(targeting).to.have.property('playerID', expectedPlayerID); + }); + + it('should return empty object when Publisher Params are absent', function () { + const targeting = extractPublisherParams(null, null); + expect(targeting).to.deep.equal({}); + }) + }); + describe('jwplayerSubmodule', function () { it('successfully instantiates', function () { expect(jwplayerSubmodule.init()).to.equal(true); From 88e5f28bfe121e6dce81d01d67fe585356f37ce0 Mon Sep 17 00:00:00 2001 From: karimJWP Date: Fri, 23 Oct 2020 11:03:11 -0400 Subject: [PATCH 3/5] updates documentation --- modules/jwplayerRtdProvider.md | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/modules/jwplayerRtdProvider.md b/modules/jwplayerRtdProvider.md index 83e1a4d7772..417e0fcc50b 100644 --- a/modules/jwplayerRtdProvider.md +++ b/modules/jwplayerRtdProvider.md @@ -25,16 +25,22 @@ pbjs.setConfig({ } }); ``` -Lastly, include the content's media ID and/or the player's ID in the matching AdUnit: +Lastly, include the content's media ID and/or the player's ID in the matching AdUnit's `fpd.context.data`: ```javascript const adUnit = { code: '/19968336/prebid_native_example_1', ... - jwTargeting: { - waitForIt: true, - playerID: 'abcd', - mediaID: '1234' + fpd: { + context: { + data: { + jwTargeting: { + // Note: the following Ids are placeholders and should be replaced with your Ids. + playerID: 'abcd', + mediaID: '1234' + } + } + } } }; @@ -46,33 +52,23 @@ pbjs.que.push(function() { }); ``` ##Prefetching -In order to prefetch targeting information for certain media, include the media IDs in the `jwplayerDataProvider` var: +In order to prefetch targeting information for certain media, include the media IDs in the `jwplayerDataProvider` var and set `waitForIt` to `true`: ```javascript const jwplayerDataProvider = { name: "jwplayer", + waitForIt: true, params: { mediaIDs: ['abc', 'def', 'ghi', 'jkl'] } }; ``` -To ensure that the prefetched targeting information is added to your bid, we strongly suggest setting -`jwTargeting.waitForIt` to `true`. If the prefetch is still in progress at the time of the bid request, the auction will -be delayed until the targeting information specific to the requested adUnits has been obtained. - -```javascript -jwTargeting: { - waitForIt: true, - ... -} -``` - You must also set a value to `auctionDelay` in the config's `realTimeData` object ```javascript realTimeData = { - auctionDelay: 1000, + auctionDelay: 500, ... }; ``` From 0f747accf23632160b248435df2a37979d3c906c Mon Sep 17 00:00:00 2001 From: karimJWP Date: Fri, 23 Oct 2020 11:24:16 -0400 Subject: [PATCH 4/5] mentions support of config fpd --- modules/jwplayerRtdProvider.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/jwplayerRtdProvider.md b/modules/jwplayerRtdProvider.md index 417e0fcc50b..07af04d8b76 100644 --- a/modules/jwplayerRtdProvider.md +++ b/modules/jwplayerRtdProvider.md @@ -51,6 +51,9 @@ pbjs.que.push(function() { }); }); ``` + +**Note**: You may also include `jwTargeting` information in the prebid config's `fpd.context.data`. Information provided in the adUnit will always supersede, and information in the config will be used as a fallback. + ##Prefetching In order to prefetch targeting information for certain media, include the media IDs in the `jwplayerDataProvider` var and set `waitForIt` to `true`: From bf65043180391ca6b0808d0cefaac909eb201191 Mon Sep 17 00:00:00 2001 From: karimJWP Date: Fri, 23 Oct 2020 11:28:54 -0400 Subject: [PATCH 5/5] reduces auction delay examples --- integrationExamples/gpt/jwplayerRtdProvider_example.html | 2 +- modules/jwplayerRtdProvider.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/integrationExamples/gpt/jwplayerRtdProvider_example.html b/integrationExamples/gpt/jwplayerRtdProvider_example.html index c85a549dbcf..75eb85a2d8c 100644 --- a/integrationExamples/gpt/jwplayerRtdProvider_example.html +++ b/integrationExamples/gpt/jwplayerRtdProvider_example.html @@ -52,7 +52,7 @@ pbjs.que.push(function() { pbjs.setConfig({ realTimeData: { - auctionDelay: 500, + auctionDelay: 100, dataProviders: [{ name: "jwplayer", waitForIt: true, diff --git a/modules/jwplayerRtdProvider.md b/modules/jwplayerRtdProvider.md index 07af04d8b76..3c83b6f521c 100644 --- a/modules/jwplayerRtdProvider.md +++ b/modules/jwplayerRtdProvider.md @@ -71,7 +71,7 @@ You must also set a value to `auctionDelay` in the config's `realTimeData` objec ```javascript realTimeData = { - auctionDelay: 500, + auctionDelay: 100, ... }; ```