From 325c162276d43804a01ae815513b595b865977ec Mon Sep 17 00:00:00 2001 From: Alexander Bogdanov Date: Mon, 15 Nov 2021 17:03:22 +0700 Subject: [PATCH 01/20] Alkimi bid adapter --- modules/alkimiAdapter.js | 105 ++++++++++++++++ modules/alkimiAdapter.md | 29 +++++ test/spec/modules/alkimiAdapter_spec.js | 161 ++++++++++++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 modules/alkimiAdapter.js create mode 100644 modules/alkimiAdapter.md create mode 100644 test/spec/modules/alkimiAdapter_spec.js diff --git a/modules/alkimiAdapter.js b/modules/alkimiAdapter.js new file mode 100644 index 00000000000..705057f5c77 --- /dev/null +++ b/modules/alkimiAdapter.js @@ -0,0 +1,105 @@ +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { deepClone, deepAccess } from '../src/utils.js'; +import { ajax } from '../src/ajax.js'; +import { VIDEO } from '../src/mediaTypes.js'; + +const BIDDER_CODE = 'alkimi'; +export const ENDPOINT = 'https://exchange-qa.alkimi.asteriosoft.com/bid?prebid=true' + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: ['banner', 'video'], + + isBidRequestValid: function (bid) { + return !!(bid.params && bid.params.bidFloor && bid.params.publisherToken); + }, + + buildRequests: function (validBidRequests, bidderRequest) { + let bids = []; + validBidRequests.forEach(bidRequest => { + let sizes = prepareSizes(bidRequest.sizes) + + bids.push({ + bidId: bidRequest.bidId, + publisherToken: bidRequest.params.publisherToken, + pos: bidRequest.params.pos, + bidFloor: bidRequest.params.bidFloor, + width: sizes[0].width, + height: sizes[0].height, + impMediaType: getFormatType(bidRequest) + }) + }) + + let payload = { + requestId: bidderRequest.bidderRequestId, + bids, + referer: bidderRequest.refererInfo.referer + } + + const options = { + contentType: 'application/json', + customHeaders: { + 'Rtb-Direct': true + } + } + + return { + method: 'POST', + url: ENDPOINT, + data: payload, + options + }; + }, + + interpretResponse: function (serverResponse, request) { + const serverBody = serverResponse.body; + if (!serverBody || typeof serverBody !== 'object') { + return []; + } + + const { prebidResponse } = serverBody; + if (!prebidResponse || typeof prebidResponse !== 'object') { + return []; + } + + let bids = []; + prebidResponse.forEach(bidResponse => { + let bid = deepClone(bidResponse); + bid.cpm = parseFloat(bidResponse.cpm); + + // banner or video + if (VIDEO === bid.format) { + bid.vastXml = bid.ad; + } + + bid.meta = {}; + bid.meta.advertiserDomains = bid.adomain || []; + + bids.push(bid); + }) + + return bids; + }, + + onBidWon: function (bid) { + if (bid.winUrl) { + const cpm = bid.cpm; + const winUrl = bid.winUrl.replace(/\$\{AUCTION_PRICE\}/, cpm); + ajax(winUrl, null); + return true; + } + return false; + } +} + +function prepareSizes(sizes) { + return sizes && sizes.map(size => ({ width: size[0], height: size[1] })); +} + +const getFormatType = bidRequest => { + if (deepAccess(bidRequest, 'mediaTypes.banner')) return 'Banner' + if (deepAccess(bidRequest, 'mediaTypes.video')) return 'Video' + if (deepAccess(bidRequest, 'mediaTypes.audio')) return 'Audio' +} + +registerBidder(spec); diff --git a/modules/alkimiAdapter.md b/modules/alkimiAdapter.md new file mode 100644 index 00000000000..dbaea323ef3 --- /dev/null +++ b/modules/alkimiAdapter.md @@ -0,0 +1,29 @@ +# Overview + +``` +Module Name: Alkimi Bidder Adapter +Module Type: Bidder Adapter +Maintainer: abogdanov@asteriosoft.com +``` + +# Description + +Connects to Alkimi Bidder for bids. +Alkimi bid adapter supports Banner and Video ads. + +# Test Parameters +``` +const adUnits = [ + { + bids: [ + { + bidder: 'alkimi', + params: { + bidFloor: 0.1 + publisherToken: '?????????????????????', // zoneToken provided by Alkimi + } + } + ] + } +]; +``` diff --git a/test/spec/modules/alkimiAdapter_spec.js b/test/spec/modules/alkimiAdapter_spec.js new file mode 100644 index 00000000000..055fb9eb026 --- /dev/null +++ b/test/spec/modules/alkimiAdapter_spec.js @@ -0,0 +1,161 @@ +import { expect } from 'chai' +import { ENDPOINT, spec } from 'modules/alkimiAdapter.js' +import { newBidder } from 'src/adapters/bidderFactory.js' + +const REQUEST = { + 'bidId': '456', + 'bidder': 'alkimi', + 'sizes': [[300, 250]], + 'mediaTypes': { + 'banner': { + 'sizes': [[300, 250]] + } + }, + 'params': { + bidFloor: 0.1, + publisherToken: 'e64782a4-8e68-4c38-965b-80ccf115d46f', + pos: 7 + } +} + +const BIDDER_BANNER_RESPONSE = { + 'prebidResponse': [{ + 'ad': '
test
', + 'requestId': 'e64782a4-8e68-4c38-965b-80ccf115d46d', + 'cpm': 900.5, + 'currency': 'USD', + 'width': 640, + 'height': 480, + 'ttl': 300, + 'creativeId': 1, + 'netRevenue': true, + 'winUrl': 'http://test.com', + 'format': 'banner', + 'adomain': ['test.com'] + }] +} + +const BIDDER_VIDEO_RESPONSE = { + 'prebidResponse': [{ + 'ad': 'vast', + 'requestId': 'e64782a4-8e68-4c38-965b-80ccf115d46z', + 'cpm': 800.4, + 'currency': 'USD', + 'width': 1024, + 'height': 768, + 'ttl': 200, + 'creativeId': 2, + 'netRevenue': true, + 'winUrl': 'http://test.com', + 'format': 'video', + 'adomain': ['test.com'] + }] +} + +const BIDDER_NO_BID_RESPONSE = '' + +describe('alkimiAdapter', function () { + const adapter = newBidder(spec) + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function') + }) + }) + + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(REQUEST)).to.equal(true) + }) + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, REQUEST) + delete bid.params.publisherToken + expect(spec.isBidRequestValid(bid)).to.equal(false) + + bid = Object.assign({}, REQUEST) + delete bid.params.bidFloor + expect(spec.isBidRequestValid(bid)).to.equal(false) + + bid = Object.assign({}, REQUEST) + delete bid.params + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + }) + + describe('buildRequests', function () { + let bidRequests = [REQUEST] + const bidderRequest = spec.buildRequests(bidRequests, { + bidderRequestId: '123', + refererInfo: { + referer: 'http://test.com/path.html' + } + }) + + it('sends bid request to ENDPOINT via POST', function () { + expect(bidderRequest.method).to.equal('POST') + expect(bidderRequest.data.requestId).to.equal('123') + expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') + expect(bidderRequest.data.bids).to.deep.contains({ bidId: '456', publisherToken: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner' }) + expect(bidderRequest.options.customHeaders).to.deep.equal({ 'Rtb-Direct': true }) + expect(bidderRequest.options.contentType).to.equal('application/json') + expect(bidderRequest.url).to.equal(ENDPOINT) + }) + }) + + describe('interpretResponse', function () { + it('handles banner request : should get correct bid response', function () { + const result = spec.interpretResponse({ body: BIDDER_BANNER_RESPONSE }, {}) + + expect(result[0]).to.have.property('ad').equal('
test
') + expect(result[0]).to.have.property('requestId').equal('e64782a4-8e68-4c38-965b-80ccf115d46d') + expect(result[0]).to.have.property('cpm').equal(900.5) + expect(result[0]).to.have.property('currency').equal('USD') + expect(result[0]).to.have.property('width').equal(640) + expect(result[0]).to.have.property('height').equal(480) + expect(result[0]).to.have.property('ttl').equal(300) + expect(result[0]).to.have.property('creativeId').equal(1) + expect(result[0]).to.have.property('netRevenue').equal(true) + expect(result[0]).to.have.property('winUrl').equal('http://test.com') + expect(result[0]).to.have.property('format').equal('banner') + expect(result[0].meta).to.exist.property('advertiserDomains') + expect(result[0].meta).to.have.property('advertiserDomains').lengthOf(1) + }) + + it('handles video request : should get correct bid response', function () { + const result = spec.interpretResponse({ body: BIDDER_VIDEO_RESPONSE }, {}) + + expect(result[0]).to.have.property('ad').equal('vast') + expect(result[0]).to.have.property('requestId').equal('e64782a4-8e68-4c38-965b-80ccf115d46z') + expect(result[0]).to.have.property('cpm').equal(800.4) + expect(result[0]).to.have.property('currency').equal('USD') + expect(result[0]).to.have.property('width').equal(1024) + expect(result[0]).to.have.property('height').equal(768) + expect(result[0]).to.have.property('ttl').equal(200) + expect(result[0]).to.have.property('creativeId').equal(2) + expect(result[0]).to.have.property('netRevenue').equal(true) + expect(result[0]).to.have.property('winUrl').equal('http://test.com') + expect(result[0]).to.have.property('format').equal('video') + expect(result[0]).to.have.property('vastXml').equal('vast') + expect(result[0].meta).to.exist.property('advertiserDomains') + expect(result[0].meta).to.have.property('advertiserDomains').lengthOf(1) + }) + + it('handles no bid response : should get empty array', function () { + let result = spec.interpretResponse({ body: undefined }, {}) + expect(result).to.deep.equal([]) + + result = spec.interpretResponse({ body: BIDDER_NO_BID_RESPONSE }, {}) + expect(result).to.deep.equal([]) + }) + }) + + describe('onBidWon', function () { + it('handles banner win: should get true', function () { + const win = BIDDER_BANNER_RESPONSE.prebidResponse[0] + const bidWonResult = spec.onBidWon(win) + + expect(bidWonResult).to.equal(true) + }) + }) +}) From df09e0d10b110e7e63f2a515dd738b69e5f3f49f Mon Sep 17 00:00:00 2001 From: Alexander Bogdanov Date: Wed, 17 Nov 2021 10:50:58 +0700 Subject: [PATCH 02/20] Alkimi bid adapter --- modules/alkimiAdapter.js | 4 ++-- modules/alkimiAdapter.md | 4 ++-- test/spec/modules/alkimiAdapter_spec.js | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/alkimiAdapter.js b/modules/alkimiAdapter.js index 705057f5c77..e89212e614a 100644 --- a/modules/alkimiAdapter.js +++ b/modules/alkimiAdapter.js @@ -11,7 +11,7 @@ export const spec = { supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - return !!(bid.params && bid.params.bidFloor && bid.params.publisherToken); + return !!(bid.params && bid.params.bidFloor && bid.params.token); }, buildRequests: function (validBidRequests, bidderRequest) { @@ -21,7 +21,7 @@ export const spec = { bids.push({ bidId: bidRequest.bidId, - publisherToken: bidRequest.params.publisherToken, + token: bidRequest.params.token, pos: bidRequest.params.pos, bidFloor: bidRequest.params.bidFloor, width: sizes[0].width, diff --git a/modules/alkimiAdapter.md b/modules/alkimiAdapter.md index dbaea323ef3..92a7c2aefe1 100644 --- a/modules/alkimiAdapter.md +++ b/modules/alkimiAdapter.md @@ -19,8 +19,8 @@ const adUnits = [ { bidder: 'alkimi', params: { - bidFloor: 0.1 - publisherToken: '?????????????????????', // zoneToken provided by Alkimi + bidFloor: 0.1, + token: '?????????????????????', // Publisher Token provided by Alkimi } } ] diff --git a/test/spec/modules/alkimiAdapter_spec.js b/test/spec/modules/alkimiAdapter_spec.js index 055fb9eb026..6013b2bfbee 100644 --- a/test/spec/modules/alkimiAdapter_spec.js +++ b/test/spec/modules/alkimiAdapter_spec.js @@ -13,7 +13,7 @@ const REQUEST = { }, 'params': { bidFloor: 0.1, - publisherToken: 'e64782a4-8e68-4c38-965b-80ccf115d46f', + token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7 } } @@ -70,7 +70,7 @@ describe('alkimiAdapter', function () { it('should return false when required params are not passed', function () { let bid = Object.assign({}, REQUEST) - delete bid.params.publisherToken + delete bid.params.token expect(spec.isBidRequestValid(bid)).to.equal(false) bid = Object.assign({}, REQUEST) @@ -96,7 +96,7 @@ describe('alkimiAdapter', function () { expect(bidderRequest.method).to.equal('POST') expect(bidderRequest.data.requestId).to.equal('123') expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') - expect(bidderRequest.data.bids).to.deep.contains({ bidId: '456', publisherToken: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner' }) + expect(bidderRequest.data.bids).to.deep.contains({ bidId: '456', token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner' }) expect(bidderRequest.options.customHeaders).to.deep.equal({ 'Rtb-Direct': true }) expect(bidderRequest.options.contentType).to.equal('application/json') expect(bidderRequest.url).to.equal(ENDPOINT) From b3e36881c248a6aebd2d8c2a4507162d800b4dbf Mon Sep 17 00:00:00 2001 From: Alexander Bogdanov Date: Wed, 17 Nov 2021 16:17:43 +0700 Subject: [PATCH 03/20] Alkimi bid adapter --- modules/alkimiAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/alkimiAdapter.js b/modules/alkimiAdapter.js index e89212e614a..cdd0dabc68c 100644 --- a/modules/alkimiAdapter.js +++ b/modules/alkimiAdapter.js @@ -4,7 +4,7 @@ import { ajax } from '../src/ajax.js'; import { VIDEO } from '../src/mediaTypes.js'; const BIDDER_CODE = 'alkimi'; -export const ENDPOINT = 'https://exchange-qa.alkimi.asteriosoft.com/bid?prebid=true' +export const ENDPOINT = 'https://exchange-dev.alkimi.asteriosoft.com/bid?prebid=true' export const spec = { code: BIDDER_CODE, @@ -68,7 +68,7 @@ export const spec = { bid.cpm = parseFloat(bidResponse.cpm); // banner or video - if (VIDEO === bid.format) { + if (VIDEO === bid.mediaType) { bid.vastXml = bid.ad; } From 144cda7ab87bafaa182985a91d74138a5613e98a Mon Sep 17 00:00:00 2001 From: Alexander Bogdanov Date: Mon, 7 Feb 2022 11:42:22 +0700 Subject: [PATCH 04/20] alkimi adapter --- modules/alkimiAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/alkimiAdapter.js b/modules/alkimiAdapter.js index cdd0dabc68c..db2760914b1 100644 --- a/modules/alkimiAdapter.js +++ b/modules/alkimiAdapter.js @@ -4,7 +4,7 @@ import { ajax } from '../src/ajax.js'; import { VIDEO } from '../src/mediaTypes.js'; const BIDDER_CODE = 'alkimi'; -export const ENDPOINT = 'https://exchange-dev.alkimi.asteriosoft.com/bid?prebid=true' +export const ENDPOINT = 'https://exchange-dev.alkimi.asteriosoft.com/bid?prebid=true'; export const spec = { code: BIDDER_CODE, From c14dcd2fb6acf306f91a4eec057053188d47385b Mon Sep 17 00:00:00 2001 From: Alexander Bogdanov Date: Tue, 8 Feb 2022 13:18:20 +0700 Subject: [PATCH 05/20] onBidWon change --- modules/alkimiAdapter.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/modules/alkimiAdapter.js b/modules/alkimiAdapter.js index db2760914b1..d819fb76d5e 100644 --- a/modules/alkimiAdapter.js +++ b/modules/alkimiAdapter.js @@ -2,6 +2,7 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { deepClone, deepAccess } from '../src/utils.js'; import { ajax } from '../src/ajax.js'; import { VIDEO } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; const BIDDER_CODE = 'alkimi'; export const ENDPOINT = 'https://exchange-dev.alkimi.asteriosoft.com/bid?prebid=true'; @@ -16,11 +17,11 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { let bids = []; + let bidIds = []; validBidRequests.forEach(bidRequest => { let sizes = prepareSizes(bidRequest.sizes) bids.push({ - bidId: bidRequest.bidId, token: bidRequest.params.token, pos: bidRequest.params.pos, bidFloor: bidRequest.params.bidFloor, @@ -28,12 +29,17 @@ export const spec = { height: sizes[0].height, impMediaType: getFormatType(bidRequest) }) + bidIds.push(bidRequest.bidId) }) + const alkimiConfig = config.getConfig('alkimi'); + let payload = { requestId: bidderRequest.bidderRequestId, bids, - referer: bidderRequest.refererInfo.referer + bidIds, + referer: bidderRequest.refererInfo.referer, + signature: alkimiConfig && alkimiConfig.signature } const options = { @@ -82,13 +88,21 @@ export const spec = { }, onBidWon: function (bid) { - if (bid.winUrl) { - const cpm = bid.cpm; - const winUrl = bid.winUrl.replace(/\$\{AUCTION_PRICE\}/, cpm); - ajax(winUrl, null); - return true; + let winUrl; + if (bid.winUrl || bid.vastUrl) { + winUrl = bid.winUrl ? bid.winUrl : bid.vastUrl; + winUrl = winUrl.replace(/\$\{AUCTION_PRICE\}/, bid.cpm); + } else if (bid.ad) { + let trackImg = bid.ad.match(/(?!^)/); + bid.ad = bid.ad.replace(trackImg[0], ''); + winUrl = trackImg[0].split('"')[1]; + winUrl = winUrl.replace(/\$%7BAUCTION_PRICE%7D/, bid.cpm); + } else { + return false; } - return false; + + ajax(winUrl, null); + return true; } } From ddec9979c8e0604ccb495283d9dbd223d23329c7 Mon Sep 17 00:00:00 2001 From: Alexander Bogdanov Date: Tue, 8 Feb 2022 15:37:48 +0700 Subject: [PATCH 06/20] sign utils --- modules/alkimiAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/alkimiAdapter.js b/modules/alkimiAdapter.js index d819fb76d5e..b8f6a3c2c31 100644 --- a/modules/alkimiAdapter.js +++ b/modules/alkimiAdapter.js @@ -36,7 +36,7 @@ export const spec = { let payload = { requestId: bidderRequest.bidderRequestId, - bids, + signRequest: { bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID }, bidIds, referer: bidderRequest.refererInfo.referer, signature: alkimiConfig && alkimiConfig.signature From 068c546806a1ac3f7c8818416e5f3126bbfb8f21 Mon Sep 17 00:00:00 2001 From: Alexander Bogdanov Date: Thu, 24 Feb 2022 14:57:50 +0700 Subject: [PATCH 07/20] auction ID as bid request ID --- modules/alkimiAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/alkimiAdapter.js b/modules/alkimiAdapter.js index b8f6a3c2c31..a68f2478e55 100644 --- a/modules/alkimiAdapter.js +++ b/modules/alkimiAdapter.js @@ -35,7 +35,7 @@ export const spec = { const alkimiConfig = config.getConfig('alkimi'); let payload = { - requestId: bidderRequest.bidderRequestId, + requestId: bidderRequest.auctionId, signRequest: { bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID }, bidIds, referer: bidderRequest.refererInfo.referer, From bf432c4d60f3cd26e0efb2b06f0b131cbcd199f0 Mon Sep 17 00:00:00 2001 From: alexander bogdanov Date: Wed, 27 Apr 2022 13:12:40 +0700 Subject: [PATCH 08/20] unit test fixes --- .../{alkimiAdapter.js => alkimiBidAdapter.js} | 2 +- .../{alkimiAdapter.md => alkimiBidAdapter.md} | 0 ...apter_spec.js => alkimiBidAdapter_spec.js} | 19 +++++++++++-------- 3 files changed, 12 insertions(+), 9 deletions(-) rename modules/{alkimiAdapter.js => alkimiBidAdapter.js} (97%) rename modules/{alkimiAdapter.md => alkimiBidAdapter.md} (100%) rename test/spec/modules/{alkimiAdapter_spec.js => alkimiBidAdapter_spec.js} (88%) diff --git a/modules/alkimiAdapter.js b/modules/alkimiBidAdapter.js similarity index 97% rename from modules/alkimiAdapter.js rename to modules/alkimiBidAdapter.js index a68f2478e55..261fd9dee68 100644 --- a/modules/alkimiAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -5,7 +5,7 @@ import { VIDEO } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; const BIDDER_CODE = 'alkimi'; -export const ENDPOINT = 'https://exchange-dev.alkimi.asteriosoft.com/bid?prebid=true'; +export const ENDPOINT = 'https://exchange.alkimi-onboarding.com/bid?prebid=true'; export const spec = { code: BIDDER_CODE, diff --git a/modules/alkimiAdapter.md b/modules/alkimiBidAdapter.md similarity index 100% rename from modules/alkimiAdapter.md rename to modules/alkimiBidAdapter.md diff --git a/test/spec/modules/alkimiAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js similarity index 88% rename from test/spec/modules/alkimiAdapter_spec.js rename to test/spec/modules/alkimiBidAdapter_spec.js index 6013b2bfbee..58a5a3b54ab 100644 --- a/test/spec/modules/alkimiAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai' -import { ENDPOINT, spec } from 'modules/alkimiAdapter.js' +import { ENDPOINT, spec } from 'modules/alkimiBidAdapter.js' import { newBidder } from 'src/adapters/bidderFactory.js' const REQUEST = { @@ -30,7 +30,7 @@ const BIDDER_BANNER_RESPONSE = { 'creativeId': 1, 'netRevenue': true, 'winUrl': 'http://test.com', - 'format': 'banner', + 'mediaType': 'banner', 'adomain': ['test.com'] }] } @@ -47,14 +47,14 @@ const BIDDER_VIDEO_RESPONSE = { 'creativeId': 2, 'netRevenue': true, 'winUrl': 'http://test.com', - 'format': 'video', + 'mediaType': 'video', 'adomain': ['test.com'] }] } const BIDDER_NO_BID_RESPONSE = '' -describe('alkimiAdapter', function () { +describe('alkimiBidAdapter', function () { const adapter = newBidder(spec) describe('inherited functions', function () { @@ -86,7 +86,7 @@ describe('alkimiAdapter', function () { describe('buildRequests', function () { let bidRequests = [REQUEST] const bidderRequest = spec.buildRequests(bidRequests, { - bidderRequestId: '123', + auctionId: '123', refererInfo: { referer: 'http://test.com/path.html' } @@ -96,7 +96,10 @@ describe('alkimiAdapter', function () { expect(bidderRequest.method).to.equal('POST') expect(bidderRequest.data.requestId).to.equal('123') expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') - expect(bidderRequest.data.bids).to.deep.contains({ bidId: '456', token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner' }) + expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner' }) + expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) + expect(bidderRequest.data.bidIds).to.deep.contains('456') + expect(bidderRequest.data.signature).to.equal(undefined) expect(bidderRequest.options.customHeaders).to.deep.equal({ 'Rtb-Direct': true }) expect(bidderRequest.options.contentType).to.equal('application/json') expect(bidderRequest.url).to.equal(ENDPOINT) @@ -117,7 +120,7 @@ describe('alkimiAdapter', function () { expect(result[0]).to.have.property('creativeId').equal(1) expect(result[0]).to.have.property('netRevenue').equal(true) expect(result[0]).to.have.property('winUrl').equal('http://test.com') - expect(result[0]).to.have.property('format').equal('banner') + expect(result[0]).to.have.property('mediaType').equal('banner') expect(result[0].meta).to.exist.property('advertiserDomains') expect(result[0].meta).to.have.property('advertiserDomains').lengthOf(1) }) @@ -135,7 +138,7 @@ describe('alkimiAdapter', function () { expect(result[0]).to.have.property('creativeId').equal(2) expect(result[0]).to.have.property('netRevenue').equal(true) expect(result[0]).to.have.property('winUrl').equal('http://test.com') - expect(result[0]).to.have.property('format').equal('video') + expect(result[0]).to.have.property('mediaType').equal('video') expect(result[0]).to.have.property('vastXml').equal('vast') expect(result[0].meta).to.exist.property('advertiserDomains') expect(result[0].meta).to.have.property('advertiserDomains').lengthOf(1) From 76afe9b6d9e6e2fc42f39eed410b39c652255125 Mon Sep 17 00:00:00 2001 From: motors Date: Wed, 11 May 2022 16:46:09 +0700 Subject: [PATCH 09/20] change maintainer info --- modules/alkimiBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/alkimiBidAdapter.md b/modules/alkimiBidAdapter.md index 92a7c2aefe1..0d76f7e63ab 100644 --- a/modules/alkimiBidAdapter.md +++ b/modules/alkimiBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: Alkimi Bidder Adapter Module Type: Bidder Adapter -Maintainer: abogdanov@asteriosoft.com +Maintainer: kalidas@alkimiexchange.com ``` # Description From 7dc389dad79979d9ceba034abc33a7fc4e24d637 Mon Sep 17 00:00:00 2001 From: Kalidas Engaiahraj Date: Mon, 16 May 2022 18:54:25 +0100 Subject: [PATCH 10/20] Updated the ad unit params --- modules/alkimiBidAdapter.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/alkimiBidAdapter.md b/modules/alkimiBidAdapter.md index 0d76f7e63ab..2d1fd42c70f 100644 --- a/modules/alkimiBidAdapter.md +++ b/modules/alkimiBidAdapter.md @@ -15,15 +15,21 @@ Alkimi bid adapter supports Banner and Video ads. ``` const adUnits = [ { - bids: [ + code: 'banner1', + mediaTypes: { + banner: { // Media Type can be banner or video or ... + sizes: [[300, 250]], + } + }, + bids: [ { bidder: 'alkimi', params: { - bidFloor: 0.1, - token: '?????????????????????', // Publisher Token provided by Alkimi + bidFloor: 0.5, + token: 'a6b042a5-2d68-4170-a051-77fbaf00203a', // Publisher Token(Id) provided by Alkimi } } ] } -]; +] ``` From ea2a9bffdc80b589fbfdd102aa6f442e6db94da3 Mon Sep 17 00:00:00 2001 From: Nikulin Mikhail Date: Tue, 31 May 2022 19:02:39 +0200 Subject: [PATCH 11/20] features support added --- modules/alkimiBidAdapter.js | 23 ++++++++++- test/spec/modules/alkimiBidAdapter_spec.js | 44 +++++++++++++++++++++- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index 261fd9dee68..d76af4b14e9 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -18,9 +18,13 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { let bids = []; let bidIds = []; + let eids; validBidRequests.forEach(bidRequest => { let sizes = prepareSizes(bidRequest.sizes) + if (bidRequest.userIdAsEids) { + eids = eids || bidRequest.userIdAsEids + } bids.push({ token: bidRequest.params.token, pos: bidRequest.params.pos, @@ -39,7 +43,24 @@ export const spec = { signRequest: { bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID }, bidIds, referer: bidderRequest.refererInfo.referer, - signature: alkimiConfig && alkimiConfig.signature + signature: alkimiConfig && alkimiConfig.signature, + schain: validBidRequests[0].schain, + cpp: config.getConfig('coppa') ? 1 : 0 + } + + if (bidderRequest && bidderRequest.gdprConsent) { + payload.gdprConsent = { + consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : false, + consentString: bidderRequest.gdprConsent.consentString + } + } + + if (bidderRequest.uspConsent) { + payload.uspConsent = bidderRequest.uspConsent; + } + + if (eids) { + payload.eids = eids } const options = { diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index 58a5a3b54ab..e0b1df9cae8 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -15,6 +15,28 @@ const REQUEST = { bidFloor: 0.1, token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7 + }, + 'userIdAsEids': [{ + 'source': 'criteo.com', + 'uids': [{ + 'id': 'test', + 'atype': 1 + }] + }, { + 'source': 'pubcid.org', + 'uids': [{ + 'id': 'test', + 'atype': 1 + }] + }], + 'schain': { + ver: '1.0', + complete: 1, + nodes: [{ + asi: 'alkimi-onboarding.com', + sid: '00001', + hp: 1 + }] } } @@ -89,13 +111,33 @@ describe('alkimiBidAdapter', function () { auctionId: '123', refererInfo: { referer: 'http://test.com/path.html' - } + }, + gdprConsent: { + consentString: 'test-consent', + vendorData: {}, + gdprApplies: true + }, + uspConsent: 'uspConsent' + }) + + it('should return a properly formatted request with eids defined', function () { + expect(bidderRequest.data.eids).to.deep.equal(REQUEST.userIdAsEids) + }) + + it('should return a properly formatted request with gdpr defined', function () { + expect(bidderRequest.data.gdprConsent.consentRequired).to.equal(true) + expect(bidderRequest.data.gdprConsent.consentString).to.equal('test-consent') + }) + + it('should return a properly formatted request with uspConsent defined', function () { + expect(bidderRequest.data.uspConsent).to.equal('uspConsent') }) it('sends bid request to ENDPOINT via POST', function () { expect(bidderRequest.method).to.equal('POST') expect(bidderRequest.data.requestId).to.equal('123') expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') + expect(bidderRequest.data.schain).to.deep.contains({ver: '1.0', complete: 1, nodes: [{asi: 'alkimi-onboarding.com', sid: '00001', hp: 1}]}) expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner' }) expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) expect(bidderRequest.data.bidIds).to.deep.contains('456') From 74f8e1272b96e0b2bd9e8cdb40bd3ed093e3be55 Mon Sep 17 00:00:00 2001 From: alexander bogdanov Date: Wed, 24 Aug 2022 16:09:00 +0200 Subject: [PATCH 12/20] transfer adUnitCode --- modules/alkimiBidAdapter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index ac8b5af9533..fe5a050f436 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -31,7 +31,8 @@ export const spec = { bidFloor: bidRequest.params.bidFloor, width: sizes[0].width, height: sizes[0].height, - impMediaType: getFormatType(bidRequest) + impMediaType: getFormatType(bidRequest), + adUnitCode: bidRequest.adUnitCode }) bidIds.push(bidRequest.bidId) }) From 0a0d8e8bacd18d0b6279942aa90abd92fee6b30c Mon Sep 17 00:00:00 2001 From: alexander bogdanov Date: Wed, 24 Aug 2022 17:38:39 +0200 Subject: [PATCH 13/20] transfer adUnitCode: test --- test/spec/modules/alkimiBidAdapter_spec.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index c98c81b706e..1ae9bb56df4 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -6,6 +6,7 @@ const REQUEST = { 'bidId': '456', 'bidder': 'alkimi', 'sizes': [[300, 250]], + 'adUnitCode': 'bannerAdUnitCode', 'mediaTypes': { 'banner': { 'sizes': [[300, 250]] @@ -138,7 +139,7 @@ describe('alkimiBidAdapter', function () { expect(bidderRequest.data.requestId).to.equal('123') expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') expect(bidderRequest.data.schain).to.deep.contains({ver: '1.0', complete: 1, nodes: [{asi: 'alkimi-onboarding.com', sid: '00001', hp: 1}]}) - expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner' }) + expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner', adUnitCode: 'bannerAdUnitCode' }) expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) expect(bidderRequest.data.bidIds).to.deep.contains('456') expect(bidderRequest.data.signature).to.equal(undefined) From 41b6ca3de83d4130dea5da7bfc000fceb1c55b8a Mon Sep 17 00:00:00 2001 From: Aleksandr Bogdanov Date: Thu, 22 Dec 2022 15:34:37 +0100 Subject: [PATCH 14/20] AlkimiBidAdapter getFloor() using --- modules/alkimiBidAdapter.js | 29 +++++++++++++++++----- test/spec/modules/alkimiBidAdapter_spec.js | 18 +++++++++++--- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index fe5a050f436..a96b245d786 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -20,18 +20,20 @@ export const spec = { let bidIds = []; let eids; validBidRequests.forEach(bidRequest => { - let sizes = prepareSizes(bidRequest.sizes) + let formatType = getFormatType(bidRequest) + let alkimiSizes = prepareAlkimiSizes(bidRequest.sizes) if (bidRequest.userIdAsEids) { eids = eids || bidRequest.userIdAsEids } + bids.push({ token: bidRequest.params.token, pos: bidRequest.params.pos, - bidFloor: bidRequest.params.bidFloor, - width: sizes[0].width, - height: sizes[0].height, - impMediaType: getFormatType(bidRequest), + bidFloor: getBidFloor(bidRequest, formatType), + width: alkimiSizes[0].width, + height: alkimiSizes[0].height, + impMediaType: formatType, adUnitCode: bidRequest.adUnitCode }) bidIds.push(bidRequest.bidId) @@ -128,10 +130,25 @@ export const spec = { } } -function prepareSizes(sizes) { +function prepareAlkimiSizes(sizes) { return sizes && sizes.map(size => ({ width: size[0], height: size[1] })); } +function prepareBidFloorSize(sizes) { + return sizes && sizes.length === 1 ? sizes[0] : '*'; +} + +function getBidFloor(bidRequest, formatType) { + if (typeof bidRequest.getFloor === 'function') { + const bidFloorSize = prepareBidFloorSize(bidRequest.sizes) + const floor = bidRequest.getFloor({ currency: 'USD', mediaType: formatType.toLowerCase(), size: bidFloorSize }); + if (floor && !isNaN(floor.floor) && (floor.currency === 'USD')) { + return floor.floor; + } + } + return bidRequest.params.bidFloor; +} + const getFormatType = bidRequest => { if (deepAccess(bidRequest, 'mediaTypes.banner')) return 'Banner' if (deepAccess(bidRequest, 'mediaTypes.video')) return 'Video' diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index 1ae9bb56df4..92e5d28f42a 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -108,7 +108,7 @@ describe('alkimiBidAdapter', function () { describe('buildRequests', function () { let bidRequests = [REQUEST] - const bidderRequest = spec.buildRequests(bidRequests, { + let requestData = { auctionId: '123', refererInfo: { page: 'http://test.com/path.html' @@ -119,7 +119,8 @@ describe('alkimiBidAdapter', function () { gdprApplies: true }, uspConsent: 'uspConsent' - }) + } + const bidderRequest = spec.buildRequests(bidRequests, requestData) it('should return a properly formatted request with eids defined', function () { expect(bidderRequest.data.eids).to.deep.equal(REQUEST.userIdAsEids) @@ -138,7 +139,7 @@ describe('alkimiBidAdapter', function () { expect(bidderRequest.method).to.equal('POST') expect(bidderRequest.data.requestId).to.equal('123') expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') - expect(bidderRequest.data.schain).to.deep.contains({ver: '1.0', complete: 1, nodes: [{asi: 'alkimi-onboarding.com', sid: '00001', hp: 1}]}) + expect(bidderRequest.data.schain).to.deep.contains({ ver: '1.0', complete: 1, nodes: [{ asi: 'alkimi-onboarding.com', sid: '00001', hp: 1 }] }) expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner', adUnitCode: 'bannerAdUnitCode' }) expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) expect(bidderRequest.data.bidIds).to.deep.contains('456') @@ -147,6 +148,17 @@ describe('alkimiBidAdapter', function () { expect(bidderRequest.options.contentType).to.equal('application/json') expect(bidderRequest.url).to.equal(ENDPOINT) }) + + it('sends bidFloor when configured', () => { + const requestWithFloor = Object.assign({}, REQUEST); + requestWithFloor.getFloor = function (arg) { + if (arg.currency === 'USD' && arg.mediaType === 'banner' && JSON.stringify(arg.size) === JSON.stringify([300, 250])) { + return { currency: 'USD', floor: 0.3 } + } + } + const bidderRequestFloor = spec.buildRequests([requestWithFloor], requestData); + expect(bidderRequestFloor.data.signRequest.bids[0].bidFloor).to.be.equal(0.3); + }); }) describe('interpretResponse', function () { From dfcf4e8593840c01f0e36fb0f168420390597876 Mon Sep 17 00:00:00 2001 From: mik Date: Wed, 8 Feb 2023 09:52:41 +0100 Subject: [PATCH 15/20] ALK-504 Multi size ad slot support --- modules/alkimiBidAdapter.js | 9 +++++---- test/spec/modules/alkimiBidAdapter_spec.js | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index a96b245d786..9f38b54e12f 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -21,7 +21,7 @@ export const spec = { let eids; validBidRequests.forEach(bidRequest => { let formatType = getFormatType(bidRequest) - let alkimiSizes = prepareAlkimiSizes(bidRequest.sizes) + let sizes = prepareSizes(bidRequest.sizes) if (bidRequest.userIdAsEids) { eids = eids || bidRequest.userIdAsEids @@ -31,8 +31,9 @@ export const spec = { token: bidRequest.params.token, pos: bidRequest.params.pos, bidFloor: getBidFloor(bidRequest, formatType), - width: alkimiSizes[0].width, - height: alkimiSizes[0].height, + sizes: sizes.length > 1 ? sizes : [], + width: sizes[0].width, + height: sizes[0].height, impMediaType: formatType, adUnitCode: bidRequest.adUnitCode }) @@ -130,7 +131,7 @@ export const spec = { } } -function prepareAlkimiSizes(sizes) { +function prepareSizes(sizes) { return sizes && sizes.map(size => ({ width: size[0], height: size[1] })); } diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index 92e5d28f42a..f4c119ff050 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -140,7 +140,7 @@ describe('alkimiBidAdapter', function () { expect(bidderRequest.data.requestId).to.equal('123') expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') expect(bidderRequest.data.schain).to.deep.contains({ ver: '1.0', complete: 1, nodes: [{ asi: 'alkimi-onboarding.com', sid: '00001', hp: 1 }] }) - expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, width: 300, height: 250, impMediaType: 'Banner', adUnitCode: 'bannerAdUnitCode' }) + expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, sizes: [], width: 300, height: 250, impMediaType: 'Banner', adUnitCode: 'bannerAdUnitCode' }) expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) expect(bidderRequest.data.bidIds).to.deep.contains('456') expect(bidderRequest.data.signature).to.equal(undefined) From 1a9fe8770e78104859e32c56280cad6865e0716c Mon Sep 17 00:00:00 2001 From: mik Date: Mon, 13 Feb 2023 12:42:18 +0100 Subject: [PATCH 16/20] ALK-504 Multi size ad slot support --- modules/alkimiBidAdapter.js | 58 ++++++++++++---------- test/spec/modules/alkimiBidAdapter_spec.js | 2 +- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index 9f38b54e12f..69b3fdae3d8 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -1,8 +1,8 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { deepClone, deepAccess } from '../src/utils.js'; -import { ajax } from '../src/ajax.js'; -import { VIDEO } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {deepClone, deepAccess} from '../src/utils.js'; +import {ajax} from '../src/ajax.js'; +import {VIDEO} from '../src/mediaTypes.js'; +import {config} from '../src/config.js'; const BIDDER_CODE = 'alkimi'; export const ENDPOINT = 'https://exchange.alkimi-onboarding.com/bid?prebid=true'; @@ -20,8 +20,7 @@ export const spec = { let bidIds = []; let eids; validBidRequests.forEach(bidRequest => { - let formatType = getFormatType(bidRequest) - let sizes = prepareSizes(bidRequest.sizes) + let formatTypes = getFormatType(bidRequest) if (bidRequest.userIdAsEids) { eids = eids || bidRequest.userIdAsEids @@ -30,11 +29,10 @@ export const spec = { bids.push({ token: bidRequest.params.token, pos: bidRequest.params.pos, - bidFloor: getBidFloor(bidRequest, formatType), - sizes: sizes.length > 1 ? sizes : [], - width: sizes[0].width, - height: sizes[0].height, - impMediaType: formatType, + bidFloor: getBidFloor(bidRequest, formatTypes), + sizes: prepareSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes')), + playerSizes: prepareSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize')), + impMediaTypes: formatTypes, adUnitCode: bidRequest.adUnitCode }) bidIds.push(bidRequest.bidId) @@ -44,7 +42,7 @@ export const spec = { let payload = { requestId: bidderRequest.auctionId, - signRequest: { bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID }, + signRequest: {bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID}, bidIds, referer: bidderRequest.refererInfo.page, signature: alkimiConfig && alkimiConfig.signature, @@ -88,7 +86,7 @@ export const spec = { return []; } - const { prebidResponse } = serverBody; + const {prebidResponse} = serverBody; if (!prebidResponse || typeof prebidResponse !== 'object') { return []; } @@ -116,7 +114,7 @@ export const spec = { let winUrl; if (bid.winUrl || bid.vastUrl) { winUrl = bid.winUrl ? bid.winUrl : bid.vastUrl; - winUrl = winUrl.replace(/\$\{AUCTION_PRICE\}/, bid.cpm); + winUrl = winUrl.replace(/\$\{AUCTION_PRICE}/, bid.cpm); } else if (bid.ad) { let trackImg = bid.ad.match(/(?!^)/); bid.ad = bid.ad.replace(trackImg[0], ''); @@ -132,28 +130,34 @@ export const spec = { } function prepareSizes(sizes) { - return sizes && sizes.map(size => ({ width: size[0], height: size[1] })); + return sizes ? sizes.map(size => ({width: size[0], height: size[1]})) : [] } function prepareBidFloorSize(sizes) { - return sizes && sizes.length === 1 ? sizes[0] : '*'; + return sizes && sizes.length === 1 ? sizes : ['*']; } -function getBidFloor(bidRequest, formatType) { +function getBidFloor(bidRequest, formatTypes) { + let minFloor if (typeof bidRequest.getFloor === 'function') { - const bidFloorSize = prepareBidFloorSize(bidRequest.sizes) - const floor = bidRequest.getFloor({ currency: 'USD', mediaType: formatType.toLowerCase(), size: bidFloorSize }); - if (floor && !isNaN(floor.floor) && (floor.currency === 'USD')) { - return floor.floor; - } + const bidFloorSizes = prepareBidFloorSize(bidRequest.sizes) + formatTypes.forEach(formatType => { + bidFloorSizes.forEach(bidFloorSize => { + const floor = bidRequest.getFloor({currency: 'USD', mediaType: formatType.toLowerCase(), size: bidFloorSize}); + if (floor && !isNaN(floor.floor) && (floor.currency === 'USD')) { + minFloor = !minFloor || floor.floor < minFloor ? floor.floor : minFloor + } + }) + }) } - return bidRequest.params.bidFloor; + return minFloor || bidRequest.params.bidFloor; } const getFormatType = bidRequest => { - if (deepAccess(bidRequest, 'mediaTypes.banner')) return 'Banner' - if (deepAccess(bidRequest, 'mediaTypes.video')) return 'Video' - if (deepAccess(bidRequest, 'mediaTypes.audio')) return 'Audio' + let formats = [] + if (deepAccess(bidRequest, 'mediaTypes.banner')) formats.push('Banner') + if (deepAccess(bidRequest, 'mediaTypes.video')) formats.push('Video') + return formats } registerBidder(spec); diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index f4c119ff050..a396e5b8139 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -140,7 +140,7 @@ describe('alkimiBidAdapter', function () { expect(bidderRequest.data.requestId).to.equal('123') expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') expect(bidderRequest.data.schain).to.deep.contains({ ver: '1.0', complete: 1, nodes: [{ asi: 'alkimi-onboarding.com', sid: '00001', hp: 1 }] }) - expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, sizes: [], width: 300, height: 250, impMediaType: 'Banner', adUnitCode: 'bannerAdUnitCode' }) + expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, sizes: [{width: 300, height: 250}], playerSizes: [], impMediaTypes: ['Banner'], adUnitCode: 'bannerAdUnitCode' }) expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) expect(bidderRequest.data.bidIds).to.deep.contains('456') expect(bidderRequest.data.signature).to.equal(undefined) From b72563235bb16ab744018374c6e7e3719f4eee74 Mon Sep 17 00:00:00 2001 From: Aleksandr Bogdanov Date: Thu, 13 Jul 2023 12:02:00 +0200 Subject: [PATCH 17/20] Support new OpenRTB parameters --- modules/alkimiBidAdapter.js | 15 ++++++++++++--- test/spec/modules/alkimiBidAdapter_spec.js | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index c087b3061a0..e860faf59b3 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -1,5 +1,5 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {deepAccess, deepClone} from '../src/utils.js'; +import {deepAccess, deepClone, getDNT} from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import {VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; @@ -29,11 +29,15 @@ export const spec = { bids.push({ token: bidRequest.params.token, pos: bidRequest.params.pos, + instl: bidRequest.params.instl, + exp: bidRequest.params.exp, bidFloor: getBidFloor(bidRequest, formatTypes), sizes: prepareSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes')), playerSizes: prepareSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize')), impMediaTypes: formatTypes, - adUnitCode: bidRequest.adUnitCode + adUnitCode: bidRequest.adUnitCode, + video: deepAccess(bidRequest, 'mediaTypes.video'), + banner: deepAccess(bidRequest, 'mediaTypes.banner') }) bidIds.push(bidRequest.bidId) }) @@ -48,7 +52,12 @@ export const spec = { referer: bidderRequest.refererInfo.page, signature: alkimiConfig && alkimiConfig.signature, schain: validBidRequests[0].schain, - cpp: config.getConfig('coppa') ? 1 : 0 + cpp: config.getConfig('coppa') ? 1 : 0, + device: { + dnt: getDNT() ? 1 : 0, + w: screen.width, + h: screen.height + } } if (bidderRequest && bidderRequest.gdprConsent) { diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index a396e5b8139..e75c87a5372 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -140,7 +140,7 @@ describe('alkimiBidAdapter', function () { expect(bidderRequest.data.requestId).to.equal('123') expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') expect(bidderRequest.data.schain).to.deep.contains({ ver: '1.0', complete: 1, nodes: [{ asi: 'alkimi-onboarding.com', sid: '00001', hp: 1 }] }) - expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, sizes: [{width: 300, height: 250}], playerSizes: [], impMediaTypes: ['Banner'], adUnitCode: 'bannerAdUnitCode' }) + expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, sizes: [{ width: 300, height: 250 }], playerSizes: [], impMediaTypes: ['Banner'], adUnitCode: 'bannerAdUnitCode', instl: undefined, exp: undefined, banner: { sizes: [[300, 250]] }, video: undefined }) expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) expect(bidderRequest.data.bidIds).to.deep.contains('456') expect(bidderRequest.data.signature).to.equal(undefined) From 36c2b78cdf522e4eb66b16a985c43213e5d8dcfa Mon Sep 17 00:00:00 2001 From: Aleksandr Bogdanov Date: Mon, 24 Jul 2023 10:34:15 +0200 Subject: [PATCH 18/20] Support new oRTB2 parameters --- modules/alkimiBidAdapter.js | 10 +++++++--- test/spec/modules/alkimiBidAdapter_spec.js | 3 +-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index e860faf59b3..2a8179693d0 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -1,5 +1,5 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {deepAccess, deepClone, getDNT} from '../src/utils.js'; +import {deepAccess, deepClone, getDNT, generateUUID} from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import {VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; @@ -45,8 +45,7 @@ export const spec = { const alkimiConfig = config.getConfig('alkimi'); let payload = { - // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 - requestId: bidderRequest.auctionId, + requestId: generateUUID(), signRequest: {bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID}, bidIds, referer: bidderRequest.refererInfo.page, @@ -57,6 +56,11 @@ export const spec = { dnt: getDNT() ? 1 : 0, w: screen.width, h: screen.height + }, + ortb2: { + at: bidderRequest.ortb2?.at, + bcat: bidderRequest.ortb2?.bcat, + wseat: bidderRequest.ortb2?.wseat } } diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index e75c87a5372..6ddc076e9a8 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -109,7 +109,6 @@ describe('alkimiBidAdapter', function () { describe('buildRequests', function () { let bidRequests = [REQUEST] let requestData = { - auctionId: '123', refererInfo: { page: 'http://test.com/path.html' }, @@ -137,7 +136,7 @@ describe('alkimiBidAdapter', function () { it('sends bid request to ENDPOINT via POST', function () { expect(bidderRequest.method).to.equal('POST') - expect(bidderRequest.data.requestId).to.equal('123') + expect(bidderRequest.data.requestId).to.not.equal(undefined) expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') expect(bidderRequest.data.schain).to.deep.contains({ ver: '1.0', complete: 1, nodes: [{ asi: 'alkimi-onboarding.com', sid: '00001', hp: 1 }] }) expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, sizes: [{ width: 300, height: 250 }], playerSizes: [], impMediaTypes: ['Banner'], adUnitCode: 'bannerAdUnitCode', instl: undefined, exp: undefined, banner: { sizes: [[300, 250]] }, video: undefined }) From 77c4113102c1d14ec4513281846cb0749ebd0176 Mon Sep 17 00:00:00 2001 From: Aleksandr Bogdanov Date: Mon, 31 Jul 2023 23:36:45 +0200 Subject: [PATCH 19/20] remove pos parameter --- modules/alkimiBidAdapter.js | 3 +-- test/spec/modules/alkimiBidAdapter_spec.js | 9 ++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index 2a8179693d0..64a46779a06 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -12,7 +12,7 @@ export const spec = { supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) { - return !!(bid.params && bid.params.bidFloor && bid.params.token); + return !!(bid.params && bid.params.token); }, buildRequests: function (validBidRequests, bidderRequest) { @@ -28,7 +28,6 @@ export const spec = { bids.push({ token: bidRequest.params.token, - pos: bidRequest.params.pos, instl: bidRequest.params.instl, exp: bidRequest.params.exp, bidFloor: getBidFloor(bidRequest, formatTypes), diff --git a/test/spec/modules/alkimiBidAdapter_spec.js b/test/spec/modules/alkimiBidAdapter_spec.js index 6ddc076e9a8..08f00186358 100644 --- a/test/spec/modules/alkimiBidAdapter_spec.js +++ b/test/spec/modules/alkimiBidAdapter_spec.js @@ -14,8 +14,7 @@ const REQUEST = { }, 'params': { bidFloor: 0.1, - token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', - pos: 7 + token: 'e64782a4-8e68-4c38-965b-80ccf115d46f' }, 'userIdAsEids': [{ 'source': 'criteo.com', @@ -96,10 +95,6 @@ describe('alkimiBidAdapter', function () { delete bid.params.token expect(spec.isBidRequestValid(bid)).to.equal(false) - bid = Object.assign({}, REQUEST) - delete bid.params.bidFloor - expect(spec.isBidRequestValid(bid)).to.equal(false) - bid = Object.assign({}, REQUEST) delete bid.params expect(spec.isBidRequestValid(bid)).to.equal(false) @@ -139,7 +134,7 @@ describe('alkimiBidAdapter', function () { expect(bidderRequest.data.requestId).to.not.equal(undefined) expect(bidderRequest.data.referer).to.equal('http://test.com/path.html') expect(bidderRequest.data.schain).to.deep.contains({ ver: '1.0', complete: 1, nodes: [{ asi: 'alkimi-onboarding.com', sid: '00001', hp: 1 }] }) - expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', pos: 7, bidFloor: 0.1, sizes: [{ width: 300, height: 250 }], playerSizes: [], impMediaTypes: ['Banner'], adUnitCode: 'bannerAdUnitCode', instl: undefined, exp: undefined, banner: { sizes: [[300, 250]] }, video: undefined }) + expect(bidderRequest.data.signRequest.bids).to.deep.contains({ token: 'e64782a4-8e68-4c38-965b-80ccf115d46f', bidFloor: 0.1, sizes: [{ width: 300, height: 250 }], playerSizes: [], impMediaTypes: ['Banner'], adUnitCode: 'bannerAdUnitCode', instl: undefined, exp: undefined, banner: { sizes: [[300, 250]] }, video: undefined }) expect(bidderRequest.data.signRequest.randomUUID).to.equal(undefined) expect(bidderRequest.data.bidIds).to.deep.contains('456') expect(bidderRequest.data.signature).to.equal(undefined) From f32111f3838f7dcf6fbc4762297b97b73d5de6e7 Mon Sep 17 00:00:00 2001 From: Aleksandr Bogdanov Date: Thu, 24 Aug 2023 12:35:43 +0200 Subject: [PATCH 20/20] Add gvl_id into Alkimi adapter --- modules/alkimiBidAdapter.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index 64a46779a06..6274ad2bf1c 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -5,10 +5,12 @@ import {VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; const BIDDER_CODE = 'alkimi'; +const GVLID = 1169; export const ENDPOINT = 'https://exchange.alkimi-onboarding.com/bid?prebid=true'; export const spec = { code: BIDDER_CODE, + gvlid: GVLID, supportedMediaTypes: ['banner', 'video'], isBidRequestValid: function (bid) {