From 95e5a3c771ed0b95e990eb0309a2288ff6010b8c Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Fri, 23 Aug 2024 10:26:01 +0300 Subject: [PATCH 01/20] POC test --- modules/appnexusBidAdapter.js | 43 +++++++++++++++++++++++++ modules/connatixBidAdapter.js | 59 +++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 4935158d21c..f76da5d10b2 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -37,6 +37,7 @@ import { import {convertCamelToUnderscore, fill, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js'; import {convertTypes} from '../libraries/transformParamsUtils/convertTypes.js'; import {chunk} from '../libraries/chunk/chunk.js'; +import { ajax } from '../src/ajax.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -521,6 +522,48 @@ function formatRequest(payload, bidderRequest) { }; } + if (window.pbjs) { + window.pbjs.onEvent('auctionTimeout', (timeoutData) => { + // eslint-disable-next-line no-console + console.log('AppNexus auction timeout', timeoutData, timeoutData); + + const timeout = timeoutData.timeout; + const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); + if (isConnatixTimeout) { + // eslint-disable-next-line no-console + console.log(timeout); + + ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({timeout}), { + method: 'POST', + withCredentials: false + }); + } + }); + window.pbjs.onEvent('auctionEnd', (auctionEndData) => { + const bidsReceived = auctionEndData.bidsReceived; + const noBids = auctionEndData.noBids; + + const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); + const hasConnatixNoBid = noBids.some(bid => bid.bidder === BIDDER_CODE); + + const bestBidPrice = connatixBid.reduce((acc, bid) => acc.cpm > bid.cpm ? acc : bid, connatixBid[0]); + + // Only if connatix compete in the auction + if (hasConnatixNoBid || connatixBid) { + const connatixBidPrice = connatixBid.cpm; + if (bestBidPrice !== connatixBidPrice) { + ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({connatixBidPrice, bestBidPrice}), { + method: 'POST', + withCredentials: false + }); + } + } + + // eslint-disable-next-line no-console + console.log('AppNexus auction end', auctionEndData); + }); + } + return request; } diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index 925ddebe099..d55d84b52ca 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -16,6 +16,9 @@ import { BANNER, VIDEO, } from '../src/mediaTypes.js'; +import { ajax } from '../src/ajax.js'; + +import * as utils from '../src/utils.js'; const BIDDER_CODE = 'connatix'; const AD_URL = 'https://capi.connatix.com/rtb/hba'; @@ -72,6 +75,20 @@ function _handleEids(payload, validBidRequests) { } } +/** + * Inserts an image pixel with the specified `url` for cookie sync + * @param {string} url URL string of the image pixel to load + * @param {function} [done] an optional exit callback, used when this usersync pixel is added during an async process + * @param {Number} [timeout] an optional timeout in milliseconds for the image to load before calling `done` + */ +export function triggerPixel(url, done, timeout) { + const img = new Image(); + if (done && utils.internal.isFn(done)) { + utils.waitForElementToLoad(img, timeout).then(done); + } + img.src = url; +} + export const spec = { code: BIDDER_CODE, gvlid: 143, @@ -140,6 +157,48 @@ export const spec = { _handleEids(requestPayload, validBidRequests); + if (window.pbjs) { + window.pbjs.onEvent('auctionTimeout', (timeoutData) => { + // eslint-disable-next-line no-console + console.log('Connatix auction timeout', timeoutData); + + const timeout = timeoutData.timeout; + const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); + if (isConnatixTimeout) { + // eslint-disable-next-line no-console + console.log(timeout); + + ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({timeout}), { + method: 'POST', + withCredentials: false + }); + } + }); + window.pbjs.onEvent('auctionEnd', (auctionEndData) => { + const bidsReceived = auctionEndData.bidsReceived; + const noBids = auctionEndData.noBids; + + const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); + const hasConnatixNoBid = noBids.some(bid => bid.bidder === BIDDER_CODE); + + const bestBidPrice = connatixBid.reduce((acc, bid) => acc.cpm > bid.cpm ? acc : bid, connatixBid[0]); + + // Only if connatix compete in the auction + if (hasConnatixNoBid || connatixBid) { + const connatixBidPrice = connatixBid.cpm; + if (bestBidPrice !== connatixBidPrice) { + ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({connatixBidPrice, bestBidPrice}), { + method: 'POST', + withCredentials: false + }); + } + } + + // eslint-disable-next-line no-console + console.log('Connatix auction end', auctionEndData); + }); + } + return { method: 'POST', url: AD_URL, From 4523b5e5bbde2cec28c3c96ce618fd4e2f03364d Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Fri, 23 Aug 2024 14:49:19 +0300 Subject: [PATCH 02/20] fix tests + a bug in log --- modules/appnexusBidAdapter.js | 42 +++++++++++++++++++---------------- modules/connatixBidAdapter.js | 26 +++++++++++++--------- 2 files changed, 38 insertions(+), 30 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index f76da5d10b2..10a03b8795e 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -37,7 +37,6 @@ import { import {convertCamelToUnderscore, fill, appnexusAliases} from '../libraries/appnexusUtils/anUtils.js'; import {convertTypes} from '../libraries/transformParamsUtils/convertTypes.js'; import {chunk} from '../libraries/chunk/chunk.js'; -import { ajax } from '../src/ajax.js'; /** * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest @@ -524,38 +523,43 @@ function formatRequest(payload, bidderRequest) { if (window.pbjs) { window.pbjs.onEvent('auctionTimeout', (timeoutData) => { - // eslint-disable-next-line no-console - console.log('AppNexus auction timeout', timeoutData, timeoutData); - - const timeout = timeoutData.timeout; const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); if (isConnatixTimeout) { + const timeout = timeoutData.timeout; + // eslint-disable-next-line no-console console.log(timeout); - ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({timeout}), { - method: 'POST', - withCredentials: false - }); + // ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({timeout}), { + // method: 'POST', + // withCredentials: false + // }); } + + // eslint-disable-next-line no-console + console.log('AppNexus auction timeout', timeoutData); }); + window.pbjs.onEvent('auctionEnd', (auctionEndData) => { const bidsReceived = auctionEndData.bidsReceived; - const noBids = auctionEndData.noBids; + const hasConnatixBid = bidsReceived.some(bid => bid.bidder === BIDDER_CODE); const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); - const hasConnatixNoBid = noBids.some(bid => bid.bidder === BIDDER_CODE); - const bestBidPrice = connatixBid.reduce((acc, bid) => acc.cpm > bid.cpm ? acc : bid, connatixBid[0]); + let bestBidPrice = 0; + bidsReceived.forEach(bid => { + if (bid.cpm > bestBidPrice) { + bestBidPrice = bid.cpm; + } + }); // Only if connatix compete in the auction - if (hasConnatixNoBid || connatixBid) { - const connatixBidPrice = connatixBid.cpm; - if (bestBidPrice !== connatixBidPrice) { - ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({connatixBidPrice, bestBidPrice}), { - method: 'POST', - withCredentials: false - }); + if (hasConnatixBid) { + if (bestBidPrice !== connatixBid.cpm) { + // ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({connatixBidPrice: connatixBid.cpm, bestBidPrice}), { + // method: 'POST', + // withCredentials: false + // }); } } diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index d55d84b52ca..41ae1a52f7e 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -159,12 +159,10 @@ export const spec = { if (window.pbjs) { window.pbjs.onEvent('auctionTimeout', (timeoutData) => { - // eslint-disable-next-line no-console - console.log('Connatix auction timeout', timeoutData); - - const timeout = timeoutData.timeout; const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); + if (isConnatixTimeout) { + const timeout = timeoutData.timeout; // eslint-disable-next-line no-console console.log(timeout); @@ -173,21 +171,27 @@ export const spec = { withCredentials: false }); } + + // eslint-disable-next-line no-console + console.log('Connatix auction timeout', timeoutData); }); window.pbjs.onEvent('auctionEnd', (auctionEndData) => { const bidsReceived = auctionEndData.bidsReceived; - const noBids = auctionEndData.noBids; + const hasConnatixBid = bidsReceived.some(bid => bid.bidder === BIDDER_CODE); const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); - const hasConnatixNoBid = noBids.some(bid => bid.bidder === BIDDER_CODE); - const bestBidPrice = connatixBid.reduce((acc, bid) => acc.cpm > bid.cpm ? acc : bid, connatixBid[0]); + let bestBidPrice = 0; + bidsReceived.forEach(bid => { + if (bid.cpm > bestBidPrice) { + bestBidPrice = bid.cpm; + } + }); // Only if connatix compete in the auction - if (hasConnatixNoBid || connatixBid) { - const connatixBidPrice = connatixBid.cpm; - if (bestBidPrice !== connatixBidPrice) { - ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({connatixBidPrice, bestBidPrice}), { + if (hasConnatixBid) { + if (bestBidPrice !== connatixBid.cpm) { + ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({connatixBidPrice: connatixBid.cpm, bestBidPrice}), { method: 'POST', withCredentials: false }); From b2396614e1df8de732a6183f9b175cdd7267cc45 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Fri, 23 Aug 2024 15:35:19 +0300 Subject: [PATCH 03/20] removed appnexus newly added events and logs --- modules/appnexusBidAdapter.js | 47 ----------------------------------- modules/connatixBidAdapter.js | 2 +- 2 files changed, 1 insertion(+), 48 deletions(-) diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index 10a03b8795e..4935158d21c 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -521,53 +521,6 @@ function formatRequest(payload, bidderRequest) { }; } - if (window.pbjs) { - window.pbjs.onEvent('auctionTimeout', (timeoutData) => { - const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); - if (isConnatixTimeout) { - const timeout = timeoutData.timeout; - - // eslint-disable-next-line no-console - console.log(timeout); - - // ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({timeout}), { - // method: 'POST', - // withCredentials: false - // }); - } - - // eslint-disable-next-line no-console - console.log('AppNexus auction timeout', timeoutData); - }); - - window.pbjs.onEvent('auctionEnd', (auctionEndData) => { - const bidsReceived = auctionEndData.bidsReceived; - - const hasConnatixBid = bidsReceived.some(bid => bid.bidder === BIDDER_CODE); - const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); - - let bestBidPrice = 0; - bidsReceived.forEach(bid => { - if (bid.cpm > bestBidPrice) { - bestBidPrice = bid.cpm; - } - }); - - // Only if connatix compete in the auction - if (hasConnatixBid) { - if (bestBidPrice !== connatixBid.cpm) { - // ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({connatixBidPrice: connatixBid.cpm, bestBidPrice}), { - // method: 'POST', - // withCredentials: false - // }); - } - } - - // eslint-disable-next-line no-console - console.log('AppNexus auction end', auctionEndData); - }); - } - return request; } diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index 41ae1a52f7e..e65f49890ea 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -178,7 +178,7 @@ export const spec = { window.pbjs.onEvent('auctionEnd', (auctionEndData) => { const bidsReceived = auctionEndData.bidsReceived; - const hasConnatixBid = bidsReceived.some(bid => bid.bidder === BIDDER_CODE); + const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); let bestBidPrice = 0; From 7e161df4260b17da2e42c64ff819ea36b5b7a65d Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Fri, 23 Aug 2024 15:44:56 +0300 Subject: [PATCH 04/20] use constants for events --- modules/connatixBidAdapter.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index e65f49890ea..8233c181234 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -19,6 +19,7 @@ import { import { ajax } from '../src/ajax.js'; import * as utils from '../src/utils.js'; +import { EVENTS } from '../src/constants.js'; const BIDDER_CODE = 'connatix'; const AD_URL = 'https://capi.connatix.com/rtb/hba'; @@ -158,7 +159,7 @@ export const spec = { _handleEids(requestPayload, validBidRequests); if (window.pbjs) { - window.pbjs.onEvent('auctionTimeout', (timeoutData) => { + window.pbjs.onEvent(EVENTS.AUCTION_TIMEOUT, (timeoutData) => { const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); if (isConnatixTimeout) { @@ -175,7 +176,7 @@ export const spec = { // eslint-disable-next-line no-console console.log('Connatix auction timeout', timeoutData); }); - window.pbjs.onEvent('auctionEnd', (auctionEndData) => { + window.pbjs.onEvent(EVENTS.AUCTION_END, (auctionEndData) => { const bidsReceived = auctionEndData.bidsReceived; const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); From 4da0a4c997cc7e7fa987b595ab70f596b390caee Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Fri, 23 Aug 2024 19:03:19 +0300 Subject: [PATCH 05/20] prepared POC for PrebidJS official --- modules/connatixBidAdapter.js | 116 ++++++++++++++++++++-------------- 1 file changed, 70 insertions(+), 46 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index 8233c181234..b6a3df9ec6e 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -22,10 +22,13 @@ import * as utils from '../src/utils.js'; import { EVENTS } from '../src/constants.js'; const BIDDER_CODE = 'connatix'; + const AD_URL = 'https://capi.connatix.com/rtb/hba'; const DEFAULT_MAX_TTL = '3600'; const DEFAULT_CURRENCY = 'USD'; +const EVENTS_BASE_URL = 'https://capi.connatix.com/event'; + /* * Get the bid floor value from the bid object, either using the getFloor function or by accessing the 'params.bidfloor' property. * If the bid floor cannot be determined, return 0 as a fallback value. @@ -76,6 +79,71 @@ function _handleEids(payload, validBidRequests) { } } +/** + * Handle prebid events to send to Connatix + */ +function _handleEvents() { + const prebidJs = window.pbjs; + + if (!prebidJs) { + ajax(`${EVENTS_BASE_URL}/nt`, null, {}, { + method: 'POST', + withCredentials: false + }); + return; + } + + prebidJs.onEvent(EVENTS.AUCTION_TIMEOUT, (timeoutData) => { + // eslint-disable-next-line no-console + console.log('Connatix auction timeout', timeoutData); + + const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); + + // Log only it is a timeout for Connatix + // Otherwise it is not relevant for us + if (!isConnatixTimeout) { + return; + } + + const timeout = timeoutData.timeout; + ajax(`${EVENTS_BASE_URL}/to`, null, JSON.stringify({timeout}), { + method: 'POST', + withCredentials: false + }); + }); + + prebidJs.onEvent(EVENTS.AUCTION_END, (auctionEndData) => { + // eslint-disable-next-line no-console + console.log('Connatix auction end', auctionEndData); + + const bidsReceived = auctionEndData.bidsReceived; + const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); + + // Log only if connatix compete in the auction and have a bid. + // Otherwise it is not relevant for us + if (!hasConnatixBid) { + return; + } + + let bestBidPrice = 0; + bidsReceived.forEach(bid => { + if (bid.cpm > bestBidPrice) { + bestBidPrice = bid.cpm; + } + }); + + const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); + const connatixBidPrice = connatixBid.cpm; + + if (bestBidPrice > connatixBidPrice) { + ajax(`${EVENTS_BASE_URL}/ae`, null, JSON.stringify({connatixBidPrice, bestBidPrice}), { + method: 'POST', + withCredentials: false + }); + } + }); +} + /** * Inserts an image pixel with the specified `url` for cookie sync * @param {string} url URL string of the image pixel to load @@ -131,6 +199,8 @@ export const spec = { * Return an object containing the request method, url, and the constructed payload. */ buildRequests: (validBidRequests = [], bidderRequest = {}) => { + _handleEvents() + const bidRequests = validBidRequests.map(bid => { const { bidId, @@ -158,52 +228,6 @@ export const spec = { _handleEids(requestPayload, validBidRequests); - if (window.pbjs) { - window.pbjs.onEvent(EVENTS.AUCTION_TIMEOUT, (timeoutData) => { - const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); - - if (isConnatixTimeout) { - const timeout = timeoutData.timeout; - // eslint-disable-next-line no-console - console.log(timeout); - - ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({timeout}), { - method: 'POST', - withCredentials: false - }); - } - - // eslint-disable-next-line no-console - console.log('Connatix auction timeout', timeoutData); - }); - window.pbjs.onEvent(EVENTS.AUCTION_END, (auctionEndData) => { - const bidsReceived = auctionEndData.bidsReceived; - - const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); - const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); - - let bestBidPrice = 0; - bidsReceived.forEach(bid => { - if (bid.cpm > bestBidPrice) { - bestBidPrice = bid.cpm; - } - }); - - // Only if connatix compete in the auction - if (hasConnatixBid) { - if (bestBidPrice !== connatixBid.cpm) { - ajax('ENDPOINT_BASR_URL' + '/timeout-route-name', null, JSON.stringify({connatixBidPrice: connatixBid.cpm, bestBidPrice}), { - method: 'POST', - withCredentials: false - }); - } - } - - // eslint-disable-next-line no-console - console.log('Connatix auction end', auctionEndData); - }); - } - return { method: 'POST', url: AD_URL, From b16672e44d4abeb242a3f1e6650eb791ca6e641d Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Mon, 26 Aug 2024 10:29:19 +0300 Subject: [PATCH 06/20] code review --- modules/connatixBidAdapter.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index b6a3df9ec6e..c7c8a8f5b5e 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -125,18 +125,19 @@ function _handleEvents() { return; } - let bestBidPrice = 0; - bidsReceived.forEach(bid => { - if (bid.cpm > bestBidPrice) { - bestBidPrice = bid.cpm; + const { bestBidPrice, bestBidBidder } = bidsReceived.reduce((acc, bid) => { + if (bid.cpm > acc.bestBidPrice) { + acc.bestBidPrice = bid.cpm; + acc.bestBidBidder = bid.bidderCode; } - }); + return acc; + }, { bestBidPrice: 0, bestBidBidder: '' }); - const connatixBid = bidsReceived.filter(bid => bid.bidderCode === BIDDER_CODE); + const connatixBid = bidsReceived.find(bid => bid.bidderCode === BIDDER_CODE); const connatixBidPrice = connatixBid.cpm; if (bestBidPrice > connatixBidPrice) { - ajax(`${EVENTS_BASE_URL}/ae`, null, JSON.stringify({connatixBidPrice, bestBidPrice}), { + ajax(`${EVENTS_BASE_URL}/ae`, null, JSON.stringify({bestBidBidder, bestBidPrice, connatixBidPrice}), { method: 'POST', withCredentials: false }); From 89a7f0596ad9d4080509b4b4c36ad009301e2c2d Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Mon, 26 Aug 2024 15:02:46 +0300 Subject: [PATCH 07/20] refactor --- modules/connatixBidAdapter.js | 48 +++++++++++++---------------------- 1 file changed, 17 insertions(+), 31 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index c7c8a8f5b5e..db46aac8431 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -10,16 +10,14 @@ import { formatQS, deepSetValue } from '../src/utils.js'; +import { EVENTS } from '../src/constants.js'; +import { ajax } from '../src/ajax.js'; import { ADPOD, BANNER, VIDEO, } from '../src/mediaTypes.js'; -import { ajax } from '../src/ajax.js'; - -import * as utils from '../src/utils.js'; -import { EVENTS } from '../src/constants.js'; const BIDDER_CODE = 'connatix'; @@ -28,6 +26,8 @@ const DEFAULT_MAX_TTL = '3600'; const DEFAULT_CURRENCY = 'USD'; const EVENTS_BASE_URL = 'https://capi.connatix.com/event'; +const TIMOUT_EVENT_ENDPOINT = 'to'; +const AUCTION_END_EVENT_ENDPOINT = 'ae'; /* * Get the bid floor value from the bid object, either using the getFloor function or by accessing the 'params.bidfloor' property. @@ -86,17 +86,15 @@ function _handleEvents() { const prebidJs = window.pbjs; if (!prebidJs) { - ajax(`${EVENTS_BASE_URL}/nt`, null, {}, { - method: 'POST', - withCredentials: false - }); + // TODO: Do we need to log this case where prebid is not available? + // ajax(`${EVENTS_BASE_URL}/nt`, null, {}, { + // method: 'POST', + // withCredentials: false + // }); return; } prebidJs.onEvent(EVENTS.AUCTION_TIMEOUT, (timeoutData) => { - // eslint-disable-next-line no-console - console.log('Connatix auction timeout', timeoutData); - const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); // Log only it is a timeout for Connatix @@ -105,17 +103,17 @@ function _handleEvents() { return; } + // TODO: Add context here similar for auction_start and bid in auction - logged by hba + const context = {}; + const timeout = timeoutData.timeout; - ajax(`${EVENTS_BASE_URL}/to`, null, JSON.stringify({timeout}), { + ajax(`${EVENTS_BASE_URL}/${TIMOUT_EVENT_ENDPOINT}`, null, JSON.stringify({timeout, context}), { method: 'POST', withCredentials: false }); }); prebidJs.onEvent(EVENTS.AUCTION_END, (auctionEndData) => { - // eslint-disable-next-line no-console - console.log('Connatix auction end', auctionEndData); - const bidsReceived = auctionEndData.bidsReceived; const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); @@ -134,10 +132,12 @@ function _handleEvents() { }, { bestBidPrice: 0, bestBidBidder: '' }); const connatixBid = bidsReceived.find(bid => bid.bidderCode === BIDDER_CODE); - const connatixBidPrice = connatixBid.cpm; + const connatixBidPrice = connatixBid?.cpm ?? 0; if (bestBidPrice > connatixBidPrice) { - ajax(`${EVENTS_BASE_URL}/ae`, null, JSON.stringify({bestBidBidder, bestBidPrice, connatixBidPrice}), { + // TODO: Add context here similar for auction_start and bid in auction - logged by hba + const context = {}; + ajax(`${EVENTS_BASE_URL}/${AUCTION_END_EVENT_ENDPOINT}`, null, JSON.stringify({bestBidBidder, bestBidPrice, connatixBidPrice, context}), { method: 'POST', withCredentials: false }); @@ -145,20 +145,6 @@ function _handleEvents() { }); } -/** - * Inserts an image pixel with the specified `url` for cookie sync - * @param {string} url URL string of the image pixel to load - * @param {function} [done] an optional exit callback, used when this usersync pixel is added during an async process - * @param {Number} [timeout] an optional timeout in milliseconds for the image to load before calling `done` - */ -export function triggerPixel(url, done, timeout) { - const img = new Image(); - if (done && utils.internal.isFn(done)) { - utils.waitForElementToLoad(img, timeout).then(done); - } - img.src = url; -} - export const spec = { code: BIDDER_CODE, gvlid: 143, From 72087311e38e022af93261421a1eded83907049a Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Mon, 26 Aug 2024 17:06:07 +0300 Subject: [PATCH 08/20] set viewability container to hba to determine if we cannot detect vieweability or the publisher does not sent us the viewability container id --- modules/connatixBidAdapter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index db46aac8431..dc559628785 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -200,6 +200,7 @@ export const spec = { mediaTypes, sizes, placementId: params.placementId, + viewabilityContainerId: params.viewabilityContainerIdentifier, floor: getBidFloor(bid), }; }); From 7e81bb4e55e8dc2c8143f0dc200d1fc32561a5d2 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Wed, 28 Aug 2024 14:52:50 +0300 Subject: [PATCH 09/20] set context and added two clear TODOs with what it remains to be considered done --- modules/connatixBidAdapter.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index dc559628785..09699ced243 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -25,6 +25,7 @@ const AD_URL = 'https://capi.connatix.com/rtb/hba'; const DEFAULT_MAX_TTL = '3600'; const DEFAULT_CURRENCY = 'USD'; +// TODO: Agree with BE team on the base URL and endpoint names const EVENTS_BASE_URL = 'https://capi.connatix.com/event'; const TIMOUT_EVENT_ENDPOINT = 'to'; const AUCTION_END_EVENT_ENDPOINT = 'ae'; @@ -82,18 +83,24 @@ function _handleEids(payload, validBidRequests) { /** * Handle prebid events to send to Connatix */ -function _handleEvents() { +function _handleEvents(validBidRequests, bidderRequest) { const prebidJs = window.pbjs; if (!prebidJs) { - // TODO: Do we need to log this case where prebid is not available? - // ajax(`${EVENTS_BASE_URL}/nt`, null, {}, { - // method: 'POST', - // withCredentials: false - // }); return; } + // TODO: Define context with BE team + const placementIdList = validBidRequests.map(bid => bid.params.placementId); + const context = { + refererInfo: bidderRequest.refererInfo, + uspConsent: bidderRequest.uspConsent, + gppConsent: bidderRequest.gppConsent, + gdprConsent: bidderRequest.gdprConsent, + ortb2: bidderRequest.ortb2, + placementIdList, + }; + prebidJs.onEvent(EVENTS.AUCTION_TIMEOUT, (timeoutData) => { const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); @@ -103,9 +110,6 @@ function _handleEvents() { return; } - // TODO: Add context here similar for auction_start and bid in auction - logged by hba - const context = {}; - const timeout = timeoutData.timeout; ajax(`${EVENTS_BASE_URL}/${TIMOUT_EVENT_ENDPOINT}`, null, JSON.stringify({timeout, context}), { method: 'POST', @@ -135,8 +139,6 @@ function _handleEvents() { const connatixBidPrice = connatixBid?.cpm ?? 0; if (bestBidPrice > connatixBidPrice) { - // TODO: Add context here similar for auction_start and bid in auction - logged by hba - const context = {}; ajax(`${EVENTS_BASE_URL}/${AUCTION_END_EVENT_ENDPOINT}`, null, JSON.stringify({bestBidBidder, bestBidPrice, connatixBidPrice, context}), { method: 'POST', withCredentials: false @@ -186,7 +188,7 @@ export const spec = { * Return an object containing the request method, url, and the constructed payload. */ buildRequests: (validBidRequests = [], bidderRequest = {}) => { - _handleEvents() + _handleEvents(validBidRequests, bidderRequest) const bidRequests = validBidRequests.map(bid => { const { From 5cf8ea0406209cc3c2475d0981b5d4ae54d775b5 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Wed, 28 Aug 2024 23:38:42 +0300 Subject: [PATCH 10/20] Connatix Bid Adapter: Support Events --- modules/connatixBidAdapter.js | 138 ++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 65 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index 09699ced243..bfeacf4995b 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -25,10 +25,7 @@ const AD_URL = 'https://capi.connatix.com/rtb/hba'; const DEFAULT_MAX_TTL = '3600'; const DEFAULT_CURRENCY = 'USD'; -// TODO: Agree with BE team on the base URL and endpoint names -const EVENTS_BASE_URL = 'https://capi.connatix.com/event'; -const TIMOUT_EVENT_ENDPOINT = 'to'; -const AUCTION_END_EVENT_ENDPOINT = 'ae'; +const EVENTS_BASE_URL = 'https://capi.connatix.com/tr/am'; /* * Get the bid floor value from the bid object, either using the getFloor function or by accessing the 'params.bidfloor' property. @@ -70,6 +67,25 @@ export function validateVideo(mediaTypes) { return video.context !== ADPOD; } +function _getBidRequests(validBidRequests) { + return validBidRequests.map(bid => { + const { + bidId, + mediaTypes, + params, + sizes, + } = bid; + return { + bidId, + mediaTypes, + sizes, + placementId: params.placementId, + hasViewabilityContainerId: Boolean(params.viewabilityContainerIdentifier), + floor: getBidFloor(bid), + }; + }); +} + /** * Get ids from Prebid User ID Modules and add them to the payload */ @@ -80,70 +96,77 @@ function _handleEids(payload, validBidRequests) { } } +function _onAuctionTimeout(timeoutData, context) { + const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); + + // Log only it is a timeout for Connatix + // Otherwise it is not relevant for us + if (!isConnatixTimeout) { + return; + } + + const timeout = timeoutData.timeout; + ajax(`${EVENTS_BASE_URL}`, null, JSON.stringify({type: 'timeout', timeout, context}), { + method: 'POST', + withCredentials: false + }); +} + +function _onAuctionEnd(auctionEndData, context) { + const bidsReceived = auctionEndData.bidsReceived; + const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); + + // Log only if connatix compete in the auction and have a bid. + // Otherwise it is not relevant for us + if (!hasConnatixBid) { + return; + } + + const { bestBidPrice, bestBidBidder } = bidsReceived.reduce((acc, bid) => { + if (bid.cpm > acc.bestBidPrice) { + acc.bestBidPrice = bid.cpm; + acc.bestBidBidder = bid.bidderCode; + } + return acc; + }, { bestBidPrice: 0, bestBidBidder: '' }); + + const connatixBid = bidsReceived.find(bid => bid.bidderCode === BIDDER_CODE); + const connatixBidPrice = connatixBid?.cpm ?? 0; + + if (bestBidPrice > connatixBidPrice) { + ajax(`${EVENTS_BASE_URL}`, null, JSON.stringify({type: 'auction_end', bestBidBidder, bestBidPrice, connatixBidPrice, context}), { + method: 'POST', + withCredentials: false + }); + } +} + /** * Handle prebid events to send to Connatix */ -function _handleEvents(validBidRequests, bidderRequest) { +function subscribeToEvents(validBidRequests, bidderRequest) { const prebidJs = window.pbjs; if (!prebidJs) { return; } - // TODO: Define context with BE team - const placementIdList = validBidRequests.map(bid => bid.params.placementId); + const bidRequests = _getBidRequests(validBidRequests); const context = { refererInfo: bidderRequest.refererInfo, uspConsent: bidderRequest.uspConsent, gppConsent: bidderRequest.gppConsent, gdprConsent: bidderRequest.gdprConsent, ortb2: bidderRequest.ortb2, - placementIdList, + bidRequests, }; prebidJs.onEvent(EVENTS.AUCTION_TIMEOUT, (timeoutData) => { - const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); - - // Log only it is a timeout for Connatix - // Otherwise it is not relevant for us - if (!isConnatixTimeout) { - return; - } - - const timeout = timeoutData.timeout; - ajax(`${EVENTS_BASE_URL}/${TIMOUT_EVENT_ENDPOINT}`, null, JSON.stringify({timeout, context}), { - method: 'POST', - withCredentials: false - }); + _onAuctionTimeout(timeoutData, context); }); prebidJs.onEvent(EVENTS.AUCTION_END, (auctionEndData) => { - const bidsReceived = auctionEndData.bidsReceived; - const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); - - // Log only if connatix compete in the auction and have a bid. - // Otherwise it is not relevant for us - if (!hasConnatixBid) { - return; - } - - const { bestBidPrice, bestBidBidder } = bidsReceived.reduce((acc, bid) => { - if (bid.cpm > acc.bestBidPrice) { - acc.bestBidPrice = bid.cpm; - acc.bestBidBidder = bid.bidderCode; - } - return acc; - }, { bestBidPrice: 0, bestBidBidder: '' }); - - const connatixBid = bidsReceived.find(bid => bid.bidderCode === BIDDER_CODE); - const connatixBidPrice = connatixBid?.cpm ?? 0; - - if (bestBidPrice > connatixBidPrice) { - ajax(`${EVENTS_BASE_URL}/${AUCTION_END_EVENT_ENDPOINT}`, null, JSON.stringify({bestBidBidder, bestBidPrice, connatixBidPrice, context}), { - method: 'POST', - withCredentials: false - }); - } + _onAuctionEnd(auctionEndData, context); }); } @@ -188,24 +211,9 @@ export const spec = { * Return an object containing the request method, url, and the constructed payload. */ buildRequests: (validBidRequests = [], bidderRequest = {}) => { - _handleEvents(validBidRequests, bidderRequest) - - const bidRequests = validBidRequests.map(bid => { - const { - bidId, - mediaTypes, - params, - sizes, - } = bid; - return { - bidId, - mediaTypes, - sizes, - placementId: params.placementId, - viewabilityContainerId: params.viewabilityContainerIdentifier, - floor: getBidFloor(bid), - }; - }); + subscribeToEvents(validBidRequests, bidderRequest) + + const bidRequests = _getBidRequests(validBidRequests); const requestPayload = { ortb2: bidderRequest.ortb2, From 8ed824fc69436b361805e33d44c8f8a8b8261bb4 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Thu, 29 Aug 2024 15:55:39 +0300 Subject: [PATCH 11/20] rename constant name --- modules/connatixBidAdapter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index bfeacf4995b..b79731f5a88 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -25,7 +25,7 @@ const AD_URL = 'https://capi.connatix.com/rtb/hba'; const DEFAULT_MAX_TTL = '3600'; const DEFAULT_CURRENCY = 'USD'; -const EVENTS_BASE_URL = 'https://capi.connatix.com/tr/am'; +const EVENTS_URL = 'https://capi.connatix.com/tr/am'; /* * Get the bid floor value from the bid object, either using the getFloor function or by accessing the 'params.bidfloor' property. @@ -106,7 +106,7 @@ function _onAuctionTimeout(timeoutData, context) { } const timeout = timeoutData.timeout; - ajax(`${EVENTS_BASE_URL}`, null, JSON.stringify({type: 'timeout', timeout, context}), { + ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'timeout', timeout, context}), { method: 'POST', withCredentials: false }); @@ -134,7 +134,7 @@ function _onAuctionEnd(auctionEndData, context) { const connatixBidPrice = connatixBid?.cpm ?? 0; if (bestBidPrice > connatixBidPrice) { - ajax(`${EVENTS_BASE_URL}`, null, JSON.stringify({type: 'auction_end', bestBidBidder, bestBidPrice, connatixBidPrice, context}), { + ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'auction_end', bestBidBidder, bestBidPrice, connatixBidPrice, context}), { method: 'POST', withCredentials: false }); From 6b94295fb065acbfa907c36c062e9a21f7425592 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Fri, 30 Aug 2024 20:47:35 +0300 Subject: [PATCH 12/20] refactor --- modules/connatixBidAdapter.js | 123 ++++++++++++++++------------------ 1 file changed, 58 insertions(+), 65 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index b79731f5a88..be7b8453895 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -2,6 +2,8 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { config } from '../src/config.js'; + import { deepAccess, isFn, @@ -10,7 +12,6 @@ import { formatQS, deepSetValue } from '../src/utils.js'; -import { EVENTS } from '../src/constants.js'; import { ajax } from '../src/ajax.js'; import { @@ -27,6 +28,8 @@ const DEFAULT_CURRENCY = 'USD'; const EVENTS_URL = 'https://capi.connatix.com/tr/am'; +let context = {}; + /* * Get the bid floor value from the bid object, either using the getFloor function or by accessing the 'params.bidfloor' property. * If the bid floor cannot be determined, return 0 as a fallback value. @@ -67,7 +70,7 @@ export function validateVideo(mediaTypes) { return video.context !== ADPOD; } -function _getBidRequests(validBidRequests) { +export function _getBidRequests(validBidRequests) { return validBidRequests.map(bid => { const { bidId, @@ -104,71 +107,41 @@ function _onAuctionTimeout(timeoutData, context) { if (!isConnatixTimeout) { return; } - - const timeout = timeoutData.timeout; + const timeout = timeoutData.timeout || config.getConfig('bidderTimeout') ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'timeout', timeout, context}), { method: 'POST', withCredentials: false }); } -function _onAuctionEnd(auctionEndData, context) { - const bidsReceived = auctionEndData.bidsReceived; - const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); - - // Log only if connatix compete in the auction and have a bid. - // Otherwise it is not relevant for us - if (!hasConnatixBid) { - return; - } - - const { bestBidPrice, bestBidBidder } = bidsReceived.reduce((acc, bid) => { - if (bid.cpm > acc.bestBidPrice) { - acc.bestBidPrice = bid.cpm; - acc.bestBidBidder = bid.bidderCode; - } - return acc; - }, { bestBidPrice: 0, bestBidBidder: '' }); - - const connatixBid = bidsReceived.find(bid => bid.bidderCode === BIDDER_CODE); - const connatixBidPrice = connatixBid?.cpm ?? 0; - - if (bestBidPrice > connatixBidPrice) { - ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'auction_end', bestBidBidder, bestBidPrice, connatixBidPrice, context}), { - method: 'POST', - withCredentials: false - }); - } -} - -/** - * Handle prebid events to send to Connatix - */ -function subscribeToEvents(validBidRequests, bidderRequest) { - const prebidJs = window.pbjs; - - if (!prebidJs) { - return; - } - - const bidRequests = _getBidRequests(validBidRequests); - const context = { - refererInfo: bidderRequest.refererInfo, - uspConsent: bidderRequest.uspConsent, - gppConsent: bidderRequest.gppConsent, - gdprConsent: bidderRequest.gdprConsent, - ortb2: bidderRequest.ortb2, - bidRequests, - }; - - prebidJs.onEvent(EVENTS.AUCTION_TIMEOUT, (timeoutData) => { - _onAuctionTimeout(timeoutData, context); - }); - - prebidJs.onEvent(EVENTS.AUCTION_END, (auctionEndData) => { - _onAuctionEnd(auctionEndData, context); - }); -} +// function _onAuctionEnd(auctionEndData, context) { +// const bidsReceived = auctionEndData.bidsReceived; +// const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); + +// // Log only if connatix compete in the auction and have a bid. +// // Otherwise it is not relevant for us +// if (!hasConnatixBid) { +// return; +// } + +// const { bestBidPrice, bestBidBidder } = bidsReceived.reduce((acc, bid) => { +// if (bid.cpm > acc.bestBidPrice) { +// acc.bestBidPrice = bid.cpm; +// acc.bestBidBidder = bid.bidderCode; +// } +// return acc; +// }, { bestBidPrice: 0, bestBidBidder: '' }); + +// const connatixBid = bidsReceived.find(bid => bid.bidderCode === BIDDER_CODE); +// const connatixBidPrice = connatixBid?.cpm ?? 0; + +// if (bestBidPrice > connatixBidPrice) { +// ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'auction_end', bestBidBidder, bestBidPrice, connatixBidPrice, context}), { +// method: 'POST', +// withCredentials: false +// }); +// } +// } export const spec = { code: BIDDER_CODE, @@ -211,8 +184,6 @@ export const spec = { * Return an object containing the request method, url, and the constructed payload. */ buildRequests: (validBidRequests = [], bidderRequest = {}) => { - subscribeToEvents(validBidRequests, bidderRequest) - const bidRequests = _getBidRequests(validBidRequests); const requestPayload = { @@ -226,10 +197,12 @@ export const spec = { _handleEids(requestPayload, validBidRequests); + context = requestPayload; + return { method: 'POST', url: AD_URL, - data: requestPayload + data: context }; }, @@ -303,7 +276,27 @@ export const spec = { type: 'iframe', url }]; - } + }, + + /** + * @param {TimedOutBid} timeoutData + */ + onTimeout: (timeoutData) => { + _onAuctionTimeout(timeoutData, context); + }, + + onBidWon(bidWinData) { + if (bidWinData == null) { + return; + } + + const {bidder, cpm} = bidWinData; + + ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'auction_end', bestBidBidder: bidder, bestBidPrice: cpm, context}), { + method: 'POST', + withCredentials: false + }); + }, }; registerBidder(spec); From 8a8b40b35eea668784be7d6b2e91ca9870a39791 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Mon, 2 Sep 2024 13:09:09 +0300 Subject: [PATCH 13/20] adapt the previous solution to the new one suggested by PrebidJs team --- modules/connatixBidAdapter.js | 73 ++++++++++++----------------------- 1 file changed, 24 insertions(+), 49 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index be7b8453895..d3e97d4d674 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -10,7 +10,8 @@ import { logError, isArray, formatQS, - deepSetValue + deepSetValue, + isNumber } from '../src/utils.js'; import { ajax } from '../src/ajax.js'; @@ -78,12 +79,13 @@ export function _getBidRequests(validBidRequests) { params, sizes, } = bid; + const { placementId, viewabilityContainerIdentifier } = params; return { bidId, mediaTypes, sizes, - placementId: params.placementId, - hasViewabilityContainerId: Boolean(params.viewabilityContainerIdentifier), + placementId, + hasViewabilityContainerId: Boolean(viewabilityContainerIdentifier), floor: getBidFloor(bid), }; }); @@ -99,50 +101,6 @@ function _handleEids(payload, validBidRequests) { } } -function _onAuctionTimeout(timeoutData, context) { - const isConnatixTimeout = timeoutData.bidderRequests.some(bidderRequest => bidderRequest.bidderCode === BIDDER_CODE); - - // Log only it is a timeout for Connatix - // Otherwise it is not relevant for us - if (!isConnatixTimeout) { - return; - } - const timeout = timeoutData.timeout || config.getConfig('bidderTimeout') - ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'timeout', timeout, context}), { - method: 'POST', - withCredentials: false - }); -} - -// function _onAuctionEnd(auctionEndData, context) { -// const bidsReceived = auctionEndData.bidsReceived; -// const hasConnatixBid = bidsReceived.some(bid => bid.bidderCode === BIDDER_CODE); - -// // Log only if connatix compete in the auction and have a bid. -// // Otherwise it is not relevant for us -// if (!hasConnatixBid) { -// return; -// } - -// const { bestBidPrice, bestBidBidder } = bidsReceived.reduce((acc, bid) => { -// if (bid.cpm > acc.bestBidPrice) { -// acc.bestBidPrice = bid.cpm; -// acc.bestBidBidder = bid.bidderCode; -// } -// return acc; -// }, { bestBidPrice: 0, bestBidBidder: '' }); - -// const connatixBid = bidsReceived.find(bid => bid.bidderCode === BIDDER_CODE); -// const connatixBidPrice = connatixBid?.cpm ?? 0; - -// if (bestBidPrice > connatixBidPrice) { -// ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'auction_end', bestBidBidder, bestBidPrice, connatixBidPrice, context}), { -// method: 'POST', -// withCredentials: false -// }); -// } -// } - export const spec = { code: BIDDER_CODE, gvlid: 143, @@ -279,12 +237,29 @@ export const spec = { }, /** + * Register bidder specific code, which will execute if the server response time is greater than auction timeout * @param {TimedOutBid} timeoutData */ onTimeout: (timeoutData) => { - _onAuctionTimeout(timeoutData, context); + const connatixBidRequestTimeout = timeoutData.find(bidderRequest => bidderRequest.bidder === BIDDER_CODE); + + // Log only it is a timeout for Connatix + // Otherwise it is not relevant for us + if (!connatixBidRequestTimeout) { + return; + } + const requestTimeout = connatixBidRequestTimeout.timeout; + const timeout = isNumber(requestTimeout) ? requestTimeout : config.getConfig('bidderTimeout'); + ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'timeout', timeout, context}), { + method: 'POST', + withCredentials: false + }); }, + /** + * Register bidder specific code, which will execute if a bid from this bidder won the auction + * @param {Bid} bid The bid that won the auction + */ onBidWon(bidWinData) { if (bidWinData == null) { return; @@ -292,7 +267,7 @@ export const spec = { const {bidder, cpm} = bidWinData; - ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'auction_end', bestBidBidder: bidder, bestBidPrice: cpm, context}), { + ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'bid_won', bestBidBidder: bidder, bestBidPrice: cpm, context}), { method: 'POST', withCredentials: false }); From 7311a294c7f62da2feb1fd8cc084c02f53680b97 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Thu, 5 Sep 2024 10:33:02 +0300 Subject: [PATCH 14/20] unit tests --- modules/connatixBidAdapter.js | 5 +- test/spec/modules/connatixBidAdapter_spec.js | 184 ++++++++++++++++++- 2 files changed, 185 insertions(+), 4 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index d3e97d4d674..d0f2c47e4f9 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -264,10 +264,9 @@ export const spec = { if (bidWinData == null) { return; } + const {bidder, cpm, requestId, adUnitCode, timeToRespond, auctionId} = bidWinData; - const {bidder, cpm} = bidWinData; - - ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'bid_won', bestBidBidder: bidder, bestBidPrice: cpm, context}), { + ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'bid_won', bestBidBidder: bidder, bestBidPrice: cpm, requestId, adUnitCode, timeToRespond, auctionId, context}), { method: 'POST', withCredentials: false }); diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index d2e8ea63cbe..ebd618b95ad 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -1,10 +1,14 @@ import { expect } from 'chai'; import { + _getBidRequests, + getBidFloor as connatixGetBidFloor, spec, - getBidFloor as connatixGetBidFloor } from '../../../modules/connatixBidAdapter.js'; +import { config } from '../../../src/config.js'; import { ADPOD, BANNER, VIDEO } from '../../../src/mediaTypes.js'; +const sinon = require('sinon'); + describe('connatixBidAdapter', function () { let bid; @@ -44,6 +48,149 @@ describe('connatixBidAdapter', function () { bid.mediaTypes = mediaTypes; } + describe('_getBidRequests', function () { + let bid; + + // Mock a bid request similar to the one already used in connatixBidAdapter tests + function mockBidRequest() { + const mediaTypes = { + banner: { + sizes: [16, 9], + } + }; + return { + bidId: 'testing', + bidder: 'connatix', + params: { + placementId: '30e91414-545c-4f45-a950-0bec9308ff22', + viewabilityContainerIdentifier: 'viewabilityId', + }, + mediaTypes, + sizes: [300, 250] + }; + } + + it('should map valid bid requests and include the expected fields', function () { + bid = mockBidRequest(); + + const result = _getBidRequests([bid]); + + expect(result).to.have.lengthOf(1); + expect(result[0]).to.have.property('bidId', bid.bidId); + expect(result[0]).to.have.property('mediaTypes', bid.mediaTypes); + expect(result[0]).to.have.property('sizes', bid.sizes); + expect(result[0]).to.have.property('placementId', bid.params.placementId); + expect(result[0]).to.have.property('hasViewabilityContainerId', true); + }); + + it('should set hasViewabilityContainerId to false when viewabilityContainerIdentifier is absent', function () { + bid = mockBidRequest(); + delete bid.params.viewabilityContainerIdentifier; + + const result = _getBidRequests([bid]); + + expect(result[0]).to.have.property('hasViewabilityContainerId', false); + }); + + it('should call getBidFloor for each bid and return the correct floor value', function () { + bid = mockBidRequest(); + const floorValue = 5; + + // Mock getFloor method on bid + bid.getFloor = function() { + return { floor: floorValue }; + }; + + const result = _getBidRequests([bid]); + + expect(result[0]).to.have.property('floor', floorValue); + }); + + it('should return floor as 0 if getBidFloor throws an error', function () { + bid = mockBidRequest(); + + // Mock getFloor method to throw an error + bid.getFloor = function() { + throw new Error('error'); + }; + + const result = _getBidRequests([bid]); + + expect(result[0]).to.have.property('floor', 0); + }); + }); + + describe('spec onTimeout', function () { + let sandbox; + let configStub; + + const EVENTS_URL = 'https://capi.connatix.com/tr/am'; + + const timeoutData = [ + { bidder: 'connatix', timeout: 300 }, + { bidder: 'otherBidder', timeout: 200 } + ]; + + beforeEach(function () { + sandbox = sinon.createSandbox(); + + // Replace the following with the correct way to access 'ajax' + sandbox.stub(window, 'ajax'); // or sandbox.stub(ajax, 'call'); + configStub = sandbox.stub(config, 'getConfig'); // Stub config to mock bidderTimeout + }); + + afterEach(function () { + sandbox.restore(); // Restore all stubs + }); + + it('Should not log timeout if no Connatix bid timeout is found', function () { + const nonConnatixTimeoutData = [{ bidder: 'otherBidder', timeout: 200 }]; + + spec.onTimeout(nonConnatixTimeoutData); + + expect(window.ajax.called).to.be.false; // Adjust according to how you access 'ajax' + }); + + it('Should log Connatix timeout with specific timeout value', function () { + const specificTimeoutData = [{ bidder: 'connatix', timeout: 200 }]; + + spec.onTimeout(specificTimeoutData); + + expect(window.ajax.calledOnce).to.be.true; // Adjust according to how you access 'ajax' + const [url, callback, requestBody, options] = window.ajax.firstCall.args; + + expect(url).to.equal(EVENTS_URL); + expect(options.method).to.equal('POST'); + expect(JSON.parse(requestBody)).to.include({ type: 'timeout', timeout: 200 }); + }); + + it('Should log with default bidderTimeout if requestTimeout is not a number', function () { + configStub.withArgs('bidderTimeout').returns(500); // Mock config value + + const invalidTimeoutData = [{ bidder: 'connatix', timeout: null }]; + spec.onTimeout(invalidTimeoutData); + + expect(window.ajax.calledOnce).to.be.true; // Adjust according to how you access 'ajax' + const [url, callback, requestBody] = window.ajax.firstCall.args; + + expect(url).to.equal(EVENTS_URL); + expect(requestBody).to.contain('"timeout":500'); + }); + + it('Should send a POST request with JSON data', function () { + spec.onTimeout(timeoutData); + + expect(window.ajax.calledOnce).to.be.true; // Adjust according to how you access 'ajax' + const [url, callback, requestBody, options] = window.ajax.firstCall.args; + + expect(url).to.equal(EVENTS_URL); + expect(options.method).to.equal('POST'); + expect(options.withCredentials).to.be.false; + expect(requestBody).to.be.a('string'); + expect(JSON.parse(requestBody)).to.have.property('type', 'timeout'); + }); + }); + describe('isBidRequestValid', function () { this.beforeEach(function () { bid = mockBidRequest(); @@ -433,4 +580,39 @@ describe('connatixBidAdapter', function () { expect(floor).to.equal(0); }); }); + + describe('onBidWon', () => { + it('should send a POST request with bid win data', () => { + const bidWinData = { + bidder: 'connatix', + cpm: 1.5, + requestId: '12345', + adUnitCode: 'adunit1', + timeToRespond: 300, + auctionId: 'auction1', + }; + + spec.onBidWon(bidWinData); + + expect(ajaxStub.calledOnce).to.be.true; + const expectedData = { + type: 'bid_won', + bestBidBidder: 'connatix', + bestBidPrice: 1.5, + requestId: '12345', + adUnitCode: 'adunit1', + timeToRespond: 300, + auctionId: 'auction1', + context: undefined, // Add context if needed + }; + expect(ajaxStub.args[0][2]).to.deep.equal(JSON.stringify(expectedData)); + expect(ajaxStub.args[0][3].method).to.equal('POST'); + expect(ajaxStub.args[0][3].withCredentials).to.be.false; + }); + + it('should not send a request if bidWinData is null', () => { + spec.onBidWon(null); + expect(ajaxStub.notCalled).to.be.true; + }); + }); }); From 1b6c4814231ad84c52901d10c75f6f12447df06b Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Thu, 5 Sep 2024 10:42:34 +0300 Subject: [PATCH 15/20] test --- test/spec/modules/connatixBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index ebd618b95ad..1f63a39e4da 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -582,7 +582,7 @@ describe('connatixBidAdapter', function () { }); describe('onBidWon', () => { - it('should send a POST request with bid win data', () => { + it('should send a POST requests with bid win data', () => { const bidWinData = { bidder: 'connatix', cpm: 1.5, From 18a2227f7922d42e4f1b659017afe9b669538859 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Thu, 5 Sep 2024 18:00:49 +0300 Subject: [PATCH 16/20] fix unit tests --- modules/connatixBidAdapter.js | 25 ++-- test/spec/modules/connatixBidAdapter_spec.js | 144 ++++++++----------- 2 files changed, 68 insertions(+), 101 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index d0f2c47e4f9..3eed2e02c79 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -4,16 +4,16 @@ import { import { config } from '../src/config.js'; +import { ajax } from '../src/ajax.js'; import { deepAccess, - isFn, - logError, - isArray, - formatQS, deepSetValue, - isNumber + formatQS, + isArray, + isFn, + isNumber, + logError } from '../src/utils.js'; -import { ajax } from '../src/ajax.js'; import { ADPOD, @@ -238,7 +238,6 @@ export const spec = { /** * Register bidder specific code, which will execute if the server response time is greater than auction timeout - * @param {TimedOutBid} timeoutData */ onTimeout: (timeoutData) => { const connatixBidRequestTimeout = timeoutData.find(bidderRequest => bidderRequest.bidder === BIDDER_CODE); @@ -250,15 +249,11 @@ export const spec = { } const requestTimeout = connatixBidRequestTimeout.timeout; const timeout = isNumber(requestTimeout) ? requestTimeout : config.getConfig('bidderTimeout'); - ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'timeout', timeout, context}), { - method: 'POST', - withCredentials: false - }); + spec.triggerEvent({type: 'Timeout', timeout, context}); }, /** * Register bidder specific code, which will execute if a bid from this bidder won the auction - * @param {Bid} bid The bid that won the auction */ onBidWon(bidWinData) { if (bidWinData == null) { @@ -266,7 +261,11 @@ export const spec = { } const {bidder, cpm, requestId, adUnitCode, timeToRespond, auctionId} = bidWinData; - ajax(`${EVENTS_URL}`, null, JSON.stringify({type: 'bid_won', bestBidBidder: bidder, bestBidPrice: cpm, requestId, adUnitCode, timeToRespond, auctionId, context}), { + spec.triggerEvent({type: 'BidWon', bestBidBidder: bidder, bestBidPrice: cpm, requestId, adUnitCode, timeToRespond, auctionId, context}); + }, + + triggerEvent(data) { + ajax(EVENTS_URL, null, JSON.stringify(data), { method: 'POST', withCredentials: false }); diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index 1f63a39e4da..6a3203823e4 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -4,11 +4,8 @@ import { getBidFloor as connatixGetBidFloor, spec, } from '../../../modules/connatixBidAdapter.js'; -import { config } from '../../../src/config.js'; import { ADPOD, BANNER, VIDEO } from '../../../src/mediaTypes.js'; -const sinon = require('sinon'); - describe('connatixBidAdapter', function () { let bid; @@ -120,74 +117,80 @@ describe('connatixBidAdapter', function () { }); }); - describe('spec onTimeout', function () { - let sandbox; - let configStub; + describe('onTimeout', function () { + let ajaxStub; - const EVENTS_URL = 'https://capi.connatix.com/tr/am'; + beforeEach(() => { + ajaxStub = sinon.stub(spec, 'triggerEvent') + }) - const timeoutData = [ - { bidder: 'connatix', timeout: 300 }, - { bidder: 'otherBidder', timeout: 200 } - ]; + afterEach(() => { + ajaxStub.restore() + }); - beforeEach(function () { - sandbox = sinon.createSandbox(); + it('call event if bidder is connatix', () => { + const result = spec.onTimeout([{ + bidder: 'connatix', + timeout: 500, + }]); + expect(ajaxStub.calledOnce).to.equal(true); - // Replace the following with the correct way to access 'ajax' - sandbox.stub(window, 'ajax'); // or sandbox.stub(ajax, 'call'); - configStub = sandbox.stub(config, 'getConfig'); // Stub config to mock bidderTimeout + const data = ajaxStub.firstCall.args[0]; + expect(data.type).to.equal('Timeout'); + expect(data.timeout).to.equal(500); }); - afterEach(function () { - sandbox.restore(); // Restore all stubs + it('timeout event is not triggered if bidder is not connatix', () => { + const result = spec.onTimeout([{ + bidder: 'otherBidder', + timeout: 500, + }]); + expect(ajaxStub.notCalled).to.equal(true); }); + }); - it('Should not log timeout if no Connatix bid timeout is found', function () { - const nonConnatixTimeoutData = [{ bidder: 'otherBidder', timeout: 200 }]; - - spec.onTimeout(nonConnatixTimeoutData); + describe('onBidWon', function () { + let ajaxStub; - expect(window.ajax.called).to.be.false; // Adjust according to how you access 'ajax' + beforeEach(() => { + ajaxStub = sinon.stub(spec, 'triggerEvent'); }); - it('Should log Connatix timeout with specific timeout value', function () { - const specificTimeoutData = [{ bidder: 'connatix', timeout: 200 }]; - - spec.onTimeout(specificTimeoutData); - - expect(window.ajax.calledOnce).to.be.true; // Adjust according to how you access 'ajax' - const [url, callback, requestBody, options] = window.ajax.firstCall.args; - - expect(url).to.equal(EVENTS_URL); - expect(options.method).to.equal('POST'); - expect(JSON.parse(requestBody)).to.include({ type: 'timeout', timeout: 200 }); + afterEach(() => { + ajaxStub.restore(); }); - it('Should log with default bidderTimeout if requestTimeout is not a number', function () { - configStub.withArgs('bidderTimeout').returns(500); // Mock config value - - const invalidTimeoutData = [{ bidder: 'connatix', timeout: null }]; - spec.onTimeout(invalidTimeoutData); + it('calls triggerEvent with correct data when bidWinData is provided', () => { + const bidWinData = { + bidder: 'connatix', + cpm: 2.5, + requestId: 'abc123', + adUnitCode: 'adunit_1', + timeToRespond: 300, + auctionId: 'auction_456', + }; - expect(window.ajax.calledOnce).to.be.true; // Adjust according to how you access 'ajax' - const [url, callback, requestBody] = window.ajax.firstCall.args; + spec.onBidWon(bidWinData); + expect(ajaxStub.calledOnce).to.equal(true); - expect(url).to.equal(EVENTS_URL); - expect(requestBody).to.contain('"timeout":500'); + const eventData = ajaxStub.firstCall.args[0]; + expect(eventData.type).to.equal('BidWon'); + expect(eventData.bestBidBidder).to.equal('connatix'); + expect(eventData.bestBidPrice).to.equal(2.5); + expect(eventData.requestId).to.equal('abc123'); + expect(eventData.adUnitCode).to.equal('adunit_1'); + expect(eventData.timeToRespond).to.equal(300); + expect(eventData.auctionId).to.equal('auction_456'); }); - it('Should send a POST request with JSON data', function () { - spec.onTimeout(timeoutData); - - expect(window.ajax.calledOnce).to.be.true; // Adjust according to how you access 'ajax' - const [url, callback, requestBody, options] = window.ajax.firstCall.args; + it('does not call triggerEvent if bidWinData is null', () => { + spec.onBidWon(null); + expect(ajaxStub.notCalled).to.equal(true); + }); - expect(url).to.equal(EVENTS_URL); - expect(options.method).to.equal('POST'); - expect(options.withCredentials).to.be.false; - expect(requestBody).to.be.a('string'); - expect(JSON.parse(requestBody)).to.have.property('type', 'timeout'); + it('does not call triggerEvent if bidWinData is undefined', () => { + spec.onBidWon(undefined); + expect(ajaxStub.notCalled).to.equal(true); }); }); @@ -580,39 +583,4 @@ describe('connatixBidAdapter', function () { expect(floor).to.equal(0); }); }); - - describe('onBidWon', () => { - it('should send a POST requests with bid win data', () => { - const bidWinData = { - bidder: 'connatix', - cpm: 1.5, - requestId: '12345', - adUnitCode: 'adunit1', - timeToRespond: 300, - auctionId: 'auction1', - }; - - spec.onBidWon(bidWinData); - - expect(ajaxStub.calledOnce).to.be.true; - const expectedData = { - type: 'bid_won', - bestBidBidder: 'connatix', - bestBidPrice: 1.5, - requestId: '12345', - adUnitCode: 'adunit1', - timeToRespond: 300, - auctionId: 'auction1', - context: undefined, // Add context if needed - }; - expect(ajaxStub.args[0][2]).to.deep.equal(JSON.stringify(expectedData)); - expect(ajaxStub.args[0][3].method).to.equal('POST'); - expect(ajaxStub.args[0][3].withCredentials).to.be.false; - }); - - it('should not send a request if bidWinData is null', () => { - spec.onBidWon(null); - expect(ajaxStub.notCalled).to.be.true; - }); - }); }); From dcbd986ce5125cfa8559878e7932b6d308cd1e04 Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Thu, 5 Sep 2024 18:16:28 +0300 Subject: [PATCH 17/20] more unit tests --- test/spec/modules/connatixBidAdapter_spec.js | 25 ++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index 6a3203823e4..1c3d6e8b2c3 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -4,6 +4,7 @@ import { getBidFloor as connatixGetBidFloor, spec, } from '../../../modules/connatixBidAdapter.js'; +import * as ajax from '../../../src/ajax.js'; import { ADPOD, BANNER, VIDEO } from '../../../src/mediaTypes.js'; describe('connatixBidAdapter', function () { @@ -194,6 +195,30 @@ describe('connatixBidAdapter', function () { }); }); + describe('triggerEvent', function () { + let ajaxStub; + + beforeEach(() => { + ajaxStub = sinon.stub(ajax, 'ajax'); + }); + + afterEach(() => { + ajaxStub.restore(); + }); + + it('should call ajax with the correct parameters', () => { + const data = { type: 'BidWon', bestBidBidder: 'bidder1', bestBidPrice: 1.5, requestId: 'req123', adUnitCode: 'ad123', timeToRespond: 250, auctionId: 'auc123', context: {} }; + spec.triggerEvent(data); + + expect(ajaxStub.calledOnce).to.equal(true); + const [url, _, payload, options] = ajaxStub.firstCall.args; + expect(url).to.equal('https://capi.connatix.com/tr/am'); + expect(payload).to.equal(JSON.stringify(data)); + expect(options.method).to.equal('POST'); + expect(options.withCredentials).to.equal(false); + }); + }); + describe('isBidRequestValid', function () { this.beforeEach(function () { bid = mockBidRequest(); From cdf1be4313f6db35907711387fef34640aa3794d Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Thu, 5 Sep 2024 18:50:36 +0300 Subject: [PATCH 18/20] added bid id on bid won event --- modules/connatixBidAdapter.js | 4 ++-- test/spec/modules/connatixBidAdapter_spec.js | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index 3eed2e02c79..ccb7267bae1 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -259,9 +259,9 @@ export const spec = { if (bidWinData == null) { return; } - const {bidder, cpm, requestId, adUnitCode, timeToRespond, auctionId} = bidWinData; + const {bidder, cpm, requestId, bidId, adUnitCode, timeToRespond, auctionId} = bidWinData; - spec.triggerEvent({type: 'BidWon', bestBidBidder: bidder, bestBidPrice: cpm, requestId, adUnitCode, timeToRespond, auctionId, context}); + spec.triggerEvent({type: 'BidWon', bestBidBidder: bidder, bestBidPrice: cpm, requestId, bidId, adUnitCode, timeToRespond, auctionId, context}); }, triggerEvent(data) { diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index 1c3d6e8b2c3..7b8e53888d5 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -166,6 +166,7 @@ describe('connatixBidAdapter', function () { bidder: 'connatix', cpm: 2.5, requestId: 'abc123', + bidId: 'dasdas-dsawda-dwaddw-dwdwd', adUnitCode: 'adunit_1', timeToRespond: 300, auctionId: 'auction_456', @@ -179,6 +180,7 @@ describe('connatixBidAdapter', function () { expect(eventData.bestBidBidder).to.equal('connatix'); expect(eventData.bestBidPrice).to.equal(2.5); expect(eventData.requestId).to.equal('abc123'); + expect(eventData.bidId).to.equal('dasdas-dsawda-dwaddw-dwdwd'); expect(eventData.adUnitCode).to.equal('adunit_1'); expect(eventData.timeToRespond).to.equal(300); expect(eventData.auctionId).to.equal('auction_456'); From 3206f1fd0e45733e2133b9b59030c66bd135fedb Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Tue, 10 Sep 2024 15:47:06 +0300 Subject: [PATCH 19/20] conficts --- modules/connatixBidAdapter.js | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index dc2d57a8b6e..f2c50bfe0f1 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -4,7 +4,6 @@ import { import { percentInView } from '../libraries/percentInView/percentInView.js'; - import { config } from '../src/config.js'; import { ajax } from '../src/ajax.js'; @@ -155,13 +154,19 @@ export function _getBidRequests(validBidRequests) { sizes, } = bid; const { placementId, viewabilityContainerIdentifier } = params; + let detectedViewabilityPercentage = detectViewability(bid); + if (isNumber(detectedViewabilityPercentage)) { + detectedViewabilityPercentage = detectedViewabilityPercentage / 100; + } return { bidId, mediaTypes, sizes, placementId, - hasViewabilityContainerId: Boolean(viewabilityContainerIdentifier), floor: getBidFloor(bid), + hasViewabilityContainerId: Boolean(viewabilityContainerIdentifier), + declaredViewabilityPercentage: bid.params.viewabilityPercentage ?? null, + detectedViewabilityPercentage, }; }); } @@ -220,22 +225,6 @@ export const spec = { buildRequests: (validBidRequests = [], bidderRequest = {}) => { const bidRequests = _getBidRequests(validBidRequests); - let detectedViewabilityPercentage = detectViewability(bid); - if (isNumber(detectedViewabilityPercentage)) { - detectedViewabilityPercentage = detectedViewabilityPercentage / 100; - } - - return { - bidId, - mediaTypes, - sizes, - detectedViewabilityPercentage, - declaredViewabilityPercentage: bid.params.viewabilityPercentage ?? null, - placementId: params.placementId, - floor: getBidFloor(bid), - }; - }); - const requestPayload = { ortb2: bidderRequest.ortb2, gdprConsent: bidderRequest.gdprConsent, From 9558f7baade73caf6ba1b43845000a94bc96b12d Mon Sep 17 00:00:00 2001 From: Rares Preda Date: Wed, 11 Sep 2024 00:02:36 +0300 Subject: [PATCH 20/20] fix find a bid by alias and include tests --- modules/connatixBidAdapter.js | 12 +++++- test/spec/modules/connatixBidAdapter_spec.js | 42 ++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/modules/connatixBidAdapter.js b/modules/connatixBidAdapter.js index f2c50bfe0f1..6e453e2caa7 100644 --- a/modules/connatixBidAdapter.js +++ b/modules/connatixBidAdapter.js @@ -1,3 +1,4 @@ +import adapterManager from '../src/adapterManager.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; @@ -317,11 +318,20 @@ export const spec = { }]; }, + isConnatix: (aliasName) => { + if (!aliasName) { + return false; + } + + const originalBidderName = adapterManager.aliasRegistry[aliasName] || aliasName; + return originalBidderName === BIDDER_CODE; + }, + /** * Register bidder specific code, which will execute if the server response time is greater than auction timeout */ onTimeout: (timeoutData) => { - const connatixBidRequestTimeout = timeoutData.find(bidderRequest => bidderRequest.bidder === BIDDER_CODE); + const connatixBidRequestTimeout = timeoutData.find(bidderRequest => spec.isConnatix(bidderRequest.bidder)); // Log only it is a timeout for Connatix // Otherwise it is not relevant for us diff --git a/test/spec/modules/connatixBidAdapter_spec.js b/test/spec/modules/connatixBidAdapter_spec.js index fc9ffd0e544..5c01e23b027 100644 --- a/test/spec/modules/connatixBidAdapter_spec.js +++ b/test/spec/modules/connatixBidAdapter_spec.js @@ -10,9 +10,12 @@ import { _isViewabilityMeasurable as connatixIsViewabilityMeasurable, spec } from '../../../modules/connatixBidAdapter.js'; +import adapterManager from '../../../src/adapterManager.js'; import * as ajax from '../../../src/ajax.js'; import { ADPOD, BANNER, VIDEO } from '../../../src/mediaTypes.js'; +const BIDDER_CODE = 'connatix'; + describe('connatixBidAdapter', function () { let bid; @@ -844,6 +847,45 @@ describe('connatixBidAdapter', function () { }); }); + describe('isConnatix', function () { + let aliasRegistryStub; + + beforeEach(() => { + aliasRegistryStub = sinon.stub(adapterManager, 'aliasRegistry').value({}); + }); + + afterEach(() => { + aliasRegistryStub.restore(); + }); + + it('should return false if aliasName is undefined or null', () => { + expect(spec.isConnatix(undefined)).to.be.false; + expect(spec.isConnatix(null)).to.be.false; + }); + + it('should return true if aliasName matches BIDDER_CODE', () => { + const aliasName = BIDDER_CODE; + expect(spec.isConnatix(aliasName)).to.be.true; + }); + + it('should return true if aliasName is mapped to BIDDER_CODE in aliasRegistry', () => { + const aliasName = 'connatixAlias'; + aliasRegistryStub.value({ 'connatixAlias': BIDDER_CODE }); + expect(spec.isConnatix(aliasName)).to.be.true; + }); + + it('should return false if aliasName does not match BIDDER_CODE', () => { + const aliasName = 'otherBidder'; + expect(spec.isConnatix(aliasName)).to.be.false; + }); + + it('should return false if aliasName is mapped to a different bidder in aliasRegistry', () => { + const aliasName = 'someOtherAlias'; + aliasRegistryStub.value({ 'someOtherAlias': 'otherBidder' }); + expect(spec.isConnatix(aliasName)).to.be.false; + }); + }); + describe('getBidFloor', function () { this.beforeEach(function () { bid = mockBidRequest();