From 5b534be06889409d347784179a7ec8821f4fce8f Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Thu, 11 Jan 2024 10:32:32 +0100 Subject: [PATCH 01/23] Dailymotion Bid Adaptor: initial release --- modules/dailymotionBidAdapter.js | 55 +++++++ modules/dailymotionBidAdapter.md | 73 +++++++++ .../modules/dailymotionBidAdapter_spec.js | 148 ++++++++++++++++++ 3 files changed, 276 insertions(+) create mode 100644 modules/dailymotionBidAdapter.js create mode 100644 modules/dailymotionBidAdapter.md create mode 100644 test/spec/modules/dailymotionBidAdapter_spec.js diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js new file mode 100644 index 00000000000..fe1c91b9226 --- /dev/null +++ b/modules/dailymotionBidAdapter.js @@ -0,0 +1,55 @@ +import { config } from '../src/config.js'; +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { VIDEO } from '../src/mediaTypes.js'; + +export const spec = { + code: 'dailymotion', + gvlid: 573, + supportedMediaTypes: [VIDEO], + + /** + * Determines whether or not the given bid request is valid. + * The only mandatory parameters for a bid to be valid are the api_key and position configuration entries. + * Other parameters are optional. + * + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: () => { + const dmConfig = config.getConfig('dailymotion'); + return !!(dmConfig?.api_key && dmConfig?.position); + }, + + /** + * Make a server request from the list of valid BidRequests (that already passed the isBidRequestValid call) + * + * @param {BidRequest[]} validBidRequests A non-empty list of valid bid requests that should be sent to the Server. + * @param {BidderRequest} bidderRequest + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: (validBidRequests = [], bidderRequest) => validBidRequests.map(bid => ({ + method: 'POST', + url: 'https://pb.dmxleo.com', + data: { + bidder_request: bidderRequest, + config: config.getConfig('dailymotion'), + coppa: config.getConfig('coppa'), + request: bid, + }, + options: { + withCredentials: true, + crossOrigin: true + }, + })), + + /** + * Map the response from the server into a list of bids. + * As dailymotion prebid server returns an entry with the correct Prebid structure, + * we directly include it as the only bid in the response. + * + * @param {*} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: serverResponse => serverResponse?.body ? [serverResponse.body] : [], +}; + +registerBidder(spec); diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md new file mode 100644 index 00000000000..a54b76f052d --- /dev/null +++ b/modules/dailymotionBidAdapter.md @@ -0,0 +1,73 @@ +# Overview + +``` +Module Name: Dailymotion Bid Adapter +Module Type: Bidder Adapter +Maintainer: ad-leo-engineering@dailymotion.com +``` + +# Description + +Dailymotion prebid adapter. + +# Configuration options + +Before calling this adapter, you need to set its configuration with a call to setConfig like this: + +``` +config.setConfig({ + dailymotion: { + api_key: 'test_api_key', + position: 'test_position', + xid: 'x123456' + } +}); +``` + +This call must be made before each auction. Here's a description of each parameter: +* `api_key` is your publisher API key. For testing purpose, you can use "dailymotion-testing". +* `position` parameter is the ad position in the video and must either be "preroll", "midroll" or "postroll". +* `xid` is the Dailymotion video identifier and should be provided to have better contextual data and higher fillrate. + +# Test Parameters + +By setting the following configuration options, you'll get a constant response to any request to validate your adapter integration: + +``` +config.setConfig({ + dailymotion: { + api_key: 'dailymotion-testing', + position: 'preroll' + } +}); +``` + +Please note that failing to set these configuration options will result in the adapter not bidding at all. + +# Sample video AdUnit + +``` +const adUnits = [ + { + code: 'test-ad-unit', + mediaTypes: { + video: { + context: 'instream', + playerSize: [1280, 720], + }, + }, + bids: [{ + bidder: "dailymotion", + params: {} + }] + } +]; +``` + +# Integrating the adapter + +To use the adapter with any non-test request, you first need to ask an API key from Dailymotion. Please contact us through **DailymotionPrebid.js@dailymotion.com**. + +You will then be able to use it within the `config` before making a bid request. + +This API key will ensure proper identification of your inventory and allow you to get real bids. diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js new file mode 100644 index 00000000000..a4452c1dccc --- /dev/null +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -0,0 +1,148 @@ +import { config } from 'src/config.js'; +import { expect } from 'chai'; +import { spec } from 'modules/dailymotionBidAdapter.js'; + +describe('dailymotionBidAdapterTests', () => { + // Validate that isBidRequestValid only validates requests + // with both api_key and position config parameters set + it('validates isBidRequestValid', () => { + config.setConfig({ dailymotion: {} }); + expect(spec.isBidRequestValid({ + bidder: 'dailymotion', + })).to.be.false; + + config.setConfig({ dailymotion: { api_key: 'test_api_key' } }); + expect(spec.isBidRequestValid({ + bidder: 'dailymotion', + })).to.be.false; + + config.setConfig({ dailymotion: { position: 'test_position' } }); + expect(spec.isBidRequestValid({ + bidder: 'dailymotion', + })).to.be.false; + + config.setConfig({ dailymotion: { api_key: 'test_api_key', position: 'test_position' } }); + expect(spec.isBidRequestValid({ + bidder: 'dailymotion', + })).to.be.true; + }); + + // Validate request generation with api key & position only + it('validates buildRequests - with api key & position', () => { + const dmConfig = { api_key: 'test_api_key', position: 'test_position' }; + + config.setConfig({ + dailymotion: dmConfig, + coppa: true, + }); + + const bidRequestData = [{ + adUnitCode: 'test_adunitcode', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: 123456, + bidder: 'dailymotion', + }]; + + const bidderRequestData = { + uspConsent: '1YN-', + gdprConsent: { + consentString: 'xxx', + gdprApplies: 1 + }, + }; + + const [request] = spec.buildRequests(bidRequestData, bidderRequestData); + const { data: reqData } = request; + + expect(request.url).to.equal('https://pb.dmxleo.com'); + expect(reqData.bidder_request).to.equal(bidderRequestData) + expect(reqData.config).to.equal(dmConfig); + expect(reqData.coppa).to.be.true; + expect(reqData.request).to.equal(bidRequestData[0]); + }); + + // Validate request generation with api key, position, xid + it('validates buildRequests - with auth & xid', function () { + const dmConfig = { + api_key: 'test_api_key', + position: 'test_position', + xid: 'x123456', + }; + + config.setConfig({ dailymotion: dmConfig }); + + const bidRequestData = [{ + adUnitCode: 'test_adunitcode', + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: 123456, + bidder: 'dailymotion', + }]; + + const bidderRequestData = { + uspConsent: '1YN-', + gdprConsent: { + consentString: 'xxx', + gdprApplies: 1 + }, + }; + + const [request] = spec.buildRequests(bidRequestData, bidderRequestData); + const { data: reqData } = request; + + expect(request.url).to.equal('https://pb.dmxleo.com'); + expect(reqData.bidder_request).to.equal(bidderRequestData) + expect(reqData.config).to.equal(dmConfig); + expect(reqData.coppa).to.equal(true); + expect(reqData.request).to.equal(bidRequestData[0]); + }); + + it('validates buildRequests - with empty/undefined validBidRequests', function () { + const dmConfig = { + api_key: 'test_api_key', + position: 'test_position', + xid: 'x123456', + }; + + config.setConfig({ dailymotion: dmConfig }); + + expect(spec.buildRequests([], {})).to.have.lengthOf(0); + + expect(spec.buildRequests(undefined, {})).to.have.lengthOf(0); + }); + + it('validates interpretResponse', function () { + const serverResponse = { + body: { + ad: 'https://fakecacheserver/cache?uuid=1234', + cacheId: '1234', + cpm: 20.0, + creativeId: '5678', + currency: 'USD', + dealId: 'deal123', + nurl: 'https://bid/nurl', + requestId: 'test_requestid', + vastUrl: 'https://fakecacheserver/cache?uuid=1234', + }, + }; + + const bids = spec.interpretResponse(serverResponse); + expect(bids).to.have.lengthOf(1); + + const [bid] = bids; + expect(bid.ad).to.equal(serverResponse.body.ad); + expect(bid.cacheId).to.equal(serverResponse.body.cacheId); + expect(bid.cpm).to.equal(serverResponse.body.cpm); + expect(bid.creativeId).to.equal(serverResponse.body.creativeId); + expect(bid.currency).to.equal(serverResponse.body.currency); + expect(bid.dealId).to.equal(serverResponse.body.dealId); + expect(bid.nurl).to.equal(serverResponse.body.nurl); + expect(bid.requestId).to.equal(serverResponse.body.requestId); + expect(bid.vastUrl).to.equal(serverResponse.body.vastUrl); + }); + + it('validates interpretResponse - with empty/undefined serverResponse', function () { + expect(spec.interpretResponse({})).to.have.lengthOf(0); + + expect(spec.interpretResponse(undefined)).to.have.lengthOf(0); + }); +}); From 807c75bce31223fd872b13bbb19d193ea24a79ff Mon Sep 17 00:00:00 2001 From: Aditi Chaudhary Date: Mon, 22 Jan 2024 17:56:53 +0100 Subject: [PATCH 02/23] .md file lint issue resolved --- modules/dailymotionBidAdapter.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index a54b76f052d..7323dfe6d9c 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -14,7 +14,7 @@ Dailymotion prebid adapter. Before calling this adapter, you need to set its configuration with a call to setConfig like this: -``` +```javascript config.setConfig({ dailymotion: { api_key: 'test_api_key', @@ -25,6 +25,7 @@ config.setConfig({ ``` This call must be made before each auction. Here's a description of each parameter: + * `api_key` is your publisher API key. For testing purpose, you can use "dailymotion-testing". * `position` parameter is the ad position in the video and must either be "preroll", "midroll" or "postroll". * `xid` is the Dailymotion video identifier and should be provided to have better contextual data and higher fillrate. @@ -33,7 +34,7 @@ This call must be made before each auction. Here's a description of each paramet By setting the following configuration options, you'll get a constant response to any request to validate your adapter integration: -``` +```javascript config.setConfig({ dailymotion: { api_key: 'dailymotion-testing', @@ -46,7 +47,7 @@ Please note that failing to set these configuration options will result in the a # Sample video AdUnit -``` +```javascript const adUnits = [ { code: 'test-ad-unit', From 6c25624cbebc2087ca6ad01391eb43662ea39182 Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Wed, 31 Jan 2024 10:39:24 +0100 Subject: [PATCH 03/23] Dailymotion Bid Adaptor: build bidder request based on param with fallbacks --- modules/dailymotionBidAdapter.js | 24 +++- .../modules/dailymotionBidAdapter_spec.js | 115 ++++++++++++++---- 2 files changed, 110 insertions(+), 29 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index fe1c91b9226..42e3f2a141e 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -30,10 +30,30 @@ export const spec = { method: 'POST', url: 'https://pb.dmxleo.com', data: { - bidder_request: bidderRequest, + bidder_request: { + gdprConsent: { + apiVersion: bidderRequest?.gdprConsent?.apiVersion || 1, + consentString: bidderRequest?.gdprConsent?.consentString || '', + // Cast boolean in any case (eg: if value is int) to ensure type + gdprApplies: !!bidderRequest?.gdprConsent?.gdprApplies, + }, + refererInfo: { + page: bidderRequest?.refererInfo?.page || '', + }, + uspConsent: bidderRequest?.uspConsent || '', + }, config: config.getConfig('dailymotion'), coppa: config.getConfig('coppa'), - request: bid, + request: { + auctionId: bid.auctionId || '', + bidId: bid.bidId || '', + mediaTypes: { + video: { + playerSize: bid.mediaTypes?.[VIDEO]?.playerSize || [], + }, + }, + sizes: bid.sizes || [], + }, }, options: { withCredentials: true, diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index a4452c1dccc..e333e870d7d 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -1,6 +1,7 @@ import { config } from 'src/config.js'; import { expect } from 'chai'; import { spec } from 'modules/dailymotionBidAdapter.js'; +import { VIDEO } from '../../../src/mediaTypes'; describe('dailymotionBidAdapterTests', () => { // Validate that isBidRequestValid only validates requests @@ -37,17 +38,25 @@ describe('dailymotionBidAdapterTests', () => { }); const bidRequestData = [{ - adUnitCode: 'test_adunitcode', auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, - bidder: 'dailymotion', + mediaTypes: { + video: { + playerSize: [[1280, 720]], + }, + }, + sizes: [[1920, 1080]], }]; const bidderRequestData = { + refererInfo: { + page: 'https://publisher.com', + }, uspConsent: '1YN-', gdprConsent: { + apiVersion: 2, consentString: 'xxx', - gdprApplies: 1 + gdprApplies: true, }, }; @@ -55,34 +64,44 @@ describe('dailymotionBidAdapterTests', () => { const { data: reqData } = request; expect(request.url).to.equal('https://pb.dmxleo.com'); - expect(reqData.bidder_request).to.equal(bidderRequestData) - expect(reqData.config).to.equal(dmConfig); + + expect(reqData.config).to.eql(dmConfig); expect(reqData.coppa).to.be.true; - expect(reqData.request).to.equal(bidRequestData[0]); + + expect(reqData.bidder_request).to.eql(bidderRequestData) + expect(reqData.request).to.eql(bidRequestData[0]); }); // Validate request generation with api key, position, xid - it('validates buildRequests - with auth & xid', function () { + it('validates buildRequests - with auth & xid', () => { const dmConfig = { api_key: 'test_api_key', position: 'test_position', xid: 'x123456', }; - config.setConfig({ dailymotion: dmConfig }); + config.setConfig({ dailymotion: dmConfig, coppa: undefined }); const bidRequestData = [{ - adUnitCode: 'test_adunitcode', auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, - bidder: 'dailymotion', + mediaTypes: { + video: { + playerSize: [[1280, 720]], + }, + }, + sizes: [[1920, 1080]], }]; const bidderRequestData = { + refererInfo: { + page: 'https://publisher.com', + }, uspConsent: '1YN-', gdprConsent: { + apiVersion: 2, consentString: 'xxx', - gdprApplies: 1 + gdprApplies: 1, }, }; @@ -90,13 +109,63 @@ describe('dailymotionBidAdapterTests', () => { const { data: reqData } = request; expect(request.url).to.equal('https://pb.dmxleo.com'); - expect(reqData.bidder_request).to.equal(bidderRequestData) - expect(reqData.config).to.equal(dmConfig); - expect(reqData.coppa).to.equal(true); - expect(reqData.request).to.equal(bidRequestData[0]); + + expect(reqData.config).to.eql(dmConfig); + expect(reqData.coppa).to.be.undefined; + + expect(reqData.bidder_request).to.eql({ + ...bidderRequestData, + gdprConsent: { + ...bidderRequestData.gdprConsent, + gdprApplies: true, // Verify cast to boolean + }, + }); + + expect(reqData.request).to.eql(bidRequestData[0]); + }); + + it('validates buildRequests - with default values on empty bid & bidder request', () => { + const dmConfig = { + api_key: 'test_api_key', + position: 'test_position', + xid: 'x123456', + }; + + config.setConfig({ dailymotion: dmConfig, coppa: false }); + + const [request] = spec.buildRequests([{}], {}); + const { data: reqData } = request; + + expect(request.url).to.equal('https://pb.dmxleo.com'); + + expect(reqData.config).to.eql(dmConfig); + expect(reqData.coppa).to.be.false; + + expect(reqData.bidder_request).to.eql({ + gdprConsent: { + apiVersion: 1, + consentString: '', + gdprApplies: false, + }, + refererInfo: { + page: '', + }, + uspConsent: '', + }); + + expect(reqData.request).to.eql({ + auctionId: '', + bidId: '', + mediaTypes: { + video: { + playerSize: [], + }, + }, + sizes: [], + }); }); - it('validates buildRequests - with empty/undefined validBidRequests', function () { + it('validates buildRequests - with empty/undefined validBidRequests', () => { const dmConfig = { api_key: 'test_api_key', position: 'test_position', @@ -110,7 +179,7 @@ describe('dailymotionBidAdapterTests', () => { expect(spec.buildRequests(undefined, {})).to.have.lengthOf(0); }); - it('validates interpretResponse', function () { + it('validates interpretResponse', () => { const serverResponse = { body: { ad: 'https://fakecacheserver/cache?uuid=1234', @@ -129,18 +198,10 @@ describe('dailymotionBidAdapterTests', () => { expect(bids).to.have.lengthOf(1); const [bid] = bids; - expect(bid.ad).to.equal(serverResponse.body.ad); - expect(bid.cacheId).to.equal(serverResponse.body.cacheId); - expect(bid.cpm).to.equal(serverResponse.body.cpm); - expect(bid.creativeId).to.equal(serverResponse.body.creativeId); - expect(bid.currency).to.equal(serverResponse.body.currency); - expect(bid.dealId).to.equal(serverResponse.body.dealId); - expect(bid.nurl).to.equal(serverResponse.body.nurl); - expect(bid.requestId).to.equal(serverResponse.body.requestId); - expect(bid.vastUrl).to.equal(serverResponse.body.vastUrl); + expect(bid).to.eql(serverResponse.body); }); - it('validates interpretResponse - with empty/undefined serverResponse', function () { + it('validates interpretResponse - with empty/undefined serverResponse', () => { expect(spec.interpretResponse({})).to.have.lengthOf(0); expect(spec.interpretResponse(undefined)).to.have.lengthOf(0); From 9aab2ea8c4d09d4931194441481595a8598f4ed2 Mon Sep 17 00:00:00 2001 From: Aditi Chaudhary Date: Fri, 16 Feb 2024 15:23:06 +0100 Subject: [PATCH 04/23] Dailymotion Bid Adaptor: support video metadata --- modules/dailymotionBidAdapter.js | 38 +++- modules/dailymotionBidAdapter.md | 72 ++++++-- .../modules/dailymotionBidAdapter_spec.js | 170 ++++++++---------- 3 files changed, 168 insertions(+), 112 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 42e3f2a141e..5cde05c217c 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -1,6 +1,38 @@ import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { VIDEO } from '../src/mediaTypes.js'; +import { deepAccess } from '../src/utils.js'; + +/** + * Get video metadata from bid request + * + * @param {BidRequest} bidRequest A valid bid requests that should be sent to the Server. + * @return video metadata + */ +function getVideoMetadata(bidRequest) { + const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); + const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); + + const videoParams = { + ...videoAdUnit, + ...videoBidderParams, // Bidder Specific overrides + }; + + const videoMetadata = { + description: videoParams.description || '', + duration: videoParams.duration || 0, + iabcat2: videoParams.iabcat2 || '', + id: videoParams.id || '', + lang: videoParams.lang || '', + private: videoParams.private || false, + tags: videoParams.tags || '', + title: videoParams.title || '', + topics: videoParams.topics || '', + xid: videoParams.xid || '', + }; + + return videoMetadata; +} export const spec = { code: 'dailymotion', @@ -16,7 +48,7 @@ export const spec = { */ isBidRequestValid: () => { const dmConfig = config.getConfig('dailymotion'); - return !!(dmConfig?.api_key && dmConfig?.position); + return !!dmConfig?.api_key; }, /** @@ -50,14 +82,16 @@ export const spec = { mediaTypes: { video: { playerSize: bid.mediaTypes?.[VIDEO]?.playerSize || [], + api: bid.mediaTypes?.[VIDEO]?.api || [], }, }, sizes: bid.sizes || [], }, + video_metadata: getVideoMetadata(bid), }, options: { withCredentials: true, - crossOrigin: true + crossOrigin: true, }, })), diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index 7323dfe6d9c..2d67ad7f62d 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -12,34 +12,35 @@ Dailymotion prebid adapter. # Configuration options -Before calling this adapter, you need to set its configuration with a call to setConfig like this: +Before calling this adapter, you need to set its configuration with a call like this: ```javascript -config.setConfig({ - dailymotion: { - api_key: 'test_api_key', - position: 'test_position', - xid: 'x123456' - } +pbjs.setBidderConfig({ + bidders: ["dailymotion"], + config: { + dailymotion: { + api_key: 'fake_api_key', + } + } }); ``` -This call must be made before each auction. Here's a description of each parameter: +This call must be made before the first auction to allow proper authentication with our servers. -* `api_key` is your publisher API key. For testing purpose, you can use "dailymotion-testing". -* `position` parameter is the ad position in the video and must either be "preroll", "midroll" or "postroll". -* `xid` is the Dailymotion video identifier and should be provided to have better contextual data and higher fillrate. +`api_key` is your publisher API key. For testing purpose, you can use "dailymotion-testing". # Test Parameters By setting the following configuration options, you'll get a constant response to any request to validate your adapter integration: ```javascript -config.setConfig({ - dailymotion: { - api_key: 'dailymotion-testing', - position: 'preroll' - } +pbjs.setBidderConfig({ + bidders: ["dailymotion"], + config: { + dailymotion: { + api_key: 'dailymotion-testing' + } + } }); ``` @@ -55,16 +56,53 @@ const adUnits = [ video: { context: 'instream', playerSize: [1280, 720], + api: [2,7], + description: 'this is a video description', + duration: 556, + iabcat2: 'test_cat', + id: '54321', + lang: 'FR', + private: false, + tags: 'tag_1,tag_2,tag_3', + title: 'test video', + topics: 'topic_1, topic_2', + xid: 'x123456' }, }, bids: [{ bidder: "dailymotion", - params: {} + params: { + video: { + description: 'this is a test video description', + duration: 330, + iabcat2: 'test_cat', + id: '54321', + lang: 'FR', + private: false, + tags: 'tag_1,tag_2,tag_3', + title: 'test video', + topics: 'topic_1, topic_2, topic_3', + xid: 'x123456' + } + } }] } ]; ``` +Following video metadata fields can be added in mediaTypes.video or bids.params.video. If a field exists in both places, it will be overridden by bids.params.video. + +* `description` - Video description +* `duration` - Video duration in seconds +* `iabcat2` - Video IAB category +* `id` - Video unique ID in host video infrastructure +* `lang` - ISO 639-1 code for main language used in the video +* `private` - True if video is not publicly available +* `tags` - Tags for the video, comma separated +* `title` - Video title +* `topics` - Main topics for the video, comma separated +* `xid` - Dailymotion video identifier (only applicable if using the Dailymotion player) and allows better targeting + # Integrating the adapter To use the adapter with any non-test request, you first need to ask an API key from Dailymotion. Please contact us through **DailymotionPrebid.js@dailymotion.com**. diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index e333e870d7d..9e5bfb049ef 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -4,48 +4,60 @@ import { spec } from 'modules/dailymotionBidAdapter.js'; import { VIDEO } from '../../../src/mediaTypes'; describe('dailymotionBidAdapterTests', () => { - // Validate that isBidRequestValid only validates requests - // with both api_key and position config parameters set + // Validate that isBidRequestValid only validates requests with api_key it('validates isBidRequestValid', () => { - config.setConfig({ dailymotion: {} }); - expect(spec.isBidRequestValid({ - bidder: 'dailymotion', - })).to.be.false; - - config.setConfig({ dailymotion: { api_key: 'test_api_key' } }); - expect(spec.isBidRequestValid({ - bidder: 'dailymotion', - })).to.be.false; - - config.setConfig({ dailymotion: { position: 'test_position' } }); - expect(spec.isBidRequestValid({ - bidder: 'dailymotion', - })).to.be.false; - - config.setConfig({ dailymotion: { api_key: 'test_api_key', position: 'test_position' } }); - expect(spec.isBidRequestValid({ - bidder: 'dailymotion', - })).to.be.true; + config.setBidderConfig({ + bidders: ['dailymotion'], + config: { dailymotion: {} }, + }); + + expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid())).to.be.false; + + config.setBidderConfig({ + bidders: ['dailymotion'], + config: { dailymotion: { api_key: 'test_api_key' } }, + }); + + expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid())).to.be.true; }); - // Validate request generation with api key & position only - it('validates buildRequests - with api key & position', () => { - const dmConfig = { api_key: 'test_api_key', position: 'test_position' }; + // Validate request generation + it('validates buildRequests', () => { + const dmConfig = { api_key: 'test_api_key' }; - config.setConfig({ - dailymotion: dmConfig, - coppa: true, + config.setBidderConfig({ + bidders: ['dailymotion'], + config: { dailymotion: dmConfig }, }); + config.setConfig({ coppa: true }); + const bidRequestData = [{ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, mediaTypes: { video: { playerSize: [[1280, 720]], + api: [2, 7], + description: 'this is a test video', + duration: 300, + iabcat2: 'test_cat', + lang: 'ENG', }, }, sizes: [[1920, 1080]], + params: { + video: { + duration: 556, + id: '54321', + lang: 'FR', + private: false, + tags: 'tag_1,tag_2,tag_3', + title: 'test video', + topics: 'topic_1, topic_2', + xid: 'x123456', + }, + }, }]; const bidderRequestData = { @@ -60,80 +72,52 @@ describe('dailymotionBidAdapterTests', () => { }, }; - const [request] = spec.buildRequests(bidRequestData, bidderRequestData); + const [request] = config.runWithBidder( + 'dailymotion', + () => spec.buildRequests(bidRequestData, bidderRequestData), + ); + const { data: reqData } = request; expect(request.url).to.equal('https://pb.dmxleo.com'); expect(reqData.config).to.eql(dmConfig); expect(reqData.coppa).to.be.true; - expect(reqData.bidder_request).to.eql(bidderRequestData) - expect(reqData.request).to.eql(bidRequestData[0]); + expect(reqData.request.auctionId).to.eql(bidRequestData[0].auctionId); + expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); + expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); + expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); + expect(reqData.video_metadata).to.eql({ + description: bidRequestData[0].mediaTypes.video.description, + iabcat2: bidRequestData[0].mediaTypes.video.iabcat2, + id: bidRequestData[0].params.video.id, + lang: bidRequestData[0].params.video.lang, + private: bidRequestData[0].params.video.private, + tags: bidRequestData[0].params.video.tags, + title: bidRequestData[0].params.video.title, + topics: bidRequestData[0].params.video.topics, + xid: bidRequestData[0].params.video.xid, + // Overriden through bidder params + duration: bidRequestData[0].params.video.duration, + }); }); - // Validate request generation with api key, position, xid - it('validates buildRequests - with auth & xid', () => { - const dmConfig = { - api_key: 'test_api_key', - position: 'test_position', - xid: 'x123456', - }; - - config.setConfig({ dailymotion: dmConfig, coppa: undefined }); - - const bidRequestData = [{ - auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', - bidId: 123456, - mediaTypes: { - video: { - playerSize: [[1280, 720]], - }, - }, - sizes: [[1920, 1080]], - }]; - - const bidderRequestData = { - refererInfo: { - page: 'https://publisher.com', - }, - uspConsent: '1YN-', - gdprConsent: { - apiVersion: 2, - consentString: 'xxx', - gdprApplies: 1, - }, - }; - - const [request] = spec.buildRequests(bidRequestData, bidderRequestData); - const { data: reqData } = request; - - expect(request.url).to.equal('https://pb.dmxleo.com'); - - expect(reqData.config).to.eql(dmConfig); - expect(reqData.coppa).to.be.undefined; + it('validates buildRequests - with default values on empty bid & bidder request', () => { + const dmConfig = { api_key: 'test_api_key' }; - expect(reqData.bidder_request).to.eql({ - ...bidderRequestData, - gdprConsent: { - ...bidderRequestData.gdprConsent, - gdprApplies: true, // Verify cast to boolean - }, + config.setBidderConfig({ + bidders: ['dailymotion'], + config: { dailymotion: dmConfig }, }); - expect(reqData.request).to.eql(bidRequestData[0]); - }); - - it('validates buildRequests - with default values on empty bid & bidder request', () => { - const dmConfig = { - api_key: 'test_api_key', - position: 'test_position', - xid: 'x123456', - }; + config.setConfig({ coppa: false }); - config.setConfig({ dailymotion: dmConfig, coppa: false }); + const [request] = config.runWithBidder( + 'dailymotion', + () => spec.buildRequests([{}], {}), + ); - const [request] = spec.buildRequests([{}], {}); const { data: reqData } = request; expect(request.url).to.equal('https://pb.dmxleo.com'); @@ -159,6 +143,7 @@ describe('dailymotionBidAdapterTests', () => { mediaTypes: { video: { playerSize: [], + api: [], }, }, sizes: [], @@ -166,13 +151,12 @@ describe('dailymotionBidAdapterTests', () => { }); it('validates buildRequests - with empty/undefined validBidRequests', () => { - const dmConfig = { - api_key: 'test_api_key', - position: 'test_position', - xid: 'x123456', - }; + const dmConfig = { api_key: 'test_api_key' }; - config.setConfig({ dailymotion: dmConfig }); + config.setBidderConfig({ + bidders: ['dailymotion'], + config: { dailymotion: dmConfig }, + }); expect(spec.buildRequests([], {})).to.have.lengthOf(0); From 32d6391d9d984feeefc26b6e548ac5d1b7241fcc Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Tue, 5 Mar 2024 18:43:25 +0100 Subject: [PATCH 05/23] Dailymotion Bid Adaptor: add support for sending adUnitCode --- modules/dailymotionBidAdapter.js | 1 + test/spec/modules/dailymotionBidAdapter_spec.js | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 5cde05c217c..2c0f5340e78 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -86,6 +86,7 @@ export const spec = { }, }, sizes: bid.sizes || [], + adUnitCode: bid.adUnitCode || '', }, video_metadata: getVideoMetadata(bid), }, diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index 9e5bfb049ef..c296a983f10 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -35,6 +35,7 @@ describe('dailymotionBidAdapterTests', () => { const bidRequestData = [{ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, + adUnitCode: 'preroll', mediaTypes: { video: { playerSize: [[1280, 720]], @@ -83,7 +84,7 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.config).to.eql(dmConfig); expect(reqData.coppa).to.be.true; - expect(reqData.bidder_request).to.eql(bidderRequestData) + expect(reqData.bidder_request).to.eql(bidderRequestData); expect(reqData.request.auctionId).to.eql(bidRequestData[0].auctionId); expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); @@ -140,6 +141,7 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request).to.eql({ auctionId: '', bidId: '', + adUnitCode: '', mediaTypes: { video: { playerSize: [], From ce0536ca2daf0b9cd7748e987a18736c483c71d5 Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Wed, 6 Mar 2024 14:21:45 +0100 Subject: [PATCH 06/23] Dailymotion Bid Adaptor: add support for sending startDelay --- modules/dailymotionBidAdapter.js | 1 + test/spec/modules/dailymotionBidAdapter_spec.js | 3 +++ 2 files changed, 4 insertions(+) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 2c0f5340e78..d31a2350733 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -83,6 +83,7 @@ export const spec = { video: { playerSize: bid.mediaTypes?.[VIDEO]?.playerSize || [], api: bid.mediaTypes?.[VIDEO]?.api || [], + startDelay: bid.mediaTypes?.[VIDEO]?.startdelay || 0, }, }, sizes: bid.sizes || [], diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index c296a983f10..0c3a8b17206 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -44,6 +44,7 @@ describe('dailymotionBidAdapterTests', () => { duration: 300, iabcat2: 'test_cat', lang: 'ENG', + startdelay: 0, }, }, sizes: [[1920, 1080]], @@ -89,6 +90,7 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); + expect(reqData.request.mediaTypes.video.startDelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); expect(reqData.video_metadata).to.eql({ description: bidRequestData[0].mediaTypes.video.description, iabcat2: bidRequestData[0].mediaTypes.video.iabcat2, @@ -145,6 +147,7 @@ describe('dailymotionBidAdapterTests', () => { mediaTypes: { video: { playerSize: [], + startDelay: 0, api: [], }, }, From 3092928d306094042ab792b79427b35b8b3ffd55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Millet?= Date: Tue, 19 Mar 2024 17:24:01 +0100 Subject: [PATCH 07/23] feat(LEO-528): Allow multiple IAB categories in video metadata The same way as we can have an array of IAB categories level 1 in the ORTB request, this PR introduces an array for the IAB categories level 2. To be forward compatible with level [2.2](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%202.2.tsv) and [3.0](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%203.0.tsv) specifications, the category IDs should be sent as strings. --- modules/dailymotionBidAdapter.js | 2 +- modules/dailymotionBidAdapter.md | 8 ++++---- test/spec/modules/dailymotionBidAdapter_spec.js | 15 ++++++++++++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index d31a2350733..78f955219e3 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -21,7 +21,7 @@ function getVideoMetadata(bidRequest) { const videoMetadata = { description: videoParams.description || '', duration: videoParams.duration || 0, - iabcat2: videoParams.iabcat2 || '', + iabcat2: Array.isArray(videoParams.iabcat2) ? videoParams.iabcat2 : [], id: videoParams.id || '', lang: videoParams.lang || '', private: videoParams.private || false, diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index 2d67ad7f62d..24034dedc56 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -59,7 +59,7 @@ const adUnits = [ api: [2,7], description: 'this is a video description', duration: 556, - iabcat2: 'test_cat', + iabcat2: ['6', '17'], id: '54321', lang: 'FR', private: false, @@ -75,7 +75,7 @@ const adUnits = [ video: { description: 'this is a test video description', duration: 330, - iabcat2: 'test_cat', + iabcat2: ['6', '17'], id: '54321', lang: 'FR', private: false, @@ -94,14 +94,14 @@ Following video metadata fields can be added in mediaTypes.video or bids.params. * `description` - Video description * `duration` - Video duration in seconds -* `iabcat2` - Video IAB category +* `iabcat2` - List of IAB category IDs from the [2.0 taxonomy](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%202.0.tsv) * `id` - Video unique ID in host video infrastructure * `lang` - ISO 639-1 code for main language used in the video * `private` - True if video is not publicly available * `tags` - Tags for the video, comma separated * `title` - Video title * `topics` - Main topics for the video, comma separated -* `xid` - Dailymotion video identifier (only applicable if using the Dailymotion player) and allows better targeting +* `xid` - Dailymotion video identifier (only applicable if using the Dailymotion player), allows better targeting # Integrating the adapter diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index 0c3a8b17206..b1fc1143ad3 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -42,7 +42,7 @@ describe('dailymotionBidAdapterTests', () => { api: [2, 7], description: 'this is a test video', duration: 300, - iabcat2: 'test_cat', + iabcat2: ['6', '17'], lang: 'ENG', startdelay: 0, }, @@ -153,6 +153,19 @@ describe('dailymotionBidAdapterTests', () => { }, sizes: [], }); + + expect(reqData.video_metadata).to.eql({ + description: '', + duration: 0, + iabcat2: [], + id: '', + lang: '', + private: false, + tags: '', + title: '', + topics: '', + xid: '', + }); }); it('validates buildRequests - with empty/undefined validBidRequests', () => { From 09f8e16c1627574a5561bde61bca245b793c8a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Millet?= Date: Wed, 27 Mar 2024 10:28:13 +0100 Subject: [PATCH 08/23] Dailymotion bid adapter: Clarify the video metadata to provide in each player context --- modules/dailymotionBidAdapter.md | 44 ++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index 24034dedc56..2fe6d4bdce2 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -48,6 +48,32 @@ Please note that failing to set these configuration options will result in the a # Sample video AdUnit +To allow better targeting, you should provide as much context about the video as possible. +There are two ways of doing this depending on if you're using Dailymotion player or a third party one. + +If you are using the Dailymotion player, you should only provide the video `xid` in your ad unit, example: + +```javascript +const adUnits = [ + { + code: 'test-ad-unit', + mediaTypes: { + video: { + context: 'instream', + playerSize: [1280, 720], + api: [2,7], + xid: 'x123456' + }, + } + } +]; +``` + +This will automatically fetch the most up-to-date information about the video. +If you provide any other metadata in addition to the `xid`, they will be ignored. + +If you are using a third party video player, you should not provide any `xid` and instead fill the following members: + ```javascript const adUnits = [ { @@ -66,23 +92,14 @@ const adUnits = [ tags: 'tag_1,tag_2,tag_3', title: 'test video', topics: 'topic_1, topic_2', - xid: 'x123456' }, }, bids: [{ bidder: "dailymotion", params: { video: { - description: 'this is a test video description', - duration: 330, - iabcat2: ['6', '17'], - id: '54321', - lang: 'FR', - private: false, - tags: 'tag_1,tag_2,tag_3', - title: 'test video', - topics: 'topic_1, topic_2, topic_3', - xid: 'x123456' + description: 'overriden video description', + duration: 330 } } }] @@ -90,7 +107,8 @@ const adUnits = [ ]; ``` -Following video metadata fields can be added in mediaTypes.video or bids.params.video. If a field exists in both places, it will be overridden by bids.params.video. +Each of the following video metadata fields can be added in mediaTypes.video or bids.params.video. +If a field exists in both places, it will be overridden by bids.params.video. * `description` - Video description * `duration` - Video duration in seconds @@ -101,7 +119,7 @@ Following video metadata fields can be added in mediaTypes.video or bids.params. * `tags` - Tags for the video, comma separated * `title` - Video title * `topics` - Main topics for the video, comma separated -* `xid` - Dailymotion video identifier (only applicable if using the Dailymotion player), allows better targeting +* `xid` - Dailymotion video identifier (only applicable if using the Dailymotion player) # Integrating the adapter From 898d8bbf2a487d23a4be9711c3b822297dcee708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Millet?= Date: Wed, 3 Apr 2024 17:58:54 +0200 Subject: [PATCH 09/23] Dailymotion bid adapter: Move API key to bid params --- modules/dailymotionBidAdapter.js | 13 ++--- modules/dailymotionBidAdapter.md | 86 ++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 78f955219e3..e7bdabb37c5 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -41,14 +41,13 @@ export const spec = { /** * Determines whether or not the given bid request is valid. - * The only mandatory parameters for a bid to be valid are the api_key and position configuration entries. + * The only mandatory parameter for a bid to be valid is the API key. * Other parameters are optional. * * @return boolean True if this is a valid bid, and false otherwise. */ - isBidRequestValid: () => { - const dmConfig = config.getConfig('dailymotion'); - return !!dmConfig?.api_key; + isBidRequestValid: function (bid) { + return (typeof bid.params.apiKey !== 'undefined'); }, /** @@ -74,9 +73,12 @@ export const spec = { }, uspConsent: bidderRequest?.uspConsent || '', }, - config: config.getConfig('dailymotion'), + config: { + api_key = bid.params.apiKey + }, coppa: config.getConfig('coppa'), request: { + adUnitCode: bid.adUnitCode || '', auctionId: bid.auctionId || '', bidId: bid.bidId || '', mediaTypes: { @@ -87,7 +89,6 @@ export const spec = { }, }, sizes: bid.sizes || [], - adUnitCode: bid.adUnitCode || '', }, video_metadata: getVideoMetadata(bid), }, diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index 2fe6d4bdce2..795273c9229 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -12,39 +12,41 @@ Dailymotion prebid adapter. # Configuration options -Before calling this adapter, you need to set its configuration with a call like this: +Before calling this adapter, you need to set at least the API key in the bid parameters: ```javascript -pbjs.setBidderConfig({ - bidders: ["dailymotion"], - config: { - dailymotion: { - api_key: 'fake_api_key', - } - } -}); +const adUnits = [ + { + bids: [{ + bidder: 'dailymotion', + params: { + apiKey: 'fake_api_key' + } + }] + } +]; ``` -This call must be made before the first auction to allow proper authentication with our servers. - -`api_key` is your publisher API key. For testing purpose, you can use "dailymotion-testing". +`apiKey` is your publisher API key. For testing purpose, you can use "dailymotion-testing". # Test Parameters -By setting the following configuration options, you'll get a constant response to any request to validate your adapter integration: +By setting the following bid parameters, you'll get a constant response to any request, to validate your adapter integration: ```javascript -pbjs.setBidderConfig({ - bidders: ["dailymotion"], - config: { - dailymotion: { - api_key: 'dailymotion-testing' - } - } -}); +const adUnits = [ + { + bids: [{ + bidder: 'dailymotion', + params: { + apiKey: 'dailymotion-testing' + } + }] + } +]; ``` -Please note that failing to set these configuration options will result in the adapter not bidding at all. +Please note that failing to set these will result in the adapter not bidding at all. # Sample video AdUnit @@ -56,13 +58,20 @@ If you are using the Dailymotion player, you should only provide the video `xid` ```javascript const adUnits = [ { + bids: [{ + bidder: 'dailymotion', + params: { + apiKey: 'dailymotion-testing' + } + }], code: 'test-ad-unit', mediaTypes: { video: { + api: [2, 7], context: 'instream', - playerSize: [1280, 720], - api: [2,7], - xid: 'x123456' + playerSize: [ [1280, 720] ], + startDelay: 0, + xid: 'x123456' // Dailymotion infrastructure unique video ID }, } } @@ -77,32 +86,33 @@ If you are using a third party video player, you should not provide any `xid` an ```javascript const adUnits = [ { + bids: [{ + bidder: 'dailymotion', + params: { + apiKey: 'dailymotion-testing', + video: { + description: 'overriden video description' + } + } + }], code: 'test-ad-unit', mediaTypes: { video: { + api: [2, 7], context: 'instream', - playerSize: [1280, 720], - api: [2,7], description: 'this is a video description', duration: 556, iabcat2: ['6', '17'], id: '54321', lang: 'FR', + playerSize: [ [1280, 720] ], private: false, + startDelay: 0, tags: 'tag_1,tag_2,tag_3', title: 'test video', topics: 'topic_1, topic_2', }, - }, - bids: [{ - bidder: "dailymotion", - params: { - video: { - description: 'overriden video description', - duration: 330 - } - } - }] + } } ]; ``` @@ -125,6 +135,6 @@ If a field exists in both places, it will be overridden by bids.params.video. To use the adapter with any non-test request, you first need to ask an API key from Dailymotion. Please contact us through **DailymotionPrebid.js@dailymotion.com**. -You will then be able to use it within the `config` before making a bid request. +You will then be able to use it within the bid parameters before making a bid request. This API key will ensure proper identification of your inventory and allow you to get real bids. From 673f831629352f3c3fd35d7db585c9afa535c914 Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Wed, 3 Apr 2024 19:10:59 +0200 Subject: [PATCH 10/23] Dailymotion bid adapter: Verify API key is string Co-authored-by: Rumesh --- modules/dailymotionBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index e7bdabb37c5..97d019bd5af 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -47,7 +47,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - return (typeof bid.params.apiKey !== 'undefined'); + return (typeof bid.params.apiKey === 'string'); }, /** From fbd456d2dc817f7c3854703e5854bc55d659a516 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Millet?= Date: Thu, 4 Apr 2024 15:01:29 +0200 Subject: [PATCH 11/23] Dailymotion bid adapter: Move API key to bid params (fix tests) --- modules/dailymotionBidAdapter.js | 4 +- .../modules/dailymotionBidAdapter_spec.js | 60 ++++++++----------- 2 files changed, 27 insertions(+), 37 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 97d019bd5af..b0411ccf2a5 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -47,7 +47,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - return (typeof bid.params.apiKey === 'string'); + return ((typeof bid !== 'undefined') && (typeof bid?.params?.apiKey === 'string') && (bid.params.apiKey.length > 10)); }, /** @@ -74,7 +74,7 @@ export const spec = { uspConsent: bidderRequest?.uspConsent || '', }, config: { - api_key = bid.params.apiKey + api_key: bid.params.apiKey }, coppa: config.getConfig('coppa'), request: { diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index b1fc1143ad3..f96364e7597 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -4,32 +4,29 @@ import { spec } from 'modules/dailymotionBidAdapter.js'; import { VIDEO } from '../../../src/mediaTypes'; describe('dailymotionBidAdapterTests', () => { - // Validate that isBidRequestValid only validates requests with api_key + // Validate that isBidRequestValid only validates requests with apiKey it('validates isBidRequestValid', () => { - config.setBidderConfig({ - bidders: ['dailymotion'], - config: { dailymotion: {} }, - }); - expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid())).to.be.false; - config.setBidderConfig({ - bidders: ['dailymotion'], - config: { dailymotion: { api_key: 'test_api_key' } }, - }); + const bidWithEmptyApi = { + params: { + apiKey: '', + }, + }; - expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid())).to.be.true; + expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid(bidWithEmptyApi))).to.be.false; + + const bidWithApi = { + params: { + apiKey: 'test_api_key', + }, + }; + + expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid(bidWithApi))).to.be.true; }); // Validate request generation it('validates buildRequests', () => { - const dmConfig = { api_key: 'test_api_key' }; - - config.setBidderConfig({ - bidders: ['dailymotion'], - config: { dailymotion: dmConfig }, - }); - config.setConfig({ coppa: true }); const bidRequestData = [{ @@ -49,6 +46,7 @@ describe('dailymotionBidAdapterTests', () => { }, sizes: [[1920, 1080]], params: { + apiKey: 'test_api_key', video: { duration: 556, id: '54321', @@ -83,9 +81,9 @@ describe('dailymotionBidAdapterTests', () => { expect(request.url).to.equal('https://pb.dmxleo.com'); - expect(reqData.config).to.eql(dmConfig); - expect(reqData.coppa).to.be.true; expect(reqData.bidder_request).to.eql(bidderRequestData); + expect(reqData.config.api_key).to.eql(bidRequestData[0].params.apiKey); + expect(reqData.coppa).to.be.true; expect(reqData.request.auctionId).to.eql(bidRequestData[0].auctionId); expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); @@ -107,25 +105,24 @@ describe('dailymotionBidAdapterTests', () => { }); it('validates buildRequests - with default values on empty bid & bidder request', () => { - const dmConfig = { api_key: 'test_api_key' }; - - config.setBidderConfig({ - bidders: ['dailymotion'], - config: { dailymotion: dmConfig }, - }); + const bidRequestDataWithApi = [{ + params: { + apiKey: 'test_api_key', + }, + }]; config.setConfig({ coppa: false }); const [request] = config.runWithBidder( 'dailymotion', - () => spec.buildRequests([{}], {}), + () => spec.buildRequests(bidRequestDataWithApi, {}), ); const { data: reqData } = request; expect(request.url).to.equal('https://pb.dmxleo.com'); - expect(reqData.config).to.eql(dmConfig); + expect(reqData.config.api_key).to.eql(bidRequestDataWithApi[0].params.apiKey); expect(reqData.coppa).to.be.false; expect(reqData.bidder_request).to.eql({ @@ -169,13 +166,6 @@ describe('dailymotionBidAdapterTests', () => { }); it('validates buildRequests - with empty/undefined validBidRequests', () => { - const dmConfig = { api_key: 'test_api_key' }; - - config.setBidderConfig({ - bidders: ['dailymotion'], - config: { dailymotion: dmConfig }, - }); - expect(spec.buildRequests([], {})).to.have.lengthOf(0); expect(spec.buildRequests(undefined, {})).to.have.lengthOf(0); From cc0c1bc133b66ff6d719b9e952f54ad1861b2350 Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Thu, 18 Apr 2024 09:27:00 +0200 Subject: [PATCH 12/23] Dailymotion Bid Adaptor: add gpp support and get coppa from request --- modules/dailymotionBidAdapter.js | 12 +- .../modules/dailymotionBidAdapter_spec.js | 115 +++++++++++++++++- 2 files changed, 119 insertions(+), 8 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index b0411ccf2a5..e7a5be56654 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -1,4 +1,3 @@ -import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { VIDEO } from '../src/mediaTypes.js'; import { deepAccess } from '../src/utils.js'; @@ -47,7 +46,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - return ((typeof bid !== 'undefined') && (typeof bid?.params?.apiKey === 'string') && (bid.params.apiKey.length > 10)); + return typeof bid?.params?.apiKey === 'string' && bid.params.apiKey.length > 10; }, /** @@ -72,11 +71,18 @@ export const spec = { page: bidderRequest?.refererInfo?.page || '', }, uspConsent: bidderRequest?.uspConsent || '', + gppConsent: { + gppString: deepAccess(bidderRequest, 'gppConsent.gppString') + || deepAccess(bidderRequest, 'ortb2.regs.gpp', ''), + applicableSections: deepAccess(bidderRequest, 'gppConsent.applicableSections') + || deepAccess(bidderRequest, 'ortb2.regs.gpp_sid', []), + }, }, config: { api_key: bid.params.apiKey }, - coppa: config.getConfig('coppa'), + // Cast boolean in any case (value should be 0 or 1) to ensure type + coppa: !!deepAccess(bidderRequest, 'ortb2.regs.coppa'), request: { adUnitCode: bid.adUnitCode || '', auctionId: bid.auctionId || '', diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index f96364e7597..8057a71755f 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -27,8 +27,6 @@ describe('dailymotionBidAdapterTests', () => { // Validate request generation it('validates buildRequests', () => { - config.setConfig({ coppa: true }); - const bidRequestData = [{ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, @@ -70,6 +68,15 @@ describe('dailymotionBidAdapterTests', () => { consentString: 'xxx', gdprApplies: true, }, + gppConsent: { + gppString: 'xxx', + applicableSections: [5], + }, + ortb2: { + regs: { + coppa: 1, + }, + }, }; const [request] = config.runWithBidder( @@ -81,7 +88,12 @@ describe('dailymotionBidAdapterTests', () => { expect(request.url).to.equal('https://pb.dmxleo.com'); - expect(reqData.bidder_request).to.eql(bidderRequestData); + expect(reqData.bidder_request).to.eql({ + refererInfo: bidderRequestData.refererInfo, + uspConsent: bidderRequestData.uspConsent, + gdprConsent: bidderRequestData.gdprConsent, + gppConsent: bidderRequestData.gppConsent, + }); expect(reqData.config.api_key).to.eql(bidRequestData[0].params.apiKey); expect(reqData.coppa).to.be.true; expect(reqData.request.auctionId).to.eql(bidRequestData[0].auctionId); @@ -104,6 +116,97 @@ describe('dailymotionBidAdapterTests', () => { }); }); + it('validates buildRequests with fallback values on ortb2 for gpp', () => { + const bidRequestData = [{ + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: 123456, + adUnitCode: 'preroll', + mediaTypes: { + video: { + playerSize: [[1280, 720]], + api: [2, 7], + description: 'this is a test video', + duration: 300, + iabcat2: ['6', '17'], + lang: 'ENG', + startdelay: 0, + }, + }, + sizes: [[1920, 1080]], + params: { + apiKey: 'test_api_key', + video: { + duration: 556, + id: '54321', + lang: 'FR', + private: false, + tags: 'tag_1,tag_2,tag_3', + title: 'test video', + topics: 'topic_1, topic_2', + xid: 'x123456', + }, + }, + }]; + + const bidderRequestData = { + refererInfo: { + page: 'https://publisher.com', + }, + uspConsent: '1YN-', + gdprConsent: { + apiVersion: 2, + consentString: 'xxx', + gdprApplies: true, + }, + ortb2: { + regs: { + gpp: 'xxx', + gpp_sid: [5], + coppa: 0, + }, + }, + }; + + const [request] = config.runWithBidder( + 'dailymotion', + () => spec.buildRequests(bidRequestData, bidderRequestData), + ); + + const { data: reqData } = request; + + expect(request.url).to.equal('https://pb.dmxleo.com'); + + expect(reqData.bidder_request).to.eql({ + refererInfo: bidderRequestData.refererInfo, + uspConsent: bidderRequestData.uspConsent, + gdprConsent: bidderRequestData.gdprConsent, + gppConsent: { + gppString: bidderRequestData.ortb2.regs.gpp, + applicableSections: bidderRequestData.ortb2.regs.gpp_sid, + }, + }); + expect(reqData.config.api_key).to.eql(bidRequestData[0].params.apiKey); + expect(reqData.coppa).to.be.false; + expect(reqData.request.auctionId).to.eql(bidRequestData[0].auctionId); + expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); + expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); + expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); + expect(reqData.request.mediaTypes.video.startDelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); + expect(reqData.video_metadata).to.eql({ + description: bidRequestData[0].mediaTypes.video.description, + iabcat2: bidRequestData[0].mediaTypes.video.iabcat2, + id: bidRequestData[0].params.video.id, + lang: bidRequestData[0].params.video.lang, + private: bidRequestData[0].params.video.private, + tags: bidRequestData[0].params.video.tags, + title: bidRequestData[0].params.video.title, + topics: bidRequestData[0].params.video.topics, + xid: bidRequestData[0].params.video.xid, + // Overriden through bidder params + duration: bidRequestData[0].params.video.duration, + }); + }); + it('validates buildRequests - with default values on empty bid & bidder request', () => { const bidRequestDataWithApi = [{ params: { @@ -111,8 +214,6 @@ describe('dailymotionBidAdapterTests', () => { }, }]; - config.setConfig({ coppa: false }); - const [request] = config.runWithBidder( 'dailymotion', () => spec.buildRequests(bidRequestDataWithApi, {}), @@ -135,6 +236,10 @@ describe('dailymotionBidAdapterTests', () => { page: '', }, uspConsent: '', + gppConsent: { + gppString: '', + applicableSections: [], + }, }); expect(reqData.request).to.eql({ From fa56a41f9789189e9312ba7b840bcd8a59877e94 Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Thu, 18 Apr 2024 15:03:50 +0200 Subject: [PATCH 13/23] Dailymotion Bid Adaptor: fix lint error --- modules/dailymotionBidAdapter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index e7a5be56654..f22471c3c4f 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -72,10 +72,10 @@ export const spec = { }, uspConsent: bidderRequest?.uspConsent || '', gppConsent: { - gppString: deepAccess(bidderRequest, 'gppConsent.gppString') - || deepAccess(bidderRequest, 'ortb2.regs.gpp', ''), - applicableSections: deepAccess(bidderRequest, 'gppConsent.applicableSections') - || deepAccess(bidderRequest, 'ortb2.regs.gpp_sid', []), + gppString: deepAccess(bidderRequest, 'gppConsent.gppString') || + deepAccess(bidderRequest, 'ortb2.regs.gpp', ''), + applicableSections: deepAccess(bidderRequest, 'gppConsent.applicableSections') || + deepAccess(bidderRequest, 'ortb2.regs.gpp_sid', []), }, }, config: { From 36637e0c02530c06d8577902b74580e7c03e59d8 Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Thu, 18 Apr 2024 16:28:45 +0200 Subject: [PATCH 14/23] Dailymotion Bid Adaptor: add iabcat1 and fallback to ortb2 for iabcat2 --- modules/dailymotionBidAdapter.js | 13 ++++++++++--- .../modules/dailymotionBidAdapter_spec.js | 19 ++++++++++++++++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index f22471c3c4f..ff8e52d6d11 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -8,7 +8,7 @@ import { deepAccess } from '../src/utils.js'; * @param {BidRequest} bidRequest A valid bid requests that should be sent to the Server. * @return video metadata */ -function getVideoMetadata(bidRequest) { +function getVideoMetadata(bidRequest, bidderRequest) { const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); @@ -20,7 +20,14 @@ function getVideoMetadata(bidRequest) { const videoMetadata = { description: videoParams.description || '', duration: videoParams.duration || 0, - iabcat2: Array.isArray(videoParams.iabcat2) ? videoParams.iabcat2 : [], + iabcat1: deepAccess(bidderRequest, 'ortb2.site.content.cat', []) + // Only take IAB cats of taxonomy V1 + .filter(cat => cat.toLowerCase().indexOf('iab-') === 0), + iabcat2: Array.isArray(videoParams.iabcat2) + ? videoParams.iabcat2 + // Only take IAB cats of taxonomy V2 or higher by excluding "IAB-" type categories + : deepAccess(bidderRequest, 'ortb2.site.content.cat', []) + .filter(cat => cat.toLowerCase().indexOf('iab-') !== 0), id: videoParams.id || '', lang: videoParams.lang || '', private: videoParams.private || false, @@ -96,7 +103,7 @@ export const spec = { }, sizes: bid.sizes || [], }, - video_metadata: getVideoMetadata(bid), + video_metadata: getVideoMetadata(bid, bidderRequest), }, options: { withCredentials: true, diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index 8057a71755f..e5a20fa6b6e 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -76,6 +76,11 @@ describe('dailymotionBidAdapterTests', () => { regs: { coppa: 1, }, + site: { + content: { + cat: ['IAB-1', '200'], + }, + }, }, }; @@ -103,6 +108,7 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.mediaTypes.video.startDelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); expect(reqData.video_metadata).to.eql({ description: bidRequestData[0].mediaTypes.video.description, + iabcat1: ['IAB-1'], // Taxonomy v2 or higher is excluded iabcat2: bidRequestData[0].mediaTypes.video.iabcat2, id: bidRequestData[0].params.video.id, lang: bidRequestData[0].params.video.lang, @@ -116,7 +122,7 @@ describe('dailymotionBidAdapterTests', () => { }); }); - it('validates buildRequests with fallback values on ortb2 for gpp', () => { + it('validates buildRequests with fallback values on ortb2 for gpp & iabcat', () => { const bidRequestData = [{ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, @@ -127,7 +133,6 @@ describe('dailymotionBidAdapterTests', () => { api: [2, 7], description: 'this is a test video', duration: 300, - iabcat2: ['6', '17'], lang: 'ENG', startdelay: 0, }, @@ -164,6 +169,11 @@ describe('dailymotionBidAdapterTests', () => { gpp_sid: [5], coppa: 0, }, + site: { + content: { + cat: ['6', '17'], + }, + }, }, }; @@ -194,7 +204,9 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.mediaTypes.video.startDelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); expect(reqData.video_metadata).to.eql({ description: bidRequestData[0].mediaTypes.video.description, - iabcat2: bidRequestData[0].mediaTypes.video.iabcat2, + // No iabcat1 here because nothing matches taxonomy + iabcat1: [], + iabcat2: bidderRequestData.ortb2.site.content.cat, id: bidRequestData[0].params.video.id, lang: bidRequestData[0].params.video.lang, private: bidRequestData[0].params.video.private, @@ -259,6 +271,7 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.video_metadata).to.eql({ description: '', duration: 0, + iabcat1: [], iabcat2: [], id: '', lang: '', From 50dda1fefe3db16212c8177346dd0251740b1a9f Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Thu, 18 Apr 2024 16:55:46 +0200 Subject: [PATCH 15/23] Dailymotion Bid Adaptor: get iabcats from ortb2.site.content.data --- modules/dailymotionBidAdapter.js | 26 +++++++-- .../modules/dailymotionBidAdapter_spec.js | 56 ++++++++++++++++++- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index ff8e52d6d11..2be5edad78e 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -17,17 +17,31 @@ function getVideoMetadata(bidRequest, bidderRequest) { ...videoBidderParams, // Bidder Specific overrides }; + // Store as object keys to ensure uniqueness + const iabcat1 = {}; + const iabcat2 = {}; + + deepAccess(bidderRequest, 'ortb2.site.content.data', []).forEach((data) => { + if ([4, 5, 6, 7].includes(data?.ext?.segtax)) { + (Array.isArray(data.segment) ? data.segment : []).forEach((segment) => { + if (typeof segment.id === 'string') { + // See https://docs.prebid.org/features/firstPartyData.html#segments-and-taxonomy + // Only take IAB cats of taxonomy V1 + if (data.ext.segtax === 4) iabcat1[segment.id] = 1; + // Only take IAB cats of taxonomy V2 or higher + if ([5, 6, 7].includes(data.ext.segtax)) iabcat2[segment.id] = 1; + } + }); + } + }); + const videoMetadata = { description: videoParams.description || '', duration: videoParams.duration || 0, - iabcat1: deepAccess(bidderRequest, 'ortb2.site.content.cat', []) - // Only take IAB cats of taxonomy V1 - .filter(cat => cat.toLowerCase().indexOf('iab-') === 0), + iabcat1: Object.keys(iabcat1), iabcat2: Array.isArray(videoParams.iabcat2) ? videoParams.iabcat2 - // Only take IAB cats of taxonomy V2 or higher by excluding "IAB-" type categories - : deepAccess(bidderRequest, 'ortb2.site.content.cat', []) - .filter(cat => cat.toLowerCase().indexOf('iab-') !== 0), + : Object.keys(iabcat2), id: videoParams.id || '', lang: videoParams.lang || '', private: videoParams.private || false, diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index e5a20fa6b6e..a102c26dca2 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -78,7 +78,18 @@ describe('dailymotionBidAdapterTests', () => { }, site: { content: { - cat: ['IAB-1', '200'], + data: [ + { + name: 'dataprovider.com', + ext: { segtax: 4 }, + segment: [{ id: 'IAB-1' }], + }, + { + name: 'dataprovider.com', + ext: { segtax: 5 }, + segment: [{ id: '200' }], + }, + ], }, }, }, @@ -171,7 +182,46 @@ describe('dailymotionBidAdapterTests', () => { }, site: { content: { - cat: ['6', '17'], + data: [ + undefined, // Undefined to check proper handling of edge cases + {}, // Empty object to check proper handling of edge cases + { ext: {} }, // Empty ext to check proper handling of edge cases + { + name: 'dataprovider.com', + ext: { segtax: 22 }, // Invalid segtax to check proper handling of edge cases + segment: [{ id: '400' }], + }, + { + name: 'dataprovider.com', + ext: { segtax: 5 }, + segment: undefined, // Invalid segment to check proper handling of edge cases + }, + { + name: 'dataprovider.com', + ext: { segtax: 4 }, + segment: undefined, // Invalid segment to check proper handling of edge cases + }, + { + name: 'dataprovider.com', + ext: { segtax: 4 }, + segment: [{ id: 2222 }], // Invalid segment id to check proper handling of edge cases + }, + { + name: 'dataprovider.com', + ext: { segtax: 5 }, + segment: [{ id: '6' }], + }, + { + name: 'dataprovider.com', + ext: { segtax: 5 }, + segment: [{ id: '6' }], // Check that same cat won't be duplicated + }, + { + name: 'dataprovider.com', + ext: { segtax: 5 }, + segment: [{ id: '17' }, { id: '20' }], + }, + ], }, }, }, @@ -206,7 +256,7 @@ describe('dailymotionBidAdapterTests', () => { description: bidRequestData[0].mediaTypes.video.description, // No iabcat1 here because nothing matches taxonomy iabcat1: [], - iabcat2: bidderRequestData.ortb2.site.content.cat, + iabcat2: ['6', '17', '20'], id: bidRequestData[0].params.video.id, lang: bidRequestData[0].params.video.lang, private: bidRequestData[0].params.video.private, From 2a38bacdd84c9c5144f33e1bba62aff906807079 Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Fri, 19 Apr 2024 09:32:32 +0200 Subject: [PATCH 16/23] Dailymotion Bid Adaptor: get content data from ortb2.site.content --- modules/dailymotionBidAdapter.js | 12 ++++++++---- test/spec/modules/dailymotionBidAdapter_spec.js | 16 ++++++++-------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 2be5edad78e..adeda1248d7 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -42,11 +42,15 @@ function getVideoMetadata(bidRequest, bidderRequest) { iabcat2: Array.isArray(videoParams.iabcat2) ? videoParams.iabcat2 : Object.keys(iabcat2), - id: videoParams.id || '', - lang: videoParams.lang || '', + id: videoParams.id || + deepAccess(bidderRequest, 'ortb2.site.content.id', ''), + lang: videoParams.lang || + deepAccess(bidderRequest, 'ortb2.site.content.language', ''), private: videoParams.private || false, - tags: videoParams.tags || '', - title: videoParams.title || '', + tags: videoParams.tags || + deepAccess(bidderRequest, 'ortb2.site.content.keywords', ''), + title: videoParams.title || + deepAccess(bidderRequest, 'ortb2.site.content.title', ''), topics: videoParams.topics || '', xid: videoParams.xid || '', }; diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index a102c26dca2..2fef4c42583 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -144,7 +144,6 @@ describe('dailymotionBidAdapterTests', () => { api: [2, 7], description: 'this is a test video', duration: 300, - lang: 'ENG', startdelay: 0, }, }, @@ -153,10 +152,7 @@ describe('dailymotionBidAdapterTests', () => { apiKey: 'test_api_key', video: { duration: 556, - id: '54321', - lang: 'FR', private: false, - tags: 'tag_1,tag_2,tag_3', title: 'test video', topics: 'topic_1, topic_2', xid: 'x123456', @@ -182,6 +178,10 @@ describe('dailymotionBidAdapterTests', () => { }, site: { content: { + id: '54321', + language: 'FR', + keywords: 'tag_1,tag_2,tag_3', + title: 'test video', data: [ undefined, // Undefined to check proper handling of edge cases {}, // Empty object to check proper handling of edge cases @@ -257,11 +257,11 @@ describe('dailymotionBidAdapterTests', () => { // No iabcat1 here because nothing matches taxonomy iabcat1: [], iabcat2: ['6', '17', '20'], - id: bidRequestData[0].params.video.id, - lang: bidRequestData[0].params.video.lang, + id: bidderRequestData.ortb2.site.content.id, + lang: bidderRequestData.ortb2.site.content.language, private: bidRequestData[0].params.video.private, - tags: bidRequestData[0].params.video.tags, - title: bidRequestData[0].params.video.title, + tags: bidderRequestData.ortb2.site.content.keywords, + title: bidderRequestData.ortb2.site.content.title, topics: bidRequestData[0].params.video.topics, xid: bidRequestData[0].params.video.xid, // Overriden through bidder params From bcaaa60b2dc3c20e7a5cddfe83acdde7c60c0e5a Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Fri, 19 Apr 2024 11:24:18 +0200 Subject: [PATCH 17/23] Dailymotion Bid Adaptor: add support for iabcat1 in videoParams and document mapping of ortb2 fpd to video metadata --- modules/dailymotionBidAdapter.js | 4 +- modules/dailymotionBidAdapter.md | 17 ++- .../modules/dailymotionBidAdapter_spec.js | 105 +++++++++++++++++- 3 files changed, 122 insertions(+), 4 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index adeda1248d7..360ecef32b5 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -38,7 +38,9 @@ function getVideoMetadata(bidRequest, bidderRequest) { const videoMetadata = { description: videoParams.description || '', duration: videoParams.duration || 0, - iabcat1: Object.keys(iabcat1), + iabcat1: Array.isArray(videoParams.iabcat1) + ? videoParams.iabcat1 + : Object.keys(iabcat1), iabcat2: Array.isArray(videoParams.iabcat2) ? videoParams.iabcat2 : Object.keys(iabcat2), diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index 795273c9229..c145817a118 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -51,7 +51,7 @@ Please note that failing to set these will result in the adapter not bidding at # Sample video AdUnit To allow better targeting, you should provide as much context about the video as possible. -There are two ways of doing this depending on if you're using Dailymotion player or a third party one. +There are three ways of doing this depending on if you're using Dailymotion player or a third party one. If you are using the Dailymotion player, you should only provide the video `xid` in your ad unit, example: @@ -102,6 +102,7 @@ const adUnits = [ context: 'instream', description: 'this is a video description', duration: 556, + iabcat1: ['IAB-2'], iabcat2: ['6', '17'], id: '54321', lang: 'FR', @@ -122,7 +123,8 @@ If a field exists in both places, it will be overridden by bids.params.video. * `description` - Video description * `duration` - Video duration in seconds -* `iabcat2` - List of IAB category IDs from the [2.0 taxonomy](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%202.0.tsv) +* `iabcat1` - List of IAB category IDs from the [1.0 taxonomy](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%201.0.tsv) +* `iabcat2` - List of IAB category IDs from the [2.0 taxonomy](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%202.0.tsv) and above * `id` - Video unique ID in host video infrastructure * `lang` - ISO 639-1 code for main language used in the video * `private` - True if video is not publicly available @@ -131,6 +133,17 @@ If a field exists in both places, it will be overridden by bids.params.video. * `topics` - Main topics for the video, comma separated * `xid` - Dailymotion video identifier (only applicable if using the Dailymotion player) +If you already specify [First-Party data](https://docs.prebid.org/features/firstPartyData.html) through the `ortb2` object when calling [`pbjs.requestBids(requestObj)`](https://docs.prebid.org/dev-docs/publisher-api-reference/requestBids.html), we will fallback to those values when possible. See the mapping below. + +| From ortb2 | Metadata fields | +|---------------------------------------------------------------------|-----------------| +| `ortb2.site.content.data` where `ext.segtax` is `4` | `iabcat1` | +| `ortb2.site.content.data` where `ext.segtax` is `5`, `6` or `7` | `iabcat2` | +| `ortb2.site.content.id` | `id` | +| `ortb2.site.content.language` | `lang` | +| `ortb2.site.content.keywords` | `tags` | +| `ortb2.site.content.title` | `title` | + # Integrating the adapter To use the adapter with any non-test request, you first need to ask an API key from Dailymotion. Please contact us through **DailymotionPrebid.js@dailymotion.com**. diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index 2fef4c42583..2aee25cf44d 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -27,6 +27,109 @@ describe('dailymotionBidAdapterTests', () => { // Validate request generation it('validates buildRequests', () => { + const bidRequestData = [{ + auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', + bidId: 123456, + adUnitCode: 'preroll', + mediaTypes: { + video: { + playerSize: [[1280, 720]], + api: [2, 7], + description: 'this is a test video', + duration: 300, + iabcat2: ['6', '17'], + lang: 'ENG', + startdelay: 0, + }, + }, + sizes: [[1920, 1080]], + params: { + apiKey: 'test_api_key', + video: { + duration: 556, + iabcat1: ['IAB-1'], + id: '54321', + lang: 'FR', + private: false, + tags: 'tag_1,tag_2,tag_3', + title: 'test video', + topics: 'topic_1, topic_2', + xid: 'x123456', + }, + }, + }]; + + const bidderRequestData = { + refererInfo: { + page: 'https://publisher.com', + }, + uspConsent: '1YN-', + gdprConsent: { + apiVersion: 2, + consentString: 'xxx', + gdprApplies: true, + }, + gppConsent: { + gppString: 'xxx', + applicableSections: [5], + }, + ortb2: { + regs: { + coppa: 1, + }, + site: { + content: { + data: [ + { + name: 'dataprovider.com', + ext: { segtax: 5 }, + segment: [{ id: '200' }], + }, + ], + }, + }, + }, + }; + + const [request] = config.runWithBidder( + 'dailymotion', + () => spec.buildRequests(bidRequestData, bidderRequestData), + ); + + const { data: reqData } = request; + + expect(request.url).to.equal('https://pb.dmxleo.com'); + + expect(reqData.bidder_request).to.eql({ + refererInfo: bidderRequestData.refererInfo, + uspConsent: bidderRequestData.uspConsent, + gdprConsent: bidderRequestData.gdprConsent, + gppConsent: bidderRequestData.gppConsent, + }); + expect(reqData.config.api_key).to.eql(bidRequestData[0].params.apiKey); + expect(reqData.coppa).to.be.true; + expect(reqData.request.auctionId).to.eql(bidRequestData[0].auctionId); + expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); + expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); + expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); + expect(reqData.request.mediaTypes.video.startDelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); + expect(reqData.video_metadata).to.eql({ + description: bidRequestData[0].mediaTypes.video.description, + iabcat1: ['IAB-1'], // Taxonomy v2 or higher is excluded + iabcat2: bidRequestData[0].mediaTypes.video.iabcat2, + id: bidRequestData[0].params.video.id, + lang: bidRequestData[0].params.video.lang, + private: bidRequestData[0].params.video.private, + tags: bidRequestData[0].params.video.tags, + title: bidRequestData[0].params.video.title, + topics: bidRequestData[0].params.video.topics, + xid: bidRequestData[0].params.video.xid, + // Overriden through bidder params + duration: bidRequestData[0].params.video.duration, + }); + }); + + it('validates buildRequests with fallback values on ortb2 for iabcat1', () => { const bidRequestData = [{ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, @@ -133,7 +236,7 @@ describe('dailymotionBidAdapterTests', () => { }); }); - it('validates buildRequests with fallback values on ortb2 for gpp & iabcat', () => { + it('validates buildRequests with fallback values on ortb2 (gpp, iabcat2, id...)', () => { const bidRequestData = [{ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, From 091eec583088eedb74dcbd5654345fc572b38ffb Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Fri, 19 Apr 2024 11:52:41 +0200 Subject: [PATCH 18/23] Dailymotion Bid Adaptor: add support for Object: App --- modules/dailymotionBidAdapter.js | 21 +++++++++++-------- .../modules/dailymotionBidAdapter_spec.js | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 360ecef32b5..4196910111a 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -17,11 +17,18 @@ function getVideoMetadata(bidRequest, bidderRequest) { ...videoBidderParams, // Bidder Specific overrides }; + // As per oRTB 2.5 spec, "A bid request must not contain both an App and a Site object." + // See section 3.2.14 + // Content object is either from Object: Site or Object: App + const contentObj = deepAccess(bidderRequest, 'ortb2.site') + ? deepAccess(bidderRequest, 'ortb2.site.content') + : deepAccess(bidderRequest, 'ortb2.app.content'); + // Store as object keys to ensure uniqueness const iabcat1 = {}; const iabcat2 = {}; - deepAccess(bidderRequest, 'ortb2.site.content.data', []).forEach((data) => { + deepAccess(contentObj, 'data', []).forEach((data) => { if ([4, 5, 6, 7].includes(data?.ext?.segtax)) { (Array.isArray(data.segment) ? data.segment : []).forEach((segment) => { if (typeof segment.id === 'string') { @@ -44,15 +51,11 @@ function getVideoMetadata(bidRequest, bidderRequest) { iabcat2: Array.isArray(videoParams.iabcat2) ? videoParams.iabcat2 : Object.keys(iabcat2), - id: videoParams.id || - deepAccess(bidderRequest, 'ortb2.site.content.id', ''), - lang: videoParams.lang || - deepAccess(bidderRequest, 'ortb2.site.content.language', ''), + id: videoParams.id || deepAccess(contentObj, 'id', ''), + lang: videoParams.lang || deepAccess(contentObj, 'language', ''), private: videoParams.private || false, - tags: videoParams.tags || - deepAccess(bidderRequest, 'ortb2.site.content.keywords', ''), - title: videoParams.title || - deepAccess(bidderRequest, 'ortb2.site.content.title', ''), + tags: videoParams.tags || deepAccess(contentObj, 'keywords', ''), + title: videoParams.title || deepAccess(contentObj, 'title', ''), topics: videoParams.topics || '', xid: videoParams.xid || '', }; diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index 2aee25cf44d..1ab93e47099 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -129,7 +129,7 @@ describe('dailymotionBidAdapterTests', () => { }); }); - it('validates buildRequests with fallback values on ortb2 for iabcat1', () => { + it('validates buildRequests with content values from App', () => { const bidRequestData = [{ auctionId: 'b06c5141-fe8f-4cdf-9d7d-54415490a917', bidId: 123456, @@ -179,7 +179,7 @@ describe('dailymotionBidAdapterTests', () => { regs: { coppa: 1, }, - site: { + app: { content: { data: [ { From 7a5b07089ea0ce5238ecbc36eff7ee208887b12a Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Fri, 19 Apr 2024 15:15:00 +0200 Subject: [PATCH 19/23] Dailymotion Bid Adaptor: only support video adunits in context instream --- modules/dailymotionBidAdapter.js | 19 ++++++- modules/dailymotionBidAdapter.md | 23 ++++++-- .../modules/dailymotionBidAdapter_spec.js | 55 ++++++++++++++++++- 3 files changed, 90 insertions(+), 7 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 4196910111a..4985297b287 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -76,7 +76,24 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: function (bid) { - return typeof bid?.params?.apiKey === 'string' && bid.params.apiKey.length > 10; + if (bid?.params) { + // We only accept video adUnits + if (!bid?.mediaTypes?.[VIDEO]) return false; + + // As `context`, `placement` & `plcmt` are optional (although recommended) + // values, we check the 3 of them to see if we are in an instream video context + const isInstream = bid.mediaTypes[VIDEO].context === 'instream' || + bid.mediaTypes[VIDEO].placement === 1 || + bid.mediaTypes[VIDEO].plcmt === 1; + + // We only accept instream video context + if (!isInstream) return false; + + // We need API key + return typeof bid.params.apiKey === 'string' && bid.params.apiKey.length > 10; + } + + return false; }, /** diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index c145817a118..6162d020c0c 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -9,10 +9,11 @@ Maintainer: ad-leo-engineering@dailymotion.com # Description Dailymotion prebid adapter. +Supports video ad units in instream context. # Configuration options -Before calling this adapter, you need to set at least the API key in the bid parameters: +Before calling this adapter, you need to at least set a video adUnit in an instream context and the API key in the bid parameters: ```javascript const adUnits = [ @@ -21,8 +22,14 @@ const adUnits = [ bidder: 'dailymotion', params: { apiKey: 'fake_api_key' - } - }] + }, + }], + code: 'test-ad-unit', + mediaTypes: { + video: { + context: 'instream', + }, + }, } ]; ``` @@ -40,8 +47,14 @@ const adUnits = [ bidder: 'dailymotion', params: { apiKey: 'dailymotion-testing' - } - }] + }, + }], + code: 'test-ad-unit', + mediaTypes: { + video: { + context: 'instream', + }, + }, } ]; ``` diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index 1ab93e47099..7d409a0e149 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -1,7 +1,7 @@ import { config } from 'src/config.js'; import { expect } from 'chai'; import { spec } from 'modules/dailymotionBidAdapter.js'; -import { VIDEO } from '../../../src/mediaTypes'; +import { BANNER, VIDEO } from '../../../src/mediaTypes'; describe('dailymotionBidAdapterTests', () => { // Validate that isBidRequestValid only validates requests with apiKey @@ -12,6 +12,11 @@ describe('dailymotionBidAdapterTests', () => { params: { apiKey: '', }, + mediaTypes: { + [VIDEO]: { + context: 'instream', + }, + }, }; expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid(bidWithEmptyApi))).to.be.false; @@ -20,9 +25,57 @@ describe('dailymotionBidAdapterTests', () => { params: { apiKey: 'test_api_key', }, + mediaTypes: { + [VIDEO]: { + context: 'instream', + }, + }, }; expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid(bidWithApi))).to.be.true; + + const bidWithEmptyMediaTypes = { + params: { + apiKey: '', + }, + }; + + expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid(bidWithEmptyMediaTypes))).to.be.false; + + const bidWithEmptyVideoAdUnit = { + params: { + apiKey: '', + }, + mediaTypes: { + [VIDEO]: {}, + }, + }; + + expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid(bidWithEmptyVideoAdUnit))).to.be.false; + + const bidWithBannerMediaType = { + params: { + apiKey: 'test_api_key', + }, + mediaTypes: { + [BANNER]: {}, + }, + }; + + expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid(bidWithBannerMediaType))).to.be.false; + + const bidWithOutstreamContext = { + params: { + apiKey: 'test_api_key', + }, + mediaTypes: { + video: { + context: 'outstream', + }, + }, + }; + + expect(config.runWithBidder('dailymotion', () => spec.isBidRequestValid(bidWithOutstreamContext))).to.be.false; }); // Validate request generation From 729647b5f4898c3745a62c80c4098117bca2976e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Millet?= Date: Fri, 19 Apr 2024 15:05:26 +0200 Subject: [PATCH 20/23] Dailymotion bid adapter: Add standard ORTB video parameters Note: I changed the case of `startdelay` to be consistent with the other parameters, but it won't have any impact on current deployments as this parameter is not used onsite. --- modules/dailymotionBidAdapter.js | 12 +++++- modules/dailymotionBidAdapter.md | 10 +++-- .../modules/dailymotionBidAdapter_spec.js | 37 +++++++++++++++---- 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 4985297b287..0c88cd92d49 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -136,9 +136,17 @@ export const spec = { bidId: bid.bidId || '', mediaTypes: { video: { - playerSize: bid.mediaTypes?.[VIDEO]?.playerSize || [], api: bid.mediaTypes?.[VIDEO]?.api || [], - startDelay: bid.mediaTypes?.[VIDEO]?.startdelay || 0, + mimes: bid.mediaTypes?.[VIDEO]?.mimes || [], + minduration: bid.mediaTypes?.[VIDEO]?.minduration || 0, + maxduration: bid.mediaTypes?.[VIDEO]?.maxduration || 0, + protocols: bid.mediaTypes?.[VIDEO]?.protocols || [], + skip: bid.mediaTypes?.[VIDEO]?.skip || 0, + skipafter: bid.mediaTypes?.[VIDEO]?.skipafter || 0, + skipmin: bid.mediaTypes?.[VIDEO]?.skipmin || 0, + startdelay: bid.mediaTypes?.[VIDEO]?.startdelay || 0, + w: bid.mediaTypes?.[VIDEO]?.w || 0, + h: bid.mediaTypes?.[VIDEO]?.h || 0, }, }, sizes: bid.sizes || [], diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index 6162d020c0c..4b6040f9982 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -82,8 +82,9 @@ const adUnits = [ video: { api: [2, 7], context: 'instream', - playerSize: [ [1280, 720] ], - startDelay: 0, + startdelay: 0, + w: 1280, + h: 720, xid: 'x123456' // Dailymotion infrastructure unique video ID }, } @@ -119,12 +120,13 @@ const adUnits = [ iabcat2: ['6', '17'], id: '54321', lang: 'FR', - playerSize: [ [1280, 720] ], private: false, - startDelay: 0, + startdelay: 0, tags: 'tag_1,tag_2,tag_3', title: 'test video', topics: 'topic_1, topic_2', + w: 1280, + h: 720, }, } } diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index 7d409a0e149..af23ce835bb 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -86,13 +86,21 @@ describe('dailymotionBidAdapterTests', () => { adUnitCode: 'preroll', mediaTypes: { video: { - playerSize: [[1280, 720]], api: [2, 7], description: 'this is a test video', duration: 300, iabcat2: ['6', '17'], lang: 'ENG', + mimes: ['video/mp4'], + minduration: 5, + maxduration: 30, + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + skip: 1, + skipafter: 5, + skipmin: 10, startdelay: 0, + w: 1280, + h: 720 }, }, sizes: [[1920, 1080]], @@ -271,8 +279,16 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.auctionId).to.eql(bidRequestData[0].auctionId); expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); - expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); - expect(reqData.request.mediaTypes.video.startDelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); + expect(reqData.request.mediaTypes.video.mimes).to.eql(bidRequestData[0].mediaTypes.video.mimes); + expect(reqData.request.mediaTypes.video.minduration).to.eql(bidRequestData[0].mediaTypes.video.minduration); + expect(reqData.request.mediaTypes.video.maxduration).to.eql(bidRequestData[0].mediaTypes.video.maxduration); + expect(reqData.request.mediaTypes.video.protocols).to.eql(bidRequestData[0].mediaTypes.video.protocols); + expect(reqData.request.mediaTypes.video.skip).to.eql(bidRequestData[0].mediaTypes.video.skip); + expect(reqData.request.mediaTypes.video.skipafter).to.eql(bidRequestData[0].mediaTypes.video.skipafter); + expect(reqData.request.mediaTypes.video.skipmin).to.eql(bidRequestData[0].mediaTypes.video.skipmin); + expect(reqData.request.mediaTypes.video.startdelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); + expect(reqData.request.mediaTypes.video.w).to.eql(bidRequestData[0].mediaTypes.video.w); + expect(reqData.request.mediaTypes.video.h).to.eql(bidRequestData[0].mediaTypes.video.h); expect(reqData.video_metadata).to.eql({ description: bidRequestData[0].mediaTypes.video.description, iabcat1: ['IAB-1'], // Taxonomy v2 or higher is excluded @@ -296,7 +312,6 @@ describe('dailymotionBidAdapterTests', () => { adUnitCode: 'preroll', mediaTypes: { video: { - playerSize: [[1280, 720]], api: [2, 7], description: 'this is a test video', duration: 300, @@ -407,7 +422,7 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); - expect(reqData.request.mediaTypes.video.startDelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); + expect(reqData.request.mediaTypes.video.startdelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); expect(reqData.video_metadata).to.eql({ description: bidRequestData[0].mediaTypes.video.description, // No iabcat1 here because nothing matches taxonomy @@ -466,9 +481,17 @@ describe('dailymotionBidAdapterTests', () => { adUnitCode: '', mediaTypes: { video: { - playerSize: [], - startDelay: 0, api: [], + mimes: [], + minduration: 0, + maxduration: 0, + protocols: [], + skip: 0, + skipafter: 0, + skipmin: 0, + startdelay: 0, + w: 0, + h: 0, }, }, sizes: [], From 6e36b69874485cc1b2f5ad70e5af2fdeac0e5cbe Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Fri, 19 Apr 2024 16:35:32 +0200 Subject: [PATCH 21/23] Dailymotion Bid Adaptor: add support for livestream and app --- modules/dailymotionBidAdapter.js | 24 ++++++++++++------- modules/dailymotionBidAdapter.md | 3 +++ .../modules/dailymotionBidAdapter_spec.js | 23 ++++++++++++++++-- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index 0c88cd92d49..f233edf842c 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -58,6 +58,9 @@ function getVideoMetadata(bidRequest, bidderRequest) { title: videoParams.title || deepAccess(contentObj, 'title', ''), topics: videoParams.topics || '', xid: videoParams.xid || '', + livestream: typeof videoParams.livestream === 'number' + ? !!videoParams.livestream + : !!deepAccess(contentObj, 'livestream', 0), }; return videoMetadata; @@ -109,15 +112,15 @@ export const spec = { data: { bidder_request: { gdprConsent: { - apiVersion: bidderRequest?.gdprConsent?.apiVersion || 1, - consentString: bidderRequest?.gdprConsent?.consentString || '', + apiVersion: deepAccess(bidderRequest, 'gdprConsent.apiVersion', 1), + consentString: deepAccess(bidderRequest, 'gdprConsent.consentString', ''), // Cast boolean in any case (eg: if value is int) to ensure type - gdprApplies: !!bidderRequest?.gdprConsent?.gdprApplies, + gdprApplies: !!deepAccess(bidderRequest, 'gdprConsent.gdprApplies'), }, refererInfo: { - page: bidderRequest?.refererInfo?.page || '', + page: deepAccess(bidderRequest, 'refererInfo.page', ''), }, - uspConsent: bidderRequest?.uspConsent || '', + uspConsent: deepAccess(bidderRequest, 'uspConsent', ''), gppConsent: { gppString: deepAccess(bidderRequest, 'gppConsent.gppString') || deepAccess(bidderRequest, 'ortb2.regs.gpp', ''), @@ -130,10 +133,15 @@ export const spec = { }, // Cast boolean in any case (value should be 0 or 1) to ensure type coppa: !!deepAccess(bidderRequest, 'ortb2.regs.coppa'), + // In app context, we need to retrieve additional informations + ...(!deepAccess(bidderRequest, 'ortb2.site') && !!deepAccess(bidderRequest, 'ortb2.app') ? { + appBundle: deepAccess(bidderRequest, 'ortb2.app.bundle', ''), + appStoreUrl: deepAccess(bidderRequest, 'ortb2.app.storeurl', ''), + } : {}), request: { - adUnitCode: bid.adUnitCode || '', - auctionId: bid.auctionId || '', - bidId: bid.bidId || '', + adUnitCode: deepAccess(bid, 'adUnitCode', ''), + auctionId: deepAccess(bid, 'auctionId', ''), + bidId: deepAccess(bid, 'bidId', ''), mediaTypes: { video: { api: bid.mediaTypes?.[VIDEO]?.api || [], diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index 4b6040f9982..fec6f56515b 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -120,6 +120,7 @@ const adUnits = [ iabcat2: ['6', '17'], id: '54321', lang: 'FR', + livestream: 0, private: false, startdelay: 0, tags: 'tag_1,tag_2,tag_3', @@ -142,6 +143,7 @@ If a field exists in both places, it will be overridden by bids.params.video. * `iabcat2` - List of IAB category IDs from the [2.0 taxonomy](https://github.com/InteractiveAdvertisingBureau/Taxonomies/blob/main/Content%20Taxonomies/Content%20Taxonomy%202.0.tsv) and above * `id` - Video unique ID in host video infrastructure * `lang` - ISO 639-1 code for main language used in the video +* `livestream` - 0 = not live, 1 = content is live * `private` - True if video is not publicly available * `tags` - Tags for the video, comma separated * `title` - Video title @@ -156,6 +158,7 @@ If you already specify [First-Party data](https://docs.prebid.org/features/first | `ortb2.site.content.data` where `ext.segtax` is `5`, `6` or `7` | `iabcat2` | | `ortb2.site.content.id` | `id` | | `ortb2.site.content.language` | `lang` | +| `ortb2.site.content.livestream` | `livestream` | | `ortb2.site.content.keywords` | `tags` | | `ortb2.site.content.title` | `title` | diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index af23ce835bb..0e001f838b2 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -116,6 +116,7 @@ describe('dailymotionBidAdapterTests', () => { title: 'test video', topics: 'topic_1, topic_2', xid: 'x123456', + livestream: 1, }, }, }]; @@ -173,7 +174,7 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); - expect(reqData.request.mediaTypes.video.startDelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); + expect(reqData.request.mediaTypes.video.startdelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); expect(reqData.video_metadata).to.eql({ description: bidRequestData[0].mediaTypes.video.description, iabcat1: ['IAB-1'], // Taxonomy v2 or higher is excluded @@ -187,6 +188,7 @@ describe('dailymotionBidAdapterTests', () => { xid: bidRequestData[0].params.video.xid, // Overriden through bidder params duration: bidRequestData[0].params.video.duration, + livestream: !!bidRequestData[0].params.video.livestream, }); }); @@ -197,13 +199,21 @@ describe('dailymotionBidAdapterTests', () => { adUnitCode: 'preroll', mediaTypes: { video: { - playerSize: [[1280, 720]], api: [2, 7], description: 'this is a test video', duration: 300, iabcat2: ['6', '17'], lang: 'ENG', + mimes: ['video/mp4'], + minduration: 5, + maxduration: 30, + protocols: [1, 2, 3, 4, 5, 6, 7, 8], + skip: 1, + skipafter: 5, + skipmin: 10, startdelay: 0, + w: 1280, + h: 720, }, }, sizes: [[1920, 1080]], @@ -218,6 +228,7 @@ describe('dailymotionBidAdapterTests', () => { title: 'test video', topics: 'topic_1, topic_2', xid: 'x123456', + livestream: 1, }, }, }]; @@ -241,6 +252,8 @@ describe('dailymotionBidAdapterTests', () => { coppa: 1, }, app: { + bundle: 'app-bundle', + storeurl: 'https://play.google.com/store/apps/details?id=app-bundle', content: { data: [ { @@ -276,6 +289,8 @@ describe('dailymotionBidAdapterTests', () => { }); expect(reqData.config.api_key).to.eql(bidRequestData[0].params.apiKey); expect(reqData.coppa).to.be.true; + expect(reqData.appBundle).to.eql(bidderRequestData.ortb2.app.bundle); + expect(reqData.appStoreUrl).to.eql(bidderRequestData.ortb2.app.storeurl); expect(reqData.request.auctionId).to.eql(bidRequestData[0].auctionId); expect(reqData.request.bidId).to.eql(bidRequestData[0].bidId); expect(reqData.request.mediaTypes.video.api).to.eql(bidRequestData[0].mediaTypes.video.api); @@ -302,6 +317,7 @@ describe('dailymotionBidAdapterTests', () => { xid: bidRequestData[0].params.video.xid, // Overriden through bidder params duration: bidRequestData[0].params.video.duration, + livestream: !!bidRequestData[0].params.video.livestream, }); }); @@ -353,6 +369,7 @@ describe('dailymotionBidAdapterTests', () => { language: 'FR', keywords: 'tag_1,tag_2,tag_3', title: 'test video', + livestream: 1, data: [ undefined, // Undefined to check proper handling of edge cases {}, // Empty object to check proper handling of edge cases @@ -437,6 +454,7 @@ describe('dailymotionBidAdapterTests', () => { xid: bidRequestData[0].params.video.xid, // Overriden through bidder params duration: bidRequestData[0].params.video.duration, + livestream: !!bidderRequestData.ortb2.site.content.livestream, }); }); @@ -509,6 +527,7 @@ describe('dailymotionBidAdapterTests', () => { title: '', topics: '', xid: '', + livestream: false, }); }); From ae8de5fc90e4984835d28cacbe3939d51e862fc5 Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Sat, 20 Apr 2024 10:29:36 +0200 Subject: [PATCH 22/23] Dailymotion Bid Adaptor: drop support for non standard fields in mediaTypes.video --- modules/dailymotionBidAdapter.js | 33 +++++++-------- modules/dailymotionBidAdapter.md | 21 +++++----- .../modules/dailymotionBidAdapter_spec.js | 41 ++++++++----------- 3 files changed, 44 insertions(+), 51 deletions(-) diff --git a/modules/dailymotionBidAdapter.js b/modules/dailymotionBidAdapter.js index f233edf842c..afded538fd0 100644 --- a/modules/dailymotionBidAdapter.js +++ b/modules/dailymotionBidAdapter.js @@ -9,13 +9,7 @@ import { deepAccess } from '../src/utils.js'; * @return video metadata */ function getVideoMetadata(bidRequest, bidderRequest) { - const videoAdUnit = deepAccess(bidRequest, 'mediaTypes.video', {}); - const videoBidderParams = deepAccess(bidRequest, 'params.video', {}); - - const videoParams = { - ...videoAdUnit, - ...videoBidderParams, // Bidder Specific overrides - }; + const videoParams = deepAccess(bidRequest, 'params.video', {}); // As per oRTB 2.5 spec, "A bid request must not contain both an App and a Site object." // See section 3.2.14 @@ -24,9 +18,11 @@ function getVideoMetadata(bidRequest, bidderRequest) { ? deepAccess(bidderRequest, 'ortb2.site.content') : deepAccess(bidderRequest, 'ortb2.app.content'); - // Store as object keys to ensure uniqueness - const iabcat1 = {}; - const iabcat2 = {}; + const parsedContentData = { + // Store as object keys to ensure uniqueness + iabcat1: {}, + iabcat2: {}, + }; deepAccess(contentObj, 'data', []).forEach((data) => { if ([4, 5, 6, 7].includes(data?.ext?.segtax)) { @@ -34,9 +30,12 @@ function getVideoMetadata(bidRequest, bidderRequest) { if (typeof segment.id === 'string') { // See https://docs.prebid.org/features/firstPartyData.html#segments-and-taxonomy // Only take IAB cats of taxonomy V1 - if (data.ext.segtax === 4) iabcat1[segment.id] = 1; - // Only take IAB cats of taxonomy V2 or higher - if ([5, 6, 7].includes(data.ext.segtax)) iabcat2[segment.id] = 1; + if (data.ext.segtax === 4) { + parsedContentData.iabcat1[segment.id] = 1; + } else { + // Only take IAB cats of taxonomy V2 or higher + parsedContentData.iabcat2[segment.id] = 1; + } } }); } @@ -44,13 +43,15 @@ function getVideoMetadata(bidRequest, bidderRequest) { const videoMetadata = { description: videoParams.description || '', - duration: videoParams.duration || 0, + duration: videoParams.duration || deepAccess(contentObj, 'len', 0), iabcat1: Array.isArray(videoParams.iabcat1) ? videoParams.iabcat1 - : Object.keys(iabcat1), + : Array.isArray(deepAccess(contentObj, 'cat')) + ? contentObj.cat + : Object.keys(parsedContentData.iabcat1), iabcat2: Array.isArray(videoParams.iabcat2) ? videoParams.iabcat2 - : Object.keys(iabcat2), + : Object.keys(parsedContentData.iabcat2), id: videoParams.id || deepAccess(contentObj, 'id', ''), lang: videoParams.lang || deepAccess(contentObj, 'language', ''), private: videoParams.private || false, diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index fec6f56515b..eb4d924501f 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -134,8 +134,7 @@ const adUnits = [ ]; ``` -Each of the following video metadata fields can be added in mediaTypes.video or bids.params.video. -If a field exists in both places, it will be overridden by bids.params.video. +Each of the following video metadata fields can be added in bids.params.video. * `description` - Video description * `duration` - Video duration in seconds @@ -152,15 +151,15 @@ If a field exists in both places, it will be overridden by bids.params.video. If you already specify [First-Party data](https://docs.prebid.org/features/firstPartyData.html) through the `ortb2` object when calling [`pbjs.requestBids(requestObj)`](https://docs.prebid.org/dev-docs/publisher-api-reference/requestBids.html), we will fallback to those values when possible. See the mapping below. -| From ortb2 | Metadata fields | -|---------------------------------------------------------------------|-----------------| -| `ortb2.site.content.data` where `ext.segtax` is `4` | `iabcat1` | -| `ortb2.site.content.data` where `ext.segtax` is `5`, `6` or `7` | `iabcat2` | -| `ortb2.site.content.id` | `id` | -| `ortb2.site.content.language` | `lang` | -| `ortb2.site.content.livestream` | `livestream` | -| `ortb2.site.content.keywords` | `tags` | -| `ortb2.site.content.title` | `title` | +| From ortb2 | Metadata fields | +|---------------------------------------------------------------------------------|-----------------| +| `ortb2.site.content.cat` OR `ortb2.site.content.data` where `ext.segtax` is `4` | `iabcat1` | +| `ortb2.site.content.data` where `ext.segtax` is `5`, `6` or `7` | `iabcat2` | +| `ortb2.site.content.id` | `id` | +| `ortb2.site.content.language` | `lang` | +| `ortb2.site.content.livestream` | `livestream` | +| `ortb2.site.content.keywords` | `tags` | +| `ortb2.site.content.title` | `title` | # Integrating the adapter diff --git a/test/spec/modules/dailymotionBidAdapter_spec.js b/test/spec/modules/dailymotionBidAdapter_spec.js index 0e001f838b2..fe9484b2814 100644 --- a/test/spec/modules/dailymotionBidAdapter_spec.js +++ b/test/spec/modules/dailymotionBidAdapter_spec.js @@ -87,10 +87,6 @@ describe('dailymotionBidAdapterTests', () => { mediaTypes: { video: { api: [2, 7], - description: 'this is a test video', - duration: 300, - iabcat2: ['6', '17'], - lang: 'ENG', mimes: ['video/mp4'], minduration: 5, maxduration: 30, @@ -107,8 +103,10 @@ describe('dailymotionBidAdapterTests', () => { params: { apiKey: 'test_api_key', video: { + description: 'this is a test video', duration: 556, iabcat1: ['IAB-1'], + iabcat2: ['6', '17'], id: '54321', lang: 'FR', private: false, @@ -176,9 +174,9 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); expect(reqData.request.mediaTypes.video.startdelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); expect(reqData.video_metadata).to.eql({ - description: bidRequestData[0].mediaTypes.video.description, - iabcat1: ['IAB-1'], // Taxonomy v2 or higher is excluded - iabcat2: bidRequestData[0].mediaTypes.video.iabcat2, + description: bidRequestData[0].params.video.description, + iabcat1: ['IAB-1'], + iabcat2: bidRequestData[0].params.video.iabcat2, id: bidRequestData[0].params.video.id, lang: bidRequestData[0].params.video.lang, private: bidRequestData[0].params.video.private, @@ -186,7 +184,6 @@ describe('dailymotionBidAdapterTests', () => { title: bidRequestData[0].params.video.title, topics: bidRequestData[0].params.video.topics, xid: bidRequestData[0].params.video.xid, - // Overriden through bidder params duration: bidRequestData[0].params.video.duration, livestream: !!bidRequestData[0].params.video.livestream, }); @@ -200,10 +197,6 @@ describe('dailymotionBidAdapterTests', () => { mediaTypes: { video: { api: [2, 7], - description: 'this is a test video', - duration: 300, - iabcat2: ['6', '17'], - lang: 'ENG', mimes: ['video/mp4'], minduration: 5, maxduration: 30, @@ -220,7 +213,8 @@ describe('dailymotionBidAdapterTests', () => { params: { apiKey: 'test_api_key', video: { - duration: 556, + description: 'this is a test video', + iabcat2: ['6', '17'], id: '54321', lang: 'FR', private: false, @@ -255,6 +249,7 @@ describe('dailymotionBidAdapterTests', () => { bundle: 'app-bundle', storeurl: 'https://play.google.com/store/apps/details?id=app-bundle', content: { + len: 556, data: [ { name: 'dataprovider.com', @@ -305,9 +300,9 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.mediaTypes.video.w).to.eql(bidRequestData[0].mediaTypes.video.w); expect(reqData.request.mediaTypes.video.h).to.eql(bidRequestData[0].mediaTypes.video.h); expect(reqData.video_metadata).to.eql({ - description: bidRequestData[0].mediaTypes.video.description, - iabcat1: ['IAB-1'], // Taxonomy v2 or higher is excluded - iabcat2: bidRequestData[0].mediaTypes.video.iabcat2, + description: bidRequestData[0].params.video.description, + iabcat1: ['IAB-1'], + iabcat2: bidRequestData[0].params.video.iabcat2, id: bidRequestData[0].params.video.id, lang: bidRequestData[0].params.video.lang, private: bidRequestData[0].params.video.private, @@ -316,7 +311,7 @@ describe('dailymotionBidAdapterTests', () => { topics: bidRequestData[0].params.video.topics, xid: bidRequestData[0].params.video.xid, // Overriden through bidder params - duration: bidRequestData[0].params.video.duration, + duration: bidderRequestData.ortb2.app.content.len, livestream: !!bidRequestData[0].params.video.livestream, }); }); @@ -329,8 +324,6 @@ describe('dailymotionBidAdapterTests', () => { mediaTypes: { video: { api: [2, 7], - description: 'this is a test video', - duration: 300, startdelay: 0, }, }, @@ -338,6 +331,7 @@ describe('dailymotionBidAdapterTests', () => { params: { apiKey: 'test_api_key', video: { + description: 'this is a test video', duration: 556, private: false, title: 'test video', @@ -370,6 +364,7 @@ describe('dailymotionBidAdapterTests', () => { keywords: 'tag_1,tag_2,tag_3', title: 'test video', livestream: 1, + cat: ['IAB-2'], data: [ undefined, // Undefined to check proper handling of edge cases {}, // Empty object to check proper handling of edge cases @@ -391,7 +386,7 @@ describe('dailymotionBidAdapterTests', () => { }, { name: 'dataprovider.com', - ext: { segtax: 4 }, + ext: { segtax: 5 }, segment: [{ id: 2222 }], // Invalid segment id to check proper handling of edge cases }, { @@ -441,9 +436,8 @@ describe('dailymotionBidAdapterTests', () => { expect(reqData.request.mediaTypes.video.playerSize).to.eql(bidRequestData[0].mediaTypes.video.playerSize); expect(reqData.request.mediaTypes.video.startdelay).to.eql(bidRequestData[0].mediaTypes.video.startdelay); expect(reqData.video_metadata).to.eql({ - description: bidRequestData[0].mediaTypes.video.description, - // No iabcat1 here because nothing matches taxonomy - iabcat1: [], + description: bidRequestData[0].params.video.description, + iabcat1: ['IAB-2'], iabcat2: ['6', '17', '20'], id: bidderRequestData.ortb2.site.content.id, lang: bidderRequestData.ortb2.site.content.language, @@ -452,7 +446,6 @@ describe('dailymotionBidAdapterTests', () => { title: bidderRequestData.ortb2.site.content.title, topics: bidRequestData[0].params.video.topics, xid: bidRequestData[0].params.video.xid, - // Overriden through bidder params duration: bidRequestData[0].params.video.duration, livestream: !!bidderRequestData.ortb2.site.content.livestream, }); From 80b6dfe058ddea609a7cd08068982023d73df56c Mon Sep 17 00:00:00 2001 From: Kevin Siow Date: Sat, 20 Apr 2024 10:39:23 +0200 Subject: [PATCH 23/23] Dailymotion Bid Adaptor: update docs examples --- modules/dailymotionBidAdapter.md | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/modules/dailymotionBidAdapter.md b/modules/dailymotionBidAdapter.md index eb4d924501f..7c871b0d536 100644 --- a/modules/dailymotionBidAdapter.md +++ b/modules/dailymotionBidAdapter.md @@ -46,7 +46,7 @@ const adUnits = [ bids: [{ bidder: 'dailymotion', params: { - apiKey: 'dailymotion-testing' + apiKey: 'dailymotion-testing', }, }], code: 'test-ad-unit', @@ -74,7 +74,10 @@ const adUnits = [ bids: [{ bidder: 'dailymotion', params: { - apiKey: 'dailymotion-testing' + apiKey: 'dailymotion-testing', + video: { + xid: 'x123456' // Dailymotion infrastructure unique video ID + }, } }], code: 'test-ad-unit', @@ -85,7 +88,6 @@ const adUnits = [ startdelay: 0, w: 1280, h: 720, - xid: 'x123456' // Dailymotion infrastructure unique video ID }, } } @@ -105,7 +107,17 @@ const adUnits = [ params: { apiKey: 'dailymotion-testing', video: { - description: 'overriden video description' + description: 'this is a video description', + duration: 556, + iabcat1: ['IAB-2'], + iabcat2: ['6', '17'], + id: '54321', + lang: 'FR', + livestream: 0, + private: false, + tags: 'tag_1,tag_2,tag_3', + title: 'test video', + topics: 'topic_1, topic_2', } } }], @@ -114,18 +126,7 @@ const adUnits = [ video: { api: [2, 7], context: 'instream', - description: 'this is a video description', - duration: 556, - iabcat1: ['IAB-2'], - iabcat2: ['6', '17'], - id: '54321', - lang: 'FR', - livestream: 0, - private: false, startdelay: 0, - tags: 'tag_1,tag_2,tag_3', - title: 'test video', - topics: 'topic_1, topic_2', w: 1280, h: 720, },