From ed7f671fefff7cdaa26b479e1f03acb8eaec777e Mon Sep 17 00:00:00 2001 From: hamper Date: Tue, 5 Aug 2025 17:49:42 +0300 Subject: [PATCH 1/2] move common code to lib and add digitalcaramel adapter --- libraries/vizionikUtils/vizionikUtils.js | 109 ++++++++ modules/digitalcaramelBidAdapter.js | 51 ++++ modules/digitalcaramelBidAdapter.md | 46 +++ modules/programmaticaBidAdapter.js | 108 +------ modules/vistarsBidAdapter.js | 29 +- .../modules/digitalcaramelBidAdapter_spec.js | 263 ++++++++++++++++++ 6 files changed, 474 insertions(+), 132 deletions(-) create mode 100644 libraries/vizionikUtils/vizionikUtils.js create mode 100644 modules/digitalcaramelBidAdapter.js create mode 100644 modules/digitalcaramelBidAdapter.md create mode 100644 test/spec/modules/digitalcaramelBidAdapter_spec.js diff --git a/libraries/vizionikUtils/vizionikUtils.js b/libraries/vizionikUtils/vizionikUtils.js new file mode 100644 index 00000000000..1c87f8a9cb4 --- /dev/null +++ b/libraries/vizionikUtils/vizionikUtils.js @@ -0,0 +1,109 @@ +import { hasPurpose1Consent } from '../../src/utils/gdpr.js'; +import { BANNER, VIDEO } from '../../src/mediaTypes.js'; +import { deepAccess, isArray, parseSizesInput } from '../../src/utils.js'; + +export function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, syncEndpoint, paramNames) { + const syncs = []; + + if (!hasPurpose1Consent(gdprConsent)) { + return syncs; + } + + let params = `${paramNames?.usp ?? 'us_privacy'}=${uspConsent ?? ''}&${paramNames?.consent ?? 'gdpr_consent'}=${gdprConsent?.consentString ?? ''}`; + + if (typeof gdprConsent?.gdprApplies === 'boolean') { + params += `&gdpr=${Number(gdprConsent.gdprApplies)}`; + } + + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: `//${syncEndpoint}/match/sp.ifr?${params}`, + }); + } + + if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: `//${syncEndpoint}/match/sp?${params}`, + }); + } + + return syncs; +} + +export function sspInterpretResponse(serverResponse, request, ttl, adomain) { + if (!serverResponse?.body?.content?.data) { + return []; + } + + const bidResponses = []; + const body = serverResponse.body; + + let mediaType = BANNER; + let ad, vastXml; + let width; + let height; + + const sizes = getSize(body.size); + if (isArray(sizes)) { + [width, height] = sizes; + } + + if (body.type.format != '') { + // banner + ad = body.content.data; + if (body.content.imps?.length) { + for (const imp of body.content.imps) { + ad += ``; + } + } + } else { + // video + vastXml = body.content.data; + mediaType = VIDEO; + + if (!width || !height) { + const pSize = deepAccess(request.bidRequest, 'mediaTypes.video.playerSize'); + const reqSize = getSize(pSize); + if (isArray(reqSize)) { + [width, height] = reqSize; + } + } + } + + const bidResponse = { + requestId: request.bidRequest.bidId, + cpm: body.cpm, + currency: body.currency || 'USD', + width: parseInt(width), + height: parseInt(height), + creativeId: body.id, + netRevenue: true, + ttl: ttl, + ad: ad, + mediaType: mediaType, + vastXml: vastXml, + meta: { + advertiserDomains: [adomain], + } + }; + + if ((mediaType === VIDEO && request.bidRequest.mediaTypes?.video) || (mediaType === BANNER && request.bidRequest.mediaTypes?.banner)) { + bidResponses.push(bidResponse); + } + + return bidResponses; +} + +function getSize(paramSizes) { + const parsedSizes = parseSizesInput(paramSizes); + const sizes = parsedSizes.map(size => { + const [width, height] = size.split('x'); + const w = parseInt(width, 10); + const h = parseInt(height, 10); + return [w, h]; + }); + + return sizes[0] || null; +} diff --git a/modules/digitalcaramelBidAdapter.js b/modules/digitalcaramelBidAdapter.js new file mode 100644 index 00000000000..8c107245fa6 --- /dev/null +++ b/modules/digitalcaramelBidAdapter.js @@ -0,0 +1,51 @@ +import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import { getUserSyncs, sspInterpretResponse } from '../libraries/vizionikUtils/vizionikUtils.js'; + +const BIDDER_CODE = 'digitalcaramel'; +const DEFAULT_ENDPOINT = 'ssp-asr.digitalcaramel.com'; +const SYNC_ENDPOINT = 'sync.digitalcaramel.com'; +const ADOMAIN = 'digitalcaramel.com'; +const TIME_TO_LIVE = 360; + +export const spec = { + code: BIDDER_CODE, + + isBidRequestValid: function(bid) { + const valid = bid.params.siteId && bid.params.placementId; + + return !!valid; + }, + + buildRequests: function(validBidRequests, bidderRequest) { + const requests = []; + for (const bid of validBidRequests) { + const endpoint = bid.params.endpoint || DEFAULT_ENDPOINT; + + requests.push({ + method: 'GET', + url: `https://${endpoint}/get`, + data: { + site_id: bid.params.siteId, + placement_id: bid.params.placementId, + prebid: true, + }, + bidRequest: bid, + }); + } + + return requests; + }, + + interpretResponse: function(serverResponse, request) { + return sspInterpretResponse(serverResponse, request, TIME_TO_LIVE, ADOMAIN); + }, + + getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { + return getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_ENDPOINT, {usp: 'usp', consent: 'consent'}) + }, + + supportedMediaTypes: [ BANNER, VIDEO ] +} + +registerBidder(spec); diff --git a/modules/digitalcaramelBidAdapter.md b/modules/digitalcaramelBidAdapter.md new file mode 100644 index 00000000000..428e46c72fe --- /dev/null +++ b/modules/digitalcaramelBidAdapter.md @@ -0,0 +1,46 @@ +# Overview + +``` +Module Name: Digitalcaramel Bid Adapter +Module Type: Bidder Adapter +Maintainer: tech@digitalcaramel.com +``` + +# Description +Connects to Digitalcaramel server for bids. +Module supports banner and video mediaType. + +# Test Parameters + +``` + var adUnits = [{ + code: '/test/div', + mediaTypes: { + banner: { + sizes: [[300, 250]] + } + }, + bids: [{ + bidder: 'digitalcaramel', + params: { + siteId: 'd1d83nbdi0fs73874a0g', + placementId: 'd1d8493di0fs73874a10' + } + }] + }, + { + code: '/test/div', + mediaTypes: { + video: { + playerSize: [[640, 360]] + } + }, + bids: [{ + bidder: 'digitalcaramel', + params: { + siteId: 'd1d83nbdi0fs73874a0g', + placementId: 'd24v2ijdi0fs73874afg' + } + }] + },]; +``` diff --git a/modules/programmaticaBidAdapter.js b/modules/programmaticaBidAdapter.js index efc9450d9b7..f44a5292b51 100644 --- a/modules/programmaticaBidAdapter.js +++ b/modules/programmaticaBidAdapter.js @@ -1,7 +1,6 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import { hasPurpose1Consent } from '../src/utils/gdpr.js'; -import { deepAccess, parseSizesInput, isArray } from '../src/utils.js'; +import { getUserSyncs, sspInterpretResponse } from '../libraries/vizionikUtils/vizionikUtils.js'; const BIDDER_CODE = 'programmatica'; const DEFAULT_ENDPOINT = 'asr.programmatica.com'; @@ -39,115 +38,14 @@ export const spec = { }, interpretResponse: function(serverResponse, request) { - if (!serverResponse?.body?.content?.data) { - return []; - } - - const bidResponses = []; - const body = serverResponse.body; - - let mediaType = BANNER; - let ad, vastXml; - let width; - let height; - - const sizes = getSize(body.size); - if (isArray(sizes)) { - [width, height] = sizes; - } - - if (body.type.format != '') { - // banner - ad = body.content.data; - if (body.content.imps?.length) { - for (const imp of body.content.imps) { - ad += ``; - } - } - } else { - // video - vastXml = body.content.data; - mediaType = VIDEO; - - if (!width || !height) { - const pSize = deepAccess(request.bidRequest, 'mediaTypes.video.playerSize'); - const reqSize = getSize(pSize); - if (isArray(reqSize)) { - [width, height] = reqSize; - } - } - } - - const bidResponse = { - requestId: request.bidRequest.bidId, - cpm: body.cpm, - currency: body.currency || 'USD', - width: parseInt(width), - height: parseInt(height), - creativeId: body.id, - netRevenue: true, - ttl: TIME_TO_LIVE, - ad: ad, - mediaType: mediaType, - vastXml: vastXml, - meta: { - advertiserDomains: [ADOMAIN], - } - }; - - if ((mediaType === VIDEO && request.bidRequest.mediaTypes?.video) || (mediaType === BANNER && request.bidRequest.mediaTypes?.banner)) { - bidResponses.push(bidResponse); - } - - return bidResponses; + return sspInterpretResponse(serverResponse, request, TIME_TO_LIVE, ADOMAIN); }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { - const syncs = [] - - if (!hasPurpose1Consent(gdprConsent)) { - return syncs; - } - - let params = `usp=${uspConsent ?? ''}&consent=${gdprConsent?.consentString ?? ''}`; - if (typeof gdprConsent?.gdprApplies === 'boolean') { - params += `&gdpr=${Number(gdprConsent.gdprApplies)}`; - } - - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: `//${SYNC_ENDPOINT}/match/sp.ifr?${params}` - }); - } - - if (syncOptions.pixelEnabled) { - syncs.push({ - type: 'image', - url: `//${SYNC_ENDPOINT}/match/sp?${params}` - }); - } - - return syncs; + return getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_ENDPOINT, {usp: 'usp', consent: 'consent'}) }, - onTimeout: function(timeoutData) {}, - onBidWon: function(bid) {}, - onSetTargeting: function(bid) {}, - onBidderError: function() {}, supportedMediaTypes: [ BANNER, VIDEO ] } registerBidder(spec); - -function getSize(paramSizes) { - const parsedSizes = parseSizesInput(paramSizes); - const sizes = parsedSizes.map(size => { - const [width, height] = size.split('x'); - const w = parseInt(width, 10); - const h = parseInt(height, 10); - return [w, h]; - }); - - return sizes[0] || null; -} diff --git a/modules/vistarsBidAdapter.js b/modules/vistarsBidAdapter.js index 7f6606ca1c1..0cc315ace68 100644 --- a/modules/vistarsBidAdapter.js +++ b/modules/vistarsBidAdapter.js @@ -1,8 +1,8 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import { hasPurpose1Consent } from '../src/utils/gdpr.js'; import { deepSetValue, replaceAuctionPrice, deepClone, deepAccess } from '../src/utils.js'; import { ortbConverter } from '../libraries/ortbConverter/converter.js'; +import { getUserSyncs } from '../libraries/vizionikUtils/vizionikUtils.js'; const BIDDER_CODE = 'vistars'; const DEFAULT_ENDPOINT = 'ex-asr.vistarsagency.com'; @@ -77,32 +77,7 @@ export const spec = { }, getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { - const syncs = [] - - if (!hasPurpose1Consent(gdprConsent)) { - return syncs; - } - - let params = `us_privacy=${uspConsent || ''}&gdpr_consent=${gdprConsent?.consentString ? gdprConsent.consentString : ''}`; - if (typeof gdprConsent?.gdprApplies === 'boolean') { - params += `&gdpr=${Number(gdprConsent.gdprApplies)}`; - } - - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: `//${SYNC_ENDPOINT}/match/sp.ifr?${params}` - }); - } - - if (syncOptions.pixelEnabled) { - syncs.push({ - type: 'image', - url: `//${SYNC_ENDPOINT}/match/sp?${params}` - }); - } - - return syncs; + return getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_ENDPOINT) }, supportedMediaTypes: [ BANNER, VIDEO ] diff --git a/test/spec/modules/digitalcaramelBidAdapter_spec.js b/test/spec/modules/digitalcaramelBidAdapter_spec.js new file mode 100644 index 00000000000..4b295ecd6bb --- /dev/null +++ b/test/spec/modules/digitalcaramelBidAdapter_spec.js @@ -0,0 +1,263 @@ +import { expect } from 'chai'; +import { spec } from 'modules/digitalcaramelBidAdapter.js'; +import { deepClone } from 'src/utils.js'; + +describe('digitalcaramelBidAdapterTests', function () { + const bidRequestData = { + bids: [ + { + bidId: 'testbid', + bidder: 'digitalcaramel', + params: { + siteId: 'testsite', + placementId: 'testplacement', + }, + sizes: [[300, 250]] + } + ] + }; + const request = []; + + it('validate_pub_params', function () { + expect( + spec.isBidRequestValid({ + bidder: 'digitalcaramel', + params: { + siteId: 'testsite', + placementId: 'testplacement', + } + }) + ).to.equal(true); + }); + + it('validate_generated_url', function () { + const request = spec.buildRequests(deepClone(bidRequestData.bids), { timeout: 1234 }); + const req_url = request[0].url; + + expect(req_url).to.equal('https://ssp-asr.digitalcaramel.com/get'); + }); + + it('validate_response_params', function () { + const serverResponse = { + body: { + 'id': 'crid', + 'type': { + 'format': 'Image', + 'source': 'passback', + 'dspId': '', + 'dspCreativeId': '' + }, + 'content': { + 'data': 'test ad', + 'imps': null, + 'click': { + 'url': '', + 'track': null + } + }, + 'size': '300x250', + 'matching': '', + 'cpm': 10, + 'currency': 'USD' + } + }; + + const bidRequest = deepClone(bidRequestData.bids) + bidRequest[0].mediaTypes = { + banner: {} + } + + const request = spec.buildRequests(bidRequest); + const bids = spec.interpretResponse(serverResponse, request[0]); + expect(bids).to.have.lengthOf(1); + + const bid = bids[0]; + expect(bid.ad).to.equal('test ad'); + expect(bid.cpm).to.equal(10); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.creativeId).to.equal('crid'); + expect(bid.meta.advertiserDomains).to.deep.equal(['digitalcaramel.com']); + }); + + it('validate_response_params_imps', function () { + const serverResponse = { + body: { + 'id': 'crid', + 'type': { + 'format': 'Image', + 'source': 'passback', + 'dspId': '', + 'dspCreativeId': '' + }, + 'content': { + 'data': 'test ad', + 'imps': [ + 'testImp' + ], + 'click': { + 'url': '', + 'track': null + } + }, + 'size': '300x250', + 'matching': '', + 'cpm': 10, + 'currency': 'USD' + } + }; + + const bidRequest = deepClone(bidRequestData.bids) + bidRequest[0].mediaTypes = { + banner: {} + } + + const request = spec.buildRequests(bidRequest); + const bids = spec.interpretResponse(serverResponse, request[0]); + expect(bids).to.have.lengthOf(1); + + const bid = bids[0]; + expect(bid.ad).to.equal('test ad'); + expect(bid.cpm).to.equal(10); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.creativeId).to.equal('crid'); + expect(bid.meta.advertiserDomains).to.deep.equal(['digitalcaramel.com']); + }) + + it('validate_invalid_response', function () { + const serverResponse = { + body: {} + }; + + const bidRequest = deepClone(bidRequestData.bids) + bidRequest[0].mediaTypes = { + banner: {} + } + + const request = spec.buildRequests(bidRequest); + const bids = spec.interpretResponse(serverResponse, request[0]); + expect(bids).to.have.lengthOf(0); + }) + + it('video_bid', function () { + const bidRequest = deepClone(bidRequestData.bids); + bidRequest[0].mediaTypes = { + video: { + playerSize: [234, 765] + } + }; + + const request = spec.buildRequests(bidRequest, { timeout: 1234 }); + const vastXml = ''; + const serverResponse = { + body: { + 'id': 'cki2n3n6snkuulqutpf0', + 'type': { + 'format': '', + 'source': 'rtb', + 'dspId': '1' + }, + 'content': { + 'data': vastXml, + 'imps': [ + 'https://ssp-asr.dev.digitalcaramel.com/track/imp' + ], + 'click': { + 'url': '', + 'track': null + } + }, + 'size': '', + 'matching': '', + 'cpm': 70, + 'currency': 'RUB' + } + }; + + const bids = spec.interpretResponse(serverResponse, request[0]); + expect(bids).to.have.lengthOf(1); + + const bid = bids[0]; + expect(bid.mediaType).to.equal('video'); + expect(bid.vastXml).to.equal(vastXml); + expect(bid.width).to.equal(234); + expect(bid.height).to.equal(765); + }); +}); + +describe('getUserSyncs', function() { + it('returns empty sync array', function() { + const syncOptions = {}; + + expect(spec.getUserSyncs(syncOptions)).to.deep.equal([]); + }); + + it('Should return array of objects with proper sync config , include CCPA', function() { + const syncData = spec.getUserSyncs({ + pixelEnabled: true, + }, {}, {}, '1---'); + expect(syncData).to.be.an('array').which.is.not.empty; + expect(syncData[0]).to.be.an('object') + expect(syncData[0].type).to.be.a('string') + expect(syncData[0].type).to.equal('image') + expect(syncData[0].url).to.be.a('string') + expect(syncData[0].url).to.equal('//sync.digitalcaramel.com/match/sp?usp=1---&consent=') + }); + + it('Should return array of objects with proper sync config , include GDPR', function() { + const syncData = spec.getUserSyncs({ + iframeEnabled: true, + }, {}, { + gdprApplies: true, + consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw', + vendorData: { + purpose: { + consents: { + 1: true + }, + }, + } + }, ''); + expect(syncData).to.be.an('array').which.is.not.empty; + expect(syncData[0]).to.be.an('object') + expect(syncData[0].type).to.be.a('string') + expect(syncData[0].type).to.equal('iframe') + expect(syncData[0].url).to.be.a('string') + expect(syncData[0].url).to.equal('//sync.digitalcaramel.com/match/sp.ifr?usp=&consent=COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&gdpr=1') + }); + + it('Should return array of objects with proper sync config , include GDPR, no purpose', function() { + const syncData = spec.getUserSyncs({ + iframeEnabled: true, + }, {}, { + gdprApplies: true, + consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw', + vendorData: { + purpose: { + consents: { + 1: false + }, + }, + } + }, ''); + expect(syncData).is.empty; + }); + + it('Should return array of objects with proper sync config , GDPR not applies', function() { + const syncData = spec.getUserSyncs({ + iframeEnabled: true, + }, {}, { + gdprApplies: false, + consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw', + }, ''); + expect(syncData).to.be.an('array').which.is.not.empty; + expect(syncData[0]).to.be.an('object') + expect(syncData[0].type).to.be.a('string') + expect(syncData[0].type).to.equal('iframe') + expect(syncData[0].url).to.be.a('string') + expect(syncData[0].url).to.equal('//sync.digitalcaramel.com/match/sp.ifr?usp=&consent=COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw&gdpr=0') + }); +}) From 5a9e5a2a72c9d9b30f8b2dc85d0eba189f445b1e Mon Sep 17 00:00:00 2001 From: hamper Date: Tue, 5 Aug 2025 19:30:22 +0300 Subject: [PATCH 2/2] more deduplication --- libraries/vizionikUtils/vizionikUtils.js | 172 ++++++++++++++--------- modules/digitalcaramelBidAdapter.js | 40 +----- modules/programmaticaBidAdapter.js | 40 +----- modules/vistarsBidAdapter.js | 4 +- 4 files changed, 113 insertions(+), 143 deletions(-) diff --git a/libraries/vizionikUtils/vizionikUtils.js b/libraries/vizionikUtils/vizionikUtils.js index 1c87f8a9cb4..6a544271ba3 100644 --- a/libraries/vizionikUtils/vizionikUtils.js +++ b/libraries/vizionikUtils/vizionikUtils.js @@ -2,98 +2,130 @@ import { hasPurpose1Consent } from '../../src/utils/gdpr.js'; import { BANNER, VIDEO } from '../../src/mediaTypes.js'; import { deepAccess, isArray, parseSizesInput } from '../../src/utils.js'; -export function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, syncEndpoint, paramNames) { - const syncs = []; +export function getUserSyncs(syncEndpoint, paramNames) { + return function(syncOptions, serverResponses, gdprConsent, uspConsent) { + const syncs = []; - if (!hasPurpose1Consent(gdprConsent)) { - return syncs; - } + if (!hasPurpose1Consent(gdprConsent)) { + return syncs; + } - let params = `${paramNames?.usp ?? 'us_privacy'}=${uspConsent ?? ''}&${paramNames?.consent ?? 'gdpr_consent'}=${gdprConsent?.consentString ?? ''}`; + let params = `${paramNames?.usp ?? 'us_privacy'}=${uspConsent ?? ''}&${paramNames?.consent ?? 'gdpr_consent'}=${gdprConsent?.consentString ?? ''}`; - if (typeof gdprConsent?.gdprApplies === 'boolean') { - params += `&gdpr=${Number(gdprConsent.gdprApplies)}`; - } + if (typeof gdprConsent?.gdprApplies === 'boolean') { + params += `&gdpr=${Number(gdprConsent.gdprApplies)}`; + } - if (syncOptions.iframeEnabled) { - syncs.push({ - type: 'iframe', - url: `//${syncEndpoint}/match/sp.ifr?${params}`, - }); - } + if (syncOptions.iframeEnabled) { + syncs.push({ + type: 'iframe', + url: `//${syncEndpoint}/match/sp.ifr?${params}`, + }); + } - if (syncOptions.pixelEnabled) { - syncs.push({ - type: 'image', - url: `//${syncEndpoint}/match/sp?${params}`, - }); - } + if (syncOptions.pixelEnabled) { + syncs.push({ + type: 'image', + url: `//${syncEndpoint}/match/sp?${params}`, + }); + } - return syncs; + return syncs; + } } -export function sspInterpretResponse(serverResponse, request, ttl, adomain) { - if (!serverResponse?.body?.content?.data) { - return []; - } +export function sspInterpretResponse(ttl, adomain) { + return function(serverResponse, request) { + if (!serverResponse?.body?.content?.data) { + return []; + } - const bidResponses = []; - const body = serverResponse.body; + const bidResponses = []; + const body = serverResponse.body; - let mediaType = BANNER; - let ad, vastXml; - let width; - let height; + let mediaType = BANNER; + let ad, vastXml; + let width; + let height; - const sizes = getSize(body.size); - if (isArray(sizes)) { - [width, height] = sizes; - } + const sizes = getSize(body.size); + if (isArray(sizes)) { + [width, height] = sizes; + } - if (body.type.format != '') { - // banner - ad = body.content.data; - if (body.content.imps?.length) { - for (const imp of body.content.imps) { - ad += ``; + if (body.type.format != '') { + // banner + ad = body.content.data; + if (body.content.imps?.length) { + for (const imp of body.content.imps) { + ad += ``; + } + } + } else { + // video + vastXml = body.content.data; + mediaType = VIDEO; + + if (!width || !height) { + const pSize = deepAccess(request.bidRequest, 'mediaTypes.video.playerSize'); + const reqSize = getSize(pSize); + if (isArray(reqSize)) { + [width, height] = reqSize; + } } } - } else { - // video - vastXml = body.content.data; - mediaType = VIDEO; - - if (!width || !height) { - const pSize = deepAccess(request.bidRequest, 'mediaTypes.video.playerSize'); - const reqSize = getSize(pSize); - if (isArray(reqSize)) { - [width, height] = reqSize; + + const bidResponse = { + requestId: request.bidRequest.bidId, + cpm: body.cpm, + currency: body.currency || 'USD', + width: parseInt(width), + height: parseInt(height), + creativeId: body.id, + netRevenue: true, + ttl: ttl, + ad: ad, + mediaType: mediaType, + vastXml: vastXml, + meta: { + advertiserDomains: [adomain], } + }; + + if ((mediaType === VIDEO && request.bidRequest.mediaTypes?.video) || (mediaType === BANNER && request.bidRequest.mediaTypes?.banner)) { + bidResponses.push(bidResponse); } + + return bidResponses; } +} - const bidResponse = { - requestId: request.bidRequest.bidId, - cpm: body.cpm, - currency: body.currency || 'USD', - width: parseInt(width), - height: parseInt(height), - creativeId: body.id, - netRevenue: true, - ttl: ttl, - ad: ad, - mediaType: mediaType, - vastXml: vastXml, - meta: { - advertiserDomains: [adomain], +export function sspBuildRequests(defaultEndpoint) { + return function(validBidRequests, bidderRequest) { + const requests = []; + for (const bid of validBidRequests) { + const endpoint = bid.params.endpoint || defaultEndpoint; + + requests.push({ + method: 'GET', + url: `https://${endpoint}/get`, + data: { + site_id: bid.params.siteId, + placement_id: bid.params.placementId, + prebid: true, + }, + bidRequest: bid, + }); } - }; - if ((mediaType === VIDEO && request.bidRequest.mediaTypes?.video) || (mediaType === BANNER && request.bidRequest.mediaTypes?.banner)) { - bidResponses.push(bidResponse); + return requests; } +} + +export function sspValidRequest(bid) { + const valid = bid.params.siteId && bid.params.placementId; - return bidResponses; + return !!valid; } function getSize(paramSizes) { diff --git a/modules/digitalcaramelBidAdapter.js b/modules/digitalcaramelBidAdapter.js index 8c107245fa6..1f045fb352d 100644 --- a/modules/digitalcaramelBidAdapter.js +++ b/modules/digitalcaramelBidAdapter.js @@ -1,6 +1,6 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import { getUserSyncs, sspInterpretResponse } from '../libraries/vizionikUtils/vizionikUtils.js'; +import { getUserSyncs, sspBuildRequests, sspInterpretResponse, sspValidRequest } from '../libraries/vizionikUtils/vizionikUtils.js'; const BIDDER_CODE = 'digitalcaramel'; const DEFAULT_ENDPOINT = 'ssp-asr.digitalcaramel.com'; @@ -11,40 +11,10 @@ const TIME_TO_LIVE = 360; export const spec = { code: BIDDER_CODE, - isBidRequestValid: function(bid) { - const valid = bid.params.siteId && bid.params.placementId; - - return !!valid; - }, - - buildRequests: function(validBidRequests, bidderRequest) { - const requests = []; - for (const bid of validBidRequests) { - const endpoint = bid.params.endpoint || DEFAULT_ENDPOINT; - - requests.push({ - method: 'GET', - url: `https://${endpoint}/get`, - data: { - site_id: bid.params.siteId, - placement_id: bid.params.placementId, - prebid: true, - }, - bidRequest: bid, - }); - } - - return requests; - }, - - interpretResponse: function(serverResponse, request) { - return sspInterpretResponse(serverResponse, request, TIME_TO_LIVE, ADOMAIN); - }, - - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { - return getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_ENDPOINT, {usp: 'usp', consent: 'consent'}) - }, - + isBidRequestValid: sspValidRequest, + buildRequests: sspBuildRequests(DEFAULT_ENDPOINT), + interpretResponse: sspInterpretResponse(TIME_TO_LIVE, ADOMAIN), + getUserSyncs: getUserSyncs(SYNC_ENDPOINT, {usp: 'usp', consent: 'consent'}), supportedMediaTypes: [ BANNER, VIDEO ] } diff --git a/modules/programmaticaBidAdapter.js b/modules/programmaticaBidAdapter.js index f44a5292b51..cb080864a7b 100644 --- a/modules/programmaticaBidAdapter.js +++ b/modules/programmaticaBidAdapter.js @@ -1,6 +1,6 @@ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { BANNER, VIDEO } from '../src/mediaTypes.js'; -import { getUserSyncs, sspInterpretResponse } from '../libraries/vizionikUtils/vizionikUtils.js'; +import { getUserSyncs, sspBuildRequests, sspInterpretResponse, sspValidRequest } from '../libraries/vizionikUtils/vizionikUtils.js'; const BIDDER_CODE = 'programmatica'; const DEFAULT_ENDPOINT = 'asr.programmatica.com'; @@ -11,40 +11,10 @@ const TIME_TO_LIVE = 360; export const spec = { code: BIDDER_CODE, - isBidRequestValid: function(bid) { - const valid = bid.params.siteId && bid.params.placementId; - - return !!valid; - }, - - buildRequests: function(validBidRequests, bidderRequest) { - const requests = []; - for (const bid of validBidRequests) { - const endpoint = bid.params.endpoint || DEFAULT_ENDPOINT; - - requests.push({ - method: 'GET', - url: `https://${endpoint}/get`, - data: { - site_id: bid.params.siteId, - placement_id: bid.params.placementId, - prebid: true, - }, - bidRequest: bid, - }); - } - - return requests; - }, - - interpretResponse: function(serverResponse, request) { - return sspInterpretResponse(serverResponse, request, TIME_TO_LIVE, ADOMAIN); - }, - - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { - return getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_ENDPOINT, {usp: 'usp', consent: 'consent'}) - }, - + isBidRequestValid: sspValidRequest, + buildRequests: sspBuildRequests(DEFAULT_ENDPOINT), + interpretResponse: sspInterpretResponse(TIME_TO_LIVE, ADOMAIN), + getUserSyncs: getUserSyncs(SYNC_ENDPOINT, {usp: 'usp', consent: 'consent'}), supportedMediaTypes: [ BANNER, VIDEO ] } diff --git a/modules/vistarsBidAdapter.js b/modules/vistarsBidAdapter.js index 0cc315ace68..305d8141bcb 100644 --- a/modules/vistarsBidAdapter.js +++ b/modules/vistarsBidAdapter.js @@ -76,9 +76,7 @@ export const spec = { return bids; }, - getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) { - return getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, SYNC_ENDPOINT) - }, + getUserSyncs: getUserSyncs(SYNC_ENDPOINT), supportedMediaTypes: [ BANNER, VIDEO ] }