From b6534c4150c0c229f5f7250550d19fb14bd11466 Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Wed, 11 Oct 2017 17:07:31 +0200 Subject: [PATCH 01/37] Convert Criteo adapter to bidderFactory --- modules/criteoBidAdapter.js | 143 ++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100755 modules/criteoBidAdapter.js diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js new file mode 100755 index 00000000000..4a2ab274804 --- /dev/null +++ b/modules/criteoBidAdapter.js @@ -0,0 +1,143 @@ +import { registerBidder } from 'src/adapters/bidderFactory'; +import { parse } from 'src/url'; +import * as utils from 'src/utils'; + +const BIDDER_CODE = 'criteo'; +const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; +const PROFILE_ID = 207; +const ADAPTER_VERSION = 2; +const INTEGRATION_MODES = { + 'amp': 1, +}; + +/** @type {BidderSpec} */ +export const spec = { + code: BIDDER_CODE, + + /** + * @param {object} bid + * @return {boolean} + */ + isBidRequestValid: bid => ( + !!(bid && bid.params && bid.params.zoneId) + ), + + /** + * @param {BidRequest[]} bidRequests + * @return {ServerRequest} + */ + buildRequests: bidRequests => { + const context = buildContext(bidRequests); + return { + method: 'POST', + url: buildCdbUrl(context), + data: buildCdbRequest(context, bidRequests), + }; + }, + + /** + * @param {*} response + * @param {ServerRequest} request + * @return {Bid[]} + */ + interpretResponse: (response, request) => { + const bids = []; + + if (response.slots && utils.isArray(response.slots)) { + response.slots.forEach(slot => { + const bid = { + requestId: slot.impid, + cpm: slot.cpm, + // currency: 'USD', // FIXME: should return currency from CDB + // netRevenue: true, // FIXME: are bids net or gross? + ad: slot.creative, + width: slot.width, + height: slot.height, + } + bids.push(bid); + }); + } + + return bids; + }, +}; + +/** + * @param {BidRequest[]} bidRequests + * @return {CriteoContext} + */ +function buildContext(bidRequests) { + const url = utils.getTopWindowUrl(); + const queryString = parse(url).search; + + const context = { + url: url, + debug: queryString['pbt_debug'] === '1', + noLog: queryString['pbt_nolog'] === '1', + integrationMode: undefined, + }; + + bidRequests.forEach(bidRequest => { + if (bidRequest.params.integrationMode) { + context.integrationMode = bidRequest.params.integrationMode; + } + }) + + return context; +} + +/** + * @param {CriteoContext} context + * @return {string} + */ +function buildCdbUrl(context) { + let url = CDB_ENDPOINT; + url += '?profileId=' + PROFILE_ID; + url += '&av=' + String(ADAPTER_VERSION); + url += '&cb=' + String(Math.floor(Math.random() * 99999999999)); + + if (context.integrationMode in INTEGRATION_MODES) { + url += '&im=' + INTEGRATION_MODES[context.integrationMode]; + } + if (context.debug) { + url += '&debug=1'; + } + if (context.noLog) { + url += '&nolog=1'; + } + + return url; +} + +/** + * @param {CriteoContext} context + * @param {BidRequest[]} bidRequests + * @return {*} + */ +function buildCdbRequest(context, bidRequests) { + let networkId; + const request = { + publisher: { + url: context.url, + }, + slots: bidRequests.map(bidRequest => { + networkId = bidRequest.params.networkId || networkId; + const slot = { + impid: bidRequest.bidId, + zoneid: bidRequest.params.zoneId, + transactionid: bidRequest.transactionId, + sizes: bidRequest.sizes.map(size => size[0] + 'x' + size[1]), + }; + if (bidRequest.params.publisherSubId) { + slot.publishersubid = bidRequest.params.publisherSubId; + } + return slot; + }), + }; + if (networkId) { + request.publisher.networkid = networkId; + } + return request; +} + +registerBidder(spec); From 1f7d0fab51639e7630e3635062210cfa101d3cc6 Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Wed, 11 Oct 2017 17:29:02 +0200 Subject: [PATCH 02/37] Add documentation for Prebid 1.0 Criteo adapter --- modules/criteoBidAdapter.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 modules/criteoBidAdapter.md diff --git a/modules/criteoBidAdapter.md b/modules/criteoBidAdapter.md new file mode 100755 index 00000000000..796c70a980f --- /dev/null +++ b/modules/criteoBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +Module Name: Criteo Bidder Adapter +Module Type: Bidder Adapter +Maintainer: pi-direct@criteo.com + +# Description + +Module that connects to Criteo's demand sources. + +# Test Parameters +``` + var adUnits = [ + { + code: 'banner-ad-div', + sizes: [[300, 250], [728, 90]], + bids: [ + { + bidder: 'criteo', + params: { + zoneId: 497747 + } + } + ] + } + ]; +``` From dc36bd39cb64d1e5d70e45950e1425bd4db27b40 Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Wed, 11 Oct 2017 17:56:18 +0200 Subject: [PATCH 03/37] Add support for zone-matching bids on Prebid 1.0 Criteo adapter --- modules/criteoBidAdapter.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 4a2ab274804..36289d8282c 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -19,7 +19,7 @@ export const spec = { * @return {boolean} */ isBidRequestValid: bid => ( - !!(bid && bid.params && bid.params.zoneId) + !!(bid && bid.params && (bid.params.zoneId || bid.params.networkId)) ), /** @@ -124,10 +124,12 @@ function buildCdbRequest(context, bidRequests) { networkId = bidRequest.params.networkId || networkId; const slot = { impid: bidRequest.bidId, - zoneid: bidRequest.params.zoneId, transactionid: bidRequest.transactionId, sizes: bidRequest.sizes.map(size => size[0] + 'x' + size[1]), }; + if (bidRequest.params.zoneId) { + slot.zoneid = bidRequest.params.zoneId; + } if (bidRequest.params.publisherSubId) { slot.publishersubid = bidRequest.params.publisherSubId; } From f780bc521df2b8dffb6fa1717f35fe535b981b76 Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Wed, 11 Oct 2017 18:09:24 +0200 Subject: [PATCH 04/37] Add unit tests to the Prebid 1.0 Criteo adapter --- test/spec/modules/criteoBidAdapter_spec.js | 164 +++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100755 test/spec/modules/criteoBidAdapter_spec.js diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js new file mode 100755 index 00000000000..d17efe9fe2b --- /dev/null +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -0,0 +1,164 @@ +import { expect } from 'chai'; +import { spec } from 'modules/criteoBidAdapter'; +import * as utils from 'src/utils'; + +describe('The Criteo bidding adapter', () => { + describe('isBidRequestValid', () => { + it('should return false when given an invalid bid', () => { + const bid = { + bidder: 'criteo', + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + + it('should return true when given a zoneId bid', () => { + const bid = { + bidder: 'criteo', + params: { + zoneId: 123, + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + + it('should return true when given a networkId bid', () => { + const bid = { + bidder: 'criteo', + params: { + networkId: 456, + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + + it('should return true when given a mixed bid with both a zoneId and a networkId', () => { + const bid = { + bidder: 'criteo', + params: { + zoneId: 123, + networkId: 456, + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + }); + + describe('buildRequests', () => { + it('should properly build a zoneId request', () => { + const bidRequests = [ + { + bidder: 'criteo', + bidId: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + params: { + zoneId: 123, + }, + }, + ]; + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal('//bidder.criteo.com/cdb'); + expect(request.method).to.equal('POST'); + expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.slots).to.have.lengthOf(2); + expect(ortbRequest.slots[0].impid).to.equal('bid-123'); + expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); + expect(ortbRequest.slots[0].sizes).to.have.lengthOf(1); + expect(ortbRequest.slots[0].sizes[0]).to.equal('728x90'); + expect(ortbRequest.slots[0].zoneid).to.equal(123); + }); + + it('should properly build a networkId request', () => { + const bidRequests = [ + { + bidder: 'criteo', + bidId: 'bid-123', + transactionId: 'transaction-123', + sizes: [[300, 250], [728, 90]], + params: { + networkId: 456, + }, + }, + ]; + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal('//bidder.criteo.com/cdb'); + expect(request.method).to.equal('POST'); + expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.networkid).to.equal(456); + expect(ortbRequest.slots).to.have.lengthOf(1); + expect(ortbRequest.slots[0].impid).to.equal('bid-123'); + expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); + expect(ortbRequest.slots[0].sizes).to.have.lengthOf(2); + expect(ortbRequest.slots[0].sizes[0]).to.equal('300x250'); + expect(ortbRequest.slots[0].sizes[1]).to.equal('728x90'); + }); + + it('should properly build a mixed request', () => { + const bidRequests = [ + { + bidder: 'criteo', + bidId: 'bid-123', + transactionId: 'transaction-123', + sizes: [[728, 90]], + params: { + zoneId: 123, + }, + }, + { + bidder: 'criteo', + bidId: 'bid-234', + transactionId: 'transaction-234', + sizes: [[300, 250], [728, 90]], + params: { + networkId: 456, + }, + }, + ]; + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal('//bidder.criteo.com/cdb'); + expect(request.method).to.equal('POST'); + expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); + expect(ortbRequest.publisher.networkid).to.equal(456); + expect(ortbRequest.slots).to.have.lengthOf(2); + expect(ortbRequest.slots[0].impid).to.equal('bid-123'); + expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); + expect(ortbRequest.slots[0].sizes).to.have.lengthOf(1); + expect(ortbRequest.slots[0].sizes[0]).to.equal('728x90'); + expect(ortbRequest.slots[1].impid).to.equal('bid-234'); + expect(ortbRequest.slots[1].transactionid).to.equal('transaction-234'); + expect(ortbRequest.slots[1].sizes).to.have.lengthOf(2); + expect(ortbRequest.slots[1].sizes[0]).to.equal('300x250'); + expect(ortbRequest.slots[1].sizes[1]).to.equal('728x90'); + }); + }); + + describe('interpretResponse', () => { + it('should return an empty array when parsing a no bid response', () => { + const response = {}; + const bids = spec.interpretResponse(response, null); + expect(bids).to.have.lengthOf(0); + }); + + it('should properly parse a bid response', () => { + const response = { + slots: [{ + impid: 'test-requestId', + cpm: 1.23, + ad: 'test-ad', + width: 728, + height: 90, + }], + }; + const bids = spec.interpretResponse(response, null); + expect(bids).to.have.lengthOf(1); + expect(bids[0].cpm).to.equal(1.23); + expect(bids[0].ad).to.equal('test-ad'); + expect(bids[0].width).to.equal(728); + expect(bids[0].height).to.equal(90); + }); + }); +}); From dd664a7589f1cdb0d9becc8a7c130b1d204c1d03 Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Thu, 12 Oct 2017 11:17:19 +0200 Subject: [PATCH 05/37] Explicit the fact that Criteo bids are net revenue --- modules/criteoBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 36289d8282c..5f91f35cd4b 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -49,7 +49,7 @@ export const spec = { requestId: slot.impid, cpm: slot.cpm, // currency: 'USD', // FIXME: should return currency from CDB - // netRevenue: true, // FIXME: are bids net or gross? + netRevenue: true, ad: slot.creative, width: slot.width, height: slot.height, From 85b65eda4ece7db9691fcb04392a0c98f61a24f5 Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Tue, 28 Nov 2017 18:05:51 +0100 Subject: [PATCH 06/37] Pass currency in Criteo 1.0 adapter --- modules/criteoBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 5f91f35cd4b..7d3b5b2921c 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -48,7 +48,7 @@ export const spec = { const bid = { requestId: slot.impid, cpm: slot.cpm, - // currency: 'USD', // FIXME: should return currency from CDB + currency: slot.currency, netRevenue: true, ad: slot.creative, width: slot.width, From ae7b2caf643578da15f399ef87c526d5f4e5de97 Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Tue, 28 Nov 2017 18:05:58 +0100 Subject: [PATCH 07/37] Update Criteo adapter to use PublisherTag if present --- modules/criteoBidAdapter.js | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 7d3b5b2921c..12d37be8a72 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -24,15 +24,24 @@ export const spec = { /** * @param {BidRequest[]} bidRequests + * @param {*} bidderRequest * @return {ServerRequest} */ - buildRequests: bidRequests => { - const context = buildContext(bidRequests); - return { - method: 'POST', - url: buildCdbUrl(context), - data: buildCdbRequest(context, bidRequests), - }; + buildRequests: (bidRequests, bidderRequest) => { + let url; + let data; + + if (typeof Criteo !== 'undefined') { + const adapter = new Criteo.PubTag.Adapters.Prebid(PROFILE_ID, ADAPTER_VERSION, bidRequests, bidderRequest); + url = adapter.buildCdbUrl(); + data = adapter.buildCdbRequest(); + } else { + const context = buildContext(bidRequests); + url = buildCdbUrl(context); + data = buildCdbRequest(context, bidRequests); + } + + return { method: 'POST', url, data }; }, /** @@ -41,10 +50,15 @@ export const spec = { * @return {Bid[]} */ interpretResponse: (response, request) => { + if (typeof Criteo !== 'undefined') { + const adapter = Criteo.PubTag.Adapters.Prebid.GetAdapter(request.data); + return adapter.interpretResponse(response.body); + } + const bids = []; - if (response.slots && utils.isArray(response.slots)) { - response.slots.forEach(slot => { + if (response.body.slots && utils.isArray(response.body.slots)) { + response.body.slots.forEach(slot => { const bid = { requestId: slot.impid, cpm: slot.cpm, @@ -125,6 +139,7 @@ function buildCdbRequest(context, bidRequests) { const slot = { impid: bidRequest.bidId, transactionid: bidRequest.transactionId, + auctionId: bidRequest.auctionId, sizes: bidRequest.sizes.map(size => size[0] + 'x' + size[1]), }; if (bidRequest.params.zoneId) { From fa076c894c9a0ddcc96c3c769432dbc0da5a3a87 Mon Sep 17 00:00:00 2001 From: "a.hubert" Date: Fri, 1 Dec 2017 11:52:19 +0100 Subject: [PATCH 08/37] Implement fastbid in prebid 1.0 criteo adapter --- modules/criteoBidAdapter.js | 30 +++++++++++++++++++--- test/spec/modules/criteoBidAdapter_spec.js | 27 +++++++++++-------- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 12d37be8a72..2b8c38275bf 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -1,14 +1,16 @@ +import { loadScript } from 'src/adloader'; import { registerBidder } from 'src/adapters/bidderFactory'; import { parse } from 'src/url'; import * as utils from 'src/utils'; +const ADAPTER_VERSION = 2; const BIDDER_CODE = 'criteo'; const CDB_ENDPOINT = '//bidder.criteo.com/cdb'; -const PROFILE_ID = 207; -const ADAPTER_VERSION = 2; const INTEGRATION_MODES = { 'amp': 1, }; +const PROFILE_ID = 207; +const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js'; /** @type {BidderSpec} */ export const spec = { @@ -31,6 +33,11 @@ export const spec = { let url; let data; + // If publisher tag not already loaded try to get it from fast bid else load it + if (typeof Criteo === 'undefined' && !tryGetCriteoFastBid()) { + loadScript(PUBLISHER_TAG_URL); + } + if (typeof Criteo !== 'undefined') { const adapter = new Criteo.PubTag.Adapters.Prebid(PROFILE_ID, ADAPTER_VERSION, bidRequests, bidderRequest); url = adapter.buildCdbUrl(); @@ -57,7 +64,7 @@ export const spec = { const bids = []; - if (response.body.slots && utils.isArray(response.body.slots)) { + if (response.body && response.body.slots && utils.isArray(response.body.slots)) { response.body.slots.forEach(slot => { const bid = { requestId: slot.impid, @@ -157,4 +164,21 @@ function buildCdbRequest(context, bidRequests) { return request; } +/** + * @return {boolean} + */ +function tryGetCriteoFastBid() { + let success = false; + try { + const fastBid = localStorage.getItem('criteo_fast_bid'); + if (fastBid !== null) { + eval(fastBid); // eslint-disable-line no-eval + success = true; + } + } catch (e) { + // Unable to get fast bid + } + return success; +} + registerBidder(spec); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index d17efe9fe2b..6fce3f16be3 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -61,10 +61,11 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//bidder.criteo.com/cdb'); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=2&cb=\d/); expect(request.method).to.equal('POST'); + const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); - expect(ortbRequest.slots).to.have.lengthOf(2); + expect(ortbRequest.slots).to.have.lengthOf(1); expect(ortbRequest.slots[0].impid).to.equal('bid-123'); expect(ortbRequest.slots[0].transactionid).to.equal('transaction-123'); expect(ortbRequest.slots[0].sizes).to.have.lengthOf(1); @@ -85,8 +86,9 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//bidder.criteo.com/cdb'); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=2&cb=\d/); expect(request.method).to.equal('POST'); + const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); expect(ortbRequest.publisher.networkid).to.equal(456); expect(ortbRequest.slots).to.have.lengthOf(1); @@ -119,8 +121,9 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//bidder.criteo.com/cdb'); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=2&cb=\d/); expect(request.method).to.equal('POST'); + const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); expect(ortbRequest.publisher.networkid).to.equal(456); expect(ortbRequest.slots).to.have.lengthOf(2); @@ -145,13 +148,15 @@ describe('The Criteo bidding adapter', () => { it('should properly parse a bid response', () => { const response = { - slots: [{ - impid: 'test-requestId', - cpm: 1.23, - ad: 'test-ad', - width: 728, - height: 90, - }], + body: { + slots: [{ + impid: 'test-requestId', + cpm: 1.23, + creative: 'test-ad', + width: 728, + height: 90, + }], + }, }; const bids = spec.interpretResponse(response, null); expect(bids).to.have.lengthOf(1); From 761a2031ff2b101297978aa5f9e1143bd7d6becf Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Thu, 7 Dec 2017 11:37:18 +0100 Subject: [PATCH 09/37] Pass the bid requests to the Criteo interpret method --- modules/criteoBidAdapter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 2b8c38275bf..e5713074c9a 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -48,7 +48,7 @@ export const spec = { data = buildCdbRequest(context, bidRequests); } - return { method: 'POST', url, data }; + return { method: 'POST', url, data, bidRequests }; }, /** @@ -58,8 +58,8 @@ export const spec = { */ interpretResponse: (response, request) => { if (typeof Criteo !== 'undefined') { - const adapter = Criteo.PubTag.Adapters.Prebid.GetAdapter(request.data); - return adapter.interpretResponse(response.body); + const adapter = Criteo.PubTag.Adapters.Prebid.GetAdapter(request); + return adapter.interpretResponse(response.body, request); } const bids = []; From 6a8ea52f94c9f562932a31cf1f499fa2a739eb49 Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Thu, 7 Dec 2017 11:38:56 +0100 Subject: [PATCH 10/37] Add missing ttl and creativeId fields to Criteo bids --- modules/criteoBidAdapter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index e5713074c9a..7750a789aa6 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -72,6 +72,8 @@ export const spec = { currency: slot.currency, netRevenue: true, ad: slot.creative, + ttl: slot.ttl || 60, + creativeId: slot.impid, width: slot.width, height: slot.height, } From d4ff98e2053e13ed489d9182380223bb74239aaf Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Thu, 7 Dec 2017 11:54:39 +0100 Subject: [PATCH 11/37] Add 'native' support to the Criteo adapter --- modules/criteoBidAdapter.js | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 7750a789aa6..c873dea3d98 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -71,12 +71,17 @@ export const spec = { cpm: slot.cpm, currency: slot.currency, netRevenue: true, - ad: slot.creative, ttl: slot.ttl || 60, creativeId: slot.impid, width: slot.width, height: slot.height, } + if (slot.native) { + const bidRequest = request.bidRequests.find(b => b.bidId === slot.impid); + bid.ad = createNativeAd(slot.impid, slot.native, bidRequest.params.nativeCallback); + } else { + bid.ad = slot.creative; + } bids.push(bid); }); } @@ -157,6 +162,9 @@ function buildCdbRequest(context, bidRequests) { if (bidRequest.params.publisherSubId) { slot.publishersubid = bidRequest.params.publisherSubId; } + if (bidRequest.params.nativeCallback) { + slot.native = true; + } return slot; }), }; @@ -166,6 +174,32 @@ function buildCdbRequest(context, bidRequests) { return request; } +/** + * @param {string} id + * @param {*} payload + * @param {*} callback + * @return {string} + */ +function createNativeAd(id, payload, callback) { + // Store the callback and payload in a global object to be later accessed from the creative + window.criteo_prebid_native_slots = window.criteo_prebid_native_slots || {}; + window.criteo_prebid_native_slots[id] = { callback, payload }; + + // The creative is in an iframe so we have to get the callback and payload + // from the parent window (doesn't work with safeframes) + return ``; +} + /** * @return {boolean} */ From b7d85e7dfe97199ff5aa54c53d944e9746150dcc Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Mon, 11 Dec 2017 14:18:40 +0100 Subject: [PATCH 12/37] Check that the Criteo adapter returned by PublisherTag is not empty --- modules/criteoBidAdapter.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index c873dea3d98..215957692ed 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -59,7 +59,9 @@ export const spec = { interpretResponse: (response, request) => { if (typeof Criteo !== 'undefined') { const adapter = Criteo.PubTag.Adapters.Prebid.GetAdapter(request); - return adapter.interpretResponse(response.body, request); + if (adapter) { + return adapter.interpretResponse(response.body, request); + } } const bids = []; From 675d3eab15711a19d12602a2f8eecb8ea30660ec Mon Sep 17 00:00:00 2001 From: Nicolas Faure Date: Tue, 12 Dec 2017 17:43:12 +0100 Subject: [PATCH 13/37] Fix 'assign to const' IE errors in Criteo native adapter --- modules/criteoBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 215957692ed..1bd9a6cd2a9 100755 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -191,7 +191,7 @@ function createNativeAd(id, payload, callback) { // from the parent window (doesn't work with safeframes) return `