diff --git a/.babelrc.js b/.babelrc.js
index c733b8876b7..43303f59a8b 100644
--- a/.babelrc.js
+++ b/.babelrc.js
@@ -14,13 +14,7 @@ module.exports = {
[
useLocal('@babel/preset-env'),
{
- "targets": {
- "browsers": [
- ">0.25%",
- "not ie 11",
- "not op_mini all"
- ]
- }
+ "useBuiltIns": "entry"
}
]
],
diff --git a/gulpfile.js b/gulpfile.js
index 8609177a8b9..98caf1d7312 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -76,6 +76,7 @@ function lint(done) {
'modules/**/*.js',
'test/**/*.js',
'plugins/**/*.js',
+ '!plugins/**/node_modules/**',
'./*.js'
], { base: './' })
.pipe(gulpif(argv.nolintfix, eslint(), eslint({ fix: true })))
diff --git a/modules/adheseBidAdapter.js b/modules/adheseBidAdapter.js
index 88f3e0e0e4f..145b5605bc2 100644
--- a/modules/adheseBidAdapter.js
+++ b/modules/adheseBidAdapter.js
@@ -2,6 +2,7 @@
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
+import { config } from '../src/config.js';
const BIDDER_CODE = 'adhese';
const GVLID = 553;
@@ -20,11 +21,15 @@ export const spec = {
if (validBidRequests.length === 0) {
return null;
}
+
const { gdprConsent, refererInfo } = bidderRequest;
+ const adheseConfig = config.getConfig('adhese');
const gdprParams = (gdprConsent && gdprConsent.consentString) ? { xt: [gdprConsent.consentString] } : {};
const refererParams = (refererInfo && refererInfo.referer) ? { xf: [base64urlEncode(refererInfo.referer)] } : {};
- const commonParams = { ...gdprParams, ...refererParams };
+ const globalCustomParams = (adheseConfig && adheseConfig.globalTargets) ? cleanTargets(adheseConfig.globalTargets) : {};
+ const commonParams = { ...globalCustomParams, ...gdprParams, ...refererParams };
+ const vastContentAsUrl = !(adheseConfig && adheseConfig.vastContentAsUrl == false);
const slots = validBidRequests.map(bid => ({
slotname: bidToSlotName(bid),
@@ -34,7 +39,7 @@ export const spec = {
const payload = {
slots: slots,
parameters: commonParams,
- vastContentAsUrl: true,
+ vastContentAsUrl: vastContentAsUrl,
user: {
ext: {
eids: getEids(validBidRequests),
diff --git a/modules/adlivetechBidAdapter.md b/modules/adlivetechBidAdapter.md
new file mode 100644
index 00000000000..612e669ea1a
--- /dev/null
+++ b/modules/adlivetechBidAdapter.md
@@ -0,0 +1,61 @@
+# Overview
+
+Module Name: Adlivetech Bidder Adapter
+Module Type: Bidder Adapter
+Maintainer: grid-tech@themediagrid.com
+
+# Description
+
+Module that connects to Grid demand source to fetch bids.
+The adapter is GDPR compliant and supports banner and video (instream and outstream).
+
+# Test Parameters
+```
+ var adUnits = [
+ {
+ code: 'test-div',
+ sizes: [[300, 250]],
+ bids: [
+ {
+ bidder: "adlivetech",
+ params: {
+ uid: '1',
+ bidFloor: 0.5
+ }
+ }
+ ]
+ },{
+ code: 'test-div',
+ sizes: [[728, 90]],
+ bids: [
+ {
+ bidder: "adlivetech",
+ params: {
+ uid: 2,
+ keywords: {
+ brandsafety: ['disaster'],
+ topic: ['stress', 'fear']
+ }
+ }
+ }
+ ]
+ },
+ {
+ code: 'test-div',
+ sizes: [[728, 90]],
+ mediaTypes: { video: {
+ context: 'instream',
+ playerSize: [728, 90],
+ mimes: ['video/mp4']
+ },
+ bids: [
+ {
+ bidder: "adlivetech",
+ params: {
+ uid: 11
+ }
+ }
+ ]
+ }
+ ];
+```
diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js
index 20e002cdc1a..c02eeccaea6 100644
--- a/modules/appnexusBidAdapter.js
+++ b/modules/appnexusBidAdapter.js
@@ -598,6 +598,10 @@ function newBid(serverBid, rtbBid, bidderRequest) {
bid.meta = Object.assign({}, bid.meta, { advertiserId: rtbBid.advertiser_id });
}
+ if (rtbBid.brand_id) {
+ bid.meta = Object.assign({}, bid.meta, { brandId: rtbBid.brand_id });
+ }
+
if (rtbBid.rtb.video) {
// shared video properties used for all 3 contexts
Object.assign(bid, {
diff --git a/modules/datablocksBidAdapter.js b/modules/datablocksBidAdapter.js
index 197ba19b1d6..43039e070c3 100644
--- a/modules/datablocksBidAdapter.js
+++ b/modules/datablocksBidAdapter.js
@@ -94,7 +94,7 @@ export const spec = {
code: 'datablocks',
// DATABLOCKS SCOPED OBJECT
- db_obj: {metrics_host: 'prebid.datablocks.net', metrics: [], metrics_timer: null, metrics_queue_time: 1000, vis_optout: false, source_id: 0},
+ db_obj: {metrics_host: 'prebid.dblks.net', metrics: [], metrics_timer: null, metrics_queue_time: 1000, vis_optout: false, source_id: 0},
// STORE THE DATABLOCKS BUYERID IN STORAGE
store_dbid: function(dbid) {
@@ -388,12 +388,12 @@ export const spec = {
};
let sourceId = validRequests[0].params.source_id || 0;
- let host = validRequests[0].params.host || 'prebid.datablocks.net';
+ let host = validRequests[0].params.host || 'prebid.dblks.net';
// RETURN WITH THE REQUEST AND PAYLOAD
return {
method: 'POST',
- url: `https://${sourceId}.${host}/openrtb/?sid=${sourceId}`,
+ url: `https://${host}/openrtb/?sid=${sourceId}`,
data: {
id: bidderRequest.auctionId,
imp: imps,
diff --git a/modules/deepintentBidAdapter.js b/modules/deepintentBidAdapter.js
index d0c8eb29993..94167b92bb0 100644
--- a/modules/deepintentBidAdapter.js
+++ b/modules/deepintentBidAdapter.js
@@ -162,7 +162,7 @@ function buildImpression(bid) {
impression = {
id: bid.bidId,
tagid: bid.params.tagId || '',
- secure: window.location.protocol === 'https' ? 1 : 0,
+ secure: window.location.protocol === 'https:' ? 1 : 0,
displaymanager: 'di_prebid',
displaymanagerver: DI_M_V,
ext: buildCustomParams(bid)
diff --git a/modules/engageyaBidAdapter.js b/modules/engageyaBidAdapter.js
index 27d1bb15af8..23b0189931f 100644
--- a/modules/engageyaBidAdapter.js
+++ b/modules/engageyaBidAdapter.js
@@ -1,7 +1,4 @@
-import {
- BANNER,
- NATIVE
-} from '../src/mediaTypes.js';
+import { BANNER, NATIVE } from '../src/mediaTypes.js';
import { createTrackPixelHtml } from '../src/utils.js';
const {
@@ -10,14 +7,21 @@ const {
const BIDDER_CODE = 'engageya';
const ENDPOINT_URL = 'https://recs.engageya.com/rec-api/getrecs.json';
const ENDPOINT_METHOD = 'GET';
+const SUPPORTED_SIZES = [
+ [100, 75], [236, 202], [100, 100], [130, 130], [200, 200], [250, 250], [300, 272], [300, 250], [300, 230], [300, 214], [300, 187], [300, 166], [300, 150], [300, 133], [300, 120], [400, 200], [300, 200], [250, 377], [620, 410], [207, 311], [310, 166], [310, 333], [190, 106], [228, 132], [300, 174], [80, 60], [600, 500], [600, 600], [1080, 610], [1080, 610], [624, 350], [650, 1168], [1080, 1920], [300, 374]
+];
-function getPageUrl() {
- var pUrl = window.location.href;
- if (isInIframe()) {
- pUrl = document.referrer ? document.referrer : pUrl;
+function getPageUrl(bidRequest, bidderRequest) {
+ if (bidRequest.params.pageUrl && bidRequest.params.pageUrl != '[PAGE_URL]') {
+ return bidRequest.params.pageUrl;
}
- pUrl = encodeURIComponent(pUrl);
- return pUrl;
+ if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) {
+ return bidderRequest.refererInfo.referer;
+ }
+ const pageUrl = (isInIframe() && document.referrer)
+ ? document.referrer
+ : window.location.href;
+ return encodeURIComponent(pageUrl);
}
function isInIframe() {
@@ -33,13 +37,14 @@ function getImageSrc(rec) {
return rec.thumbnail_path.indexOf('http') === -1 ? 'https:' + rec.thumbnail_path : rec.thumbnail_path;
}
-function getImpressionTrackers(rec) {
+function getImpressionTrackers(rec, response) {
+ const responseTrackers = [response.viewPxl];
if (!rec.trackers) {
- return [];
+ return responseTrackers;
}
const impressionTrackers = rec.trackers.impressionPixels || [];
const viewTrackers = rec.trackers.viewPixels || [];
- return [...impressionTrackers, ...viewTrackers];
+ return [...impressionTrackers, ...viewTrackers, ...responseTrackers];
}
function parseNativeResponse(rec, response) {
@@ -56,7 +61,7 @@ function parseNativeResponse(rec, response) {
displayUrl: rec.url,
cta: '',
sponsoredBy: rec.displayName,
- impressionTrackers: getImpressionTrackers(rec),
+ impressionTrackers: getImpressionTrackers(rec, response),
};
}
@@ -74,56 +79,65 @@ function parseBannerResponse(rec, response) {
}
const title = rec.title && rec.title.trim() ? `
${rec.title}
` : '';
const displayName = rec.displayName && title ? `${rec.displayName}
` : '';
- const trackers = getImpressionTrackers(rec)
+ const trackers = getImpressionTrackers(rec, response)
.map(createTrackPixelHtml)
.join('');
return `${style}`;
}
+function getImageSize(bidRequest) {
+ if (bidRequest.sizes && bidRequest.sizes.length > 0) {
+ return bidRequest.sizes[0];
+ } else if (bidRequest.nativeParams && bidRequest.nativeParams.image && bidRequest.nativeParams.image.sizes) {
+ return bidRequest.nativeParams.image.sizes;
+ }
+ return [-1, -1];
+}
+
+function isValidSize([width, height]) {
+ if (!width || !height) {
+ return false;
+ }
+ return SUPPORTED_SIZES.some(([supportedWidth, supportedHeight]) => supportedWidth === width && supportedHeight === height);
+}
+
export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER, NATIVE],
- isBidRequestValid: function (bid) {
- return bid && bid.params && bid.params.hasOwnProperty('widgetId') && bid.params.hasOwnProperty('websiteId') && !isNaN(bid.params.widgetId) && !isNaN(bid.params.websiteId);
+
+ isBidRequestValid: function (bidRequest) {
+ return bidRequest &&
+ bidRequest.params &&
+ bidRequest.params.hasOwnProperty('widgetId') &&
+ bidRequest.params.hasOwnProperty('websiteId') &&
+ !isNaN(bidRequest.params.widgetId) &&
+ !isNaN(bidRequest.params.websiteId) &&
+ isValidSize(getImageSize(bidRequest));
},
buildRequests: function (validBidRequests, bidderRequest) {
- var bidRequests = [];
- if (validBidRequests && validBidRequests.length > 0) {
- validBidRequests.forEach(function (bidRequest) {
- if (bidRequest.params) {
- var mediaType = bidRequest.hasOwnProperty('nativeParams') ? 1 : 2;
- var imageWidth = -1;
- var imageHeight = -1;
- if (bidRequest.sizes && bidRequest.sizes.length > 0) {
- imageWidth = bidRequest.sizes[0][0];
- imageHeight = bidRequest.sizes[0][1];
- } else if (bidRequest.nativeParams && bidRequest.nativeParams.image && bidRequest.nativeParams.image.sizes) {
- imageWidth = bidRequest.nativeParams.image.sizes[0];
- imageHeight = bidRequest.nativeParams.image.sizes[1];
- }
-
- var widgetId = bidRequest.params.widgetId;
- var websiteId = bidRequest.params.websiteId;
- var pageUrl = (bidRequest.params.pageUrl && bidRequest.params.pageUrl != '[PAGE_URL]') ? bidRequest.params.pageUrl : '';
- if (!pageUrl) {
- pageUrl = (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer) ? bidderRequest.refererInfo.referer : getPageUrl();
- }
- var bidId = bidRequest.bidId;
- var finalUrl = ENDPOINT_URL + '?pubid=0&webid=' + websiteId + '&wid=' + widgetId + '&url=' + pageUrl + '&ireqid=' + bidId + '&pbtpid=' + mediaType + '&imw=' + imageWidth + '&imh=' + imageHeight;
- if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprApplies && bidderRequest.consentString) {
- finalUrl += '&is_gdpr=1&gdpr_consent=' + bidderRequest.consentString;
- }
- bidRequests.push({
- url: finalUrl,
- method: ENDPOINT_METHOD,
- data: ''
- });
- }
- });
+ if (!validBidRequests) {
+ return [];
}
-
- return bidRequests;
+ return validBidRequests.map(bidRequest => {
+ if (bidRequest.params) {
+ const mediaType = bidRequest.hasOwnProperty('nativeParams') ? 1 : 2;
+ const [imageWidth, imageHeight] = getImageSize(bidRequest);
+ const widgetId = bidRequest.params.widgetId;
+ const websiteId = bidRequest.params.websiteId;
+ const pageUrl = getPageUrl(bidRequest, bidderRequest);
+ const bidId = bidRequest.bidId;
+ let finalUrl = ENDPOINT_URL + '?pubid=0&webid=' + websiteId + '&wid=' + widgetId + '&url=' + pageUrl + '&ireqid=' + bidId + '&pbtpid=' + mediaType + '&imw=' + imageWidth + '&imh=' + imageHeight;
+ if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprApplies && bidderRequest.consentString) {
+ finalUrl += '&is_gdpr=1&gdpr_consent=' + bidderRequest.consentString;
+ }
+ return {
+ url: finalUrl,
+ method: ENDPOINT_METHOD,
+ data: ''
+ };
+ }
+ }).filter(Boolean);
},
interpretResponse: function (serverResponse, bidRequest) {
@@ -135,12 +149,12 @@ export const spec = {
return response.recs.map(rec => {
let bid = {
requestId: response.ireqId,
- cpm: rec.ecpm,
width: response.imageWidth,
height: response.imageHeight,
creativeId: rec.postId,
+ cpm: rec.pecpm || (rec.ecpm / 100),
currency: 'USD',
- netRevenue: false,
+ netRevenue: !!rec.pecpm,
ttl: 360,
meta: { advertiserDomains: rec.domain ? [rec.domain] : [] },
}
diff --git a/modules/glimpseBidAdapter.js b/modules/glimpseBidAdapter.js
index b3646755d80..ea846c1a7b6 100644
--- a/modules/glimpseBidAdapter.js
+++ b/modules/glimpseBidAdapter.js
@@ -1,19 +1,22 @@
import { BANNER } from '../src/mediaTypes.js'
+import { config } from '../src/config.js'
import { getStorageManager } from '../src/storageManager.js'
import { isArray } from '../src/utils.js'
import { registerBidder } from '../src/adapters/bidderFactory.js'
const storageManager = getStorageManager()
+const GVLID = 1012
const BIDDER_CODE = 'glimpse'
const ENDPOINT = 'https://api.glimpsevault.io/ads/serving/public/v1/prebid'
const LOCAL_STORAGE_KEY = {
- glimpse: {
+ vault: {
jwt: 'gp_vault_jwt',
},
}
export const spec = {
+ gvlid: GVLID,
code: BIDDER_CODE,
supportedMediaTypes: [BANNER],
@@ -37,20 +40,28 @@ export const spec = {
* @returns {ServerRequest}
*/
buildRequests: (validBidRequests, bidderRequest) => {
- const networkId = window.networkId || -1
- const bids = validBidRequests.map(processBidRequest)
+ const demo = config.getConfig('glimpse.demo') || false
+ const account = config.getConfig('glimpse.account') || -1
+ const demand = config.getConfig('glimpse.demand') || 'glimpse'
+ const keywords = config.getConfig('glimpse.keywords') || {}
+
+ const auth = getVaultJwt()
const referer = getReferer(bidderRequest)
const gdprConsent = getGdprConsentChoice(bidderRequest)
- const jwt = getVaultJwt()
+ const bids = validBidRequests.map((bidRequest) => {
+ return processBidRequest(bidRequest, keywords)
+ })
const data = {
- auth: jwt,
+ auth,
data: {
bidderCode: spec.code,
- networkId,
- bids,
+ demo,
+ account,
+ demand,
referer,
gdprConsent,
+ bids,
}
}
@@ -65,10 +76,9 @@ export const spec = {
/**
* Parse response from Glimpse server
* @param bidResponse {ServerResponse}
- * @param bidRequest {BidRequest}
* @returns {Bid[]}
*/
- interpretResponse: (bidResponse, bidRequest) => {
+ interpretResponse: (bidResponse) => {
const isValidResponse = isValidBidResponse(bidResponse)
if (isValidResponse) {
@@ -81,16 +91,20 @@ export const spec = {
},
}
-function processBidRequest(bidRequest) {
+function processBidRequest(bidRequest, globalKeywords) {
const sizes = normalizeSizes(bidRequest.sizes)
- const keywords = bidRequest.params.keywords || []
+ const bidKeywords = bidRequest.params.keywords || {}
+ const keywords = {
+ ...globalKeywords,
+ ...bidKeywords,
+ }
return {
+ unitCode: bidRequest.adUnitCode,
bidId: bidRequest.bidId,
placementId: bidRequest.params.placementId,
- unitCode: bidRequest.adUnitCode,
- sizes,
keywords,
+ sizes,
}
}
@@ -124,7 +138,8 @@ function getReferer(bidderRequest) {
function getGdprConsentChoice(bidderRequest) {
const hasGdprConsent =
hasValue(bidderRequest) &&
- hasValue(bidderRequest.gdprConsent)
+ hasValue(bidderRequest.gdprConsent) &&
+ hasStringValue(bidderRequest.gdprConsent.consentString)
if (hasGdprConsent) {
return bidderRequest.gdprConsent
@@ -138,11 +153,11 @@ function getGdprConsentChoice(bidderRequest) {
}
function setVaultJwt(auth) {
- storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.glimpse.jwt, auth)
+ storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth)
}
function getVaultJwt() {
- return storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.glimpse.jwt) || ''
+ return storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || ''
}
function isValidBidResponse(bidResponse) {
diff --git a/modules/gptPreAuction.js b/modules/gptPreAuction.js
index 6519572b383..2dc5a6983b9 100644
--- a/modules/gptPreAuction.js
+++ b/modules/gptPreAuction.js
@@ -55,15 +55,16 @@ export const appendPbAdSlot = adUnit => {
const context = adUnit.ortb2Imp.ext.data;
const { customPbAdSlot } = _currentConfig;
- if (customPbAdSlot) {
- context.pbadslot = customPbAdSlot(adUnit.code, deepAccess(context, 'adserver.adslot'));
+ // use context.pbAdSlot if set (if someone set it already, it will take precedence over others)
+ if (context.pbadslot) {
return;
}
- // use context.pbAdSlot if set
- if (context.pbadslot) {
+ if (customPbAdSlot) {
+ context.pbadslot = customPbAdSlot(adUnit.code, deepAccess(context, 'adserver.adslot'));
return;
}
+
// use data attribute 'data-adslotid' if set
try {
const adUnitCodeDiv = document.getElementById(adUnit.code);
@@ -78,12 +79,17 @@ export const appendPbAdSlot = adUnit => {
return;
}
context.pbadslot = adUnit.code;
+ return true;
};
export const makeBidRequestsHook = (fn, adUnits, ...args) => {
appendGptSlots(adUnits);
adUnits.forEach(adUnit => {
- appendPbAdSlot(adUnit);
+ const usedAdUnitCode = appendPbAdSlot(adUnit);
+ // gpid should be set to itself if already set, or to what pbadslot was (as long as it was not adUnit code)
+ if (!adUnit.ortb2Imp.ext.gpid && !usedAdUnitCode) {
+ adUnit.ortb2Imp.ext.gpid = adUnit.ortb2Imp.ext.data.pbadslot;
+ }
});
return fn.call(this, adUnits, ...args);
};
diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js
index f62b62b7a97..6d3f8ad2792 100644
--- a/modules/gridBidAdapter.js
+++ b/modules/gridBidAdapter.js
@@ -29,7 +29,7 @@ let hasSynced = false;
export const spec = {
code: BIDDER_CODE,
- aliases: ['playwire'],
+ aliases: ['playwire', 'adlivetech'],
supportedMediaTypes: [ BANNER, VIDEO ],
/**
* Determines whether or not the given bid request is valid.
diff --git a/modules/id5IdSystem.md b/modules/id5IdSystem.md
index 8ffe29e091f..11f8ffc5609 100644
--- a/modules/id5IdSystem.md
+++ b/modules/id5IdSystem.md
@@ -1,14 +1,14 @@
# ID5 Universal ID
-The ID5 Universal ID is a shared, neutral identifier that publishers and ad tech platforms can use to recognise users even in environments where 3rd party cookies are not available. The ID5 Universal ID is designed to respect users' privacy choices and publishers’ preferences throughout the advertising value chain. For more information about the ID5 Universal ID and detailed integration docs, please visit [our documentation](https://support.id5.io/portal/en/kb/articles/prebid-js-user-id-module). We also recommend that you sign up for our [release notes](https://id5.io/universal-id/release-notes) to stay up-to-date with any changes to the implementation of the ID5 Universal ID in Prebid.
+The ID5 ID is a shared, neutral identifier that publishers and ad tech platforms can use to recognise users even in environments where 3rd party cookies are not available. The ID5 ID is designed to respect users' privacy choices and publishers’ preferences throughout the advertising value chain. For more information about the ID5 ID and detailed integration docs, please visit [our documentation](https://support.id5.io/portal/en/kb/articles/prebid-js-user-id-module).
-## ID5 Universal ID Registration
+## ID5 ID Registration
-The ID5 Universal ID is free to use, but requires a simple registration with ID5. Please visit [id5.io/universal-id](https://id5.io/universal-id) to sign up and request your ID5 Partner Number to get started.
+The ID5 ID is free to use, but requires a simple registration with ID5. Please visit [our website](https://id5.io/solutions/#publishers) to sign up and request your ID5 Partner Number to get started.
-The ID5 privacy policy is at [https://www.id5.io/platform-privacy-policy](https://www.id5.io/platform-privacy-policy).
+The ID5 privacy policy is at [https://id5.io/platform-privacy-policy](https://id5.io/platform-privacy-policy).
-## ID5 Universal ID Configuration
+## ID5 ID Configuration
First, make sure to add the ID5 submodule to your Prebid.js package with:
@@ -46,7 +46,7 @@ pbjs.setConfig({
| Param under userSync.userIds[] | Scope | Type | Description | Example |
| --- | --- | --- | --- | --- |
| name | Required | String | The name of this module: `"id5Id"` | `"id5Id"` |
-| params | Required | Object | Details for the ID5 Universal ID. | |
+| params | Required | Object | Details for the ID5 ID. | |
| params.partner | Required | Number | This is the ID5 Partner Number obtained from registering with ID5. | `173` |
| params.pd | Optional | String | Partner-supplied data used for linking ID5 IDs across domains. See [our documentation](https://support.id5.io/portal/en/kb/articles/passing-partner-data-to-id5) for details on generating the string. Omit the parameter or leave as an empty string if no data to supply | `"MT1iNTBjY..."` |
| params.provider | Optional | String | An identifier provided by ID5 to technology partners who manage Prebid setups on behalf of publishers. Reach out to [ID5](mailto:prebid@id5.io) if you have questions about this parameter | `pubmatic-identity-hub` |
diff --git a/modules/imRtdProvider.js b/modules/imRtdProvider.js
index db2c51ccf51..7ab19c0e2d6 100644
--- a/modules/imRtdProvider.js
+++ b/modules/imRtdProvider.js
@@ -37,6 +37,34 @@ function setImDataInCookie(value) {
);
}
+/**
+* @param {string} bidderName
+*/
+export function getBidderFunction(bidderName) {
+ const biddersFunction = {
+ ix: function (bid, data) {
+ if (data.im_segments && data.im_segments.length) {
+ config.setConfig({
+ ix: {firstPartyData: {im_segments: data.im_segments}},
+ });
+ }
+ return bid
+ },
+ pubmatic: function (bid, data) {
+ if (data.im_segments && data.im_segments.length) {
+ const dctr = deepAccess(bid, 'params.dctr');
+ deepSetValue(
+ bid,
+ 'params.dctr',
+ `${dctr ? dctr + '|' : ''}im_segments=${data.im_segments.join(',')}`
+ );
+ }
+ return bid
+ }
+ }
+ return biddersFunction[bidderName] || null;
+}
+
export function getCustomBidderFunction(config, bidder) {
const overwriteFn = deepAccess(config, `params.overwrites.${bidder}`)
@@ -73,9 +101,12 @@ export function setRealTimeData(bidConfig, moduleConfig, data) {
adUnits.forEach(adUnit => {
adUnit.bids.forEach(bid => {
+ const bidderFunction = getBidderFunction(bid.bidder);
const overwriteFunction = getCustomBidderFunction(moduleConfig, bid.bidder);
if (overwriteFunction) {
overwriteFunction(bid, data, utils, config);
+ } else if (bidderFunction) {
+ bidderFunction(bid, data);
}
})
});
diff --git a/modules/invibesBidAdapter.js b/modules/invibesBidAdapter.js
index 75da1509f19..d715ecf6663 100644
--- a/modules/invibesBidAdapter.js
+++ b/modules/invibesBidAdapter.js
@@ -77,12 +77,14 @@ function isBidRequestValid(bid) {
function buildRequest(bidRequests, bidderRequest) {
bidderRequest = bidderRequest || {};
const _placementIds = [];
+ const _adUnitCodes = [];
let _loginId, _customEndpoint, _userId;
let _ivAuctionStart = bidderRequest.auctionStart || Date.now();
bidRequests.forEach(function (bidRequest) {
bidRequest.startTime = new Date().getTime();
_placementIds.push(bidRequest.params.placementId);
+ _adUnitCodes.push(bidRequest.adUnitCode);
_loginId = _loginId || bidRequest.params.loginId;
_customEndpoint = _customEndpoint || bidRequest.params.customEndpoint;
_customUserSync = _customUserSync || bidRequest.params.customUserSync;
@@ -99,6 +101,7 @@ function buildRequest(bidRequests, bidderRequest) {
let userIdModel = getUserIds(_userId);
let bidParamsJson = {
placementIds: _placementIds,
+ adUnitCodes: _adUnitCodes,
loginId: _loginId,
auctionStartTime: _ivAuctionStart,
bidVersion: CONSTANTS.PREBID_VERSION
@@ -181,9 +184,12 @@ function handleResponse(responseObj, bidRequests) {
const bidResponses = [];
for (let i = 0; i < bidRequests.length; i++) {
let bidRequest = bidRequests[i];
+ let usedPlacementId = responseObj.UseAdUnitCode === true
+ ? bidRequest.params.placementId + '_' + bidRequest.adUnitCode
+ : bidRequest.params.placementId;
- if (invibes.placementBids.indexOf(bidRequest.params.placementId) > -1) {
- logInfo('Invibes Adapter - Placement was previously bid on ' + bidRequest.params.placementId);
+ if (invibes.placementBids.indexOf(usedPlacementId) > -1) {
+ logInfo('Invibes Adapter - Placement was previously bid on ' + usedPlacementId);
continue;
}
@@ -191,21 +197,21 @@ function handleResponse(responseObj, bidRequests) {
if (responseObj.AdPlacements != null) {
for (let j = 0; j < responseObj.AdPlacements.length; j++) {
let bidModel = responseObj.AdPlacements[j].BidModel;
- if (bidModel != null && bidModel.PlacementId == bidRequest.params.placementId) {
+ if (bidModel != null && bidModel.PlacementId == usedPlacementId) {
requestPlacement = responseObj.AdPlacements[j];
break;
}
}
} else {
let bidModel = responseObj.BidModel;
- if (bidModel != null && bidModel.PlacementId == bidRequest.params.placementId) {
+ if (bidModel != null && bidModel.PlacementId == usedPlacementId) {
requestPlacement = responseObj;
}
}
- let bid = createBid(bidRequest, requestPlacement, responseObj.MultipositionEnabled);
+ let bid = createBid(bidRequest, requestPlacement, responseObj.MultipositionEnabled, usedPlacementId);
if (bid !== null) {
- invibes.placementBids.push(bidRequest.params.placementId);
+ invibes.placementBids.push(usedPlacementId);
bidResponses.push(bid);
}
}
@@ -213,9 +219,9 @@ function handleResponse(responseObj, bidRequests) {
return bidResponses;
}
-function createBid(bidRequest, requestPlacement, multipositionEnabled) {
+function createBid(bidRequest, requestPlacement, multipositionEnabled, usedPlacementId) {
if (requestPlacement === null || requestPlacement.BidModel === null) {
- logInfo('Invibes Adapter - Placement not configured for bidding ' + bidRequest.params.placementId);
+ logInfo('Invibes Adapter - Placement not configured for bidding ' + usedPlacementId);
return null;
}
@@ -684,7 +690,7 @@ let keywords = (function () {
return kw;
}());
-// =====================
+// ======================
export function resetInvibes() {
invibes.optIn = undefined;
diff --git a/modules/ixBidAdapter.js b/modules/ixBidAdapter.js
index 0a686ddace2..af981a226c0 100644
--- a/modules/ixBidAdapter.js
+++ b/modules/ixBidAdapter.js
@@ -1,6 +1,9 @@
import { deepAccess, parseGPTSingleSizeArray, inIframe, deepClone, logError, logWarn, isFn, contains, isInteger, isArray, deepSetValue, parseQueryStringParameters, isEmpty, mergeDeep, convertTypes } from '../src/utils.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { config } from '../src/config.js';
+import { EVENTS } from '../src/constants.json';
+import { getStorageManager } from '../src/storageManager.js';
+import events from '../src/events.js';
import find from 'core-js-pure/features/array/find.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { INSTREAM, OUTSTREAM } from '../src/video.js';
@@ -20,15 +23,23 @@ const VIDEO_TIME_TO_LIVE = 3600; // 1hr
const NET_REVENUE = true;
const MAX_REQUEST_SIZE = 8000;
const MAX_REQUEST_LIMIT = 4;
-
const PRICE_TO_DOLLAR_FACTOR = {
JPY: 1
};
const USER_SYNC_URL = 'https://js-sec.indexww.com/um/ixmatch.html';
const RENDERER_URL = 'https://js-sec.indexww.com/htv/video-player.js';
const FLOOR_SOURCE = { PBJS: 'p', IX: 'x' };
-// determines which eids we send and the rtiPartner field in ext
-
+export const ERROR_CODES = {
+ BID_SIZE_INVALID_FORMAT: 1,
+ BID_SIZE_NOT_INCLUDED: 2,
+ PROPERTY_NOT_INCLUDED: 3,
+ SITE_ID_INVALID_VALUE: 4,
+ BID_FLOOR_INVALID_FORMAT: 5,
+ IX_FPD_EXCEEDS_MAX_SIZE: 6,
+ EXCEEDS_MAX_SIZE: 7,
+ PB_FPD_EXCEEDS_MAX_SIZE: 8,
+ VIDEO_DURATION_INVALID: 9
+};
const FIRST_PARTY_DATA = {
SITE: [
'id', 'name', 'domain', 'cat', 'sectioncat', 'pagecat', 'page', 'ref', 'search', 'mobile',
@@ -36,7 +47,6 @@ const FIRST_PARTY_DATA = {
],
USER: ['id', 'buyeruid', 'yob', 'gender', 'keywords', 'customdata', 'geo', 'data', 'ext']
};
-
const SOURCE_RTI_MAPPING = {
'liveramp.com': 'idl',
'netid.de': 'NETID',
@@ -45,7 +55,6 @@ const SOURCE_RTI_MAPPING = {
'uidapi.com': 'UID2',
'adserver.org': 'TDID'
};
-
const PROVIDERS = [
'britepoolid',
'id5id',
@@ -62,9 +71,7 @@ const PROVIDERS = [
'TDID',
'flocId'
];
-
const REQUIRED_VIDEO_PARAMS = ['mimes', 'minduration', 'maxduration']; // note: protocol/protocols is also reqd
-
const VIDEO_PARAMS_ALLOW_LIST = [
'mimes', 'minduration', 'maxduration', 'protocols', 'protocol',
'startdelay', 'placement', 'linearity', 'skip', 'skipmin',
@@ -73,6 +80,17 @@ const VIDEO_PARAMS_ALLOW_LIST = [
'delivery', 'pos', 'companionad', 'api', 'companiontype', 'ext',
'playerSize', 'w', 'h'
];
+const LOCAL_STORAGE_KEY = 'ixdiag';
+let hasRegisteredHandler = false;
+export const storage = getStorageManager(GLOBAL_VENDOR_ID, BIDDER_CODE);
+
+// Possible values for bidResponse.seatBid[].bid[].mtype which indicates the type of the creative markup so that it can properly be associated with the right sub-object of the BidRequest.Imp.
+const MEDIA_TYPES = {
+ Banner: 1,
+ Video: 2,
+ Audio: 3,
+ Native: 4
+}
/**
* Transform valid bid request config object to banner impression object that will be sent to ad server.
@@ -125,7 +143,10 @@ function bidToVideoImp(bid) {
}
if (imp.video.minduration > imp.video.maxduration) {
- logError(`IX Bid Adapter: video minduration [${imp.video.minduration}] cannot be greater than video maxduration [${imp.video.maxduration}]`);
+ logError(
+ `IX Bid Adapter: video minduration [${imp.video.minduration}] cannot be greater than video maxduration [${imp.video.maxduration}]`,
+ { bidder: BIDDER_CODE, code: ERROR_CODES.VIDEO_DURATION_INVALID }
+ );
return {};
}
@@ -262,9 +283,14 @@ function parseBid(rawBid, currency, bidRequest) {
bid.currency = currency;
bid.creativeId = rawBid.hasOwnProperty('crid') ? rawBid.crid : '-';
- // in the event of a video
- if (deepAccess(rawBid, 'ext.vasturl')) {
+ if (rawBid.mtype == MEDIA_TYPES.Video) {
+ bid.vastXml = rawBid.adm
+ } else if (rawBid.ext && rawBid.ext.vasturl) {
bid.vastUrl = rawBid.ext.vasturl
+ }
+
+ // in the event of a video
+ if ((rawBid.ext && rawBid.ext.vasturl) || rawBid.mtype == MEDIA_TYPES.Video) {
bid.width = bidRequest.video.w;
bid.height = bidRequest.video.h;
bid.mediaType = VIDEO;
@@ -498,6 +524,13 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
r.ext.ixdiag[key] = ixdiag[key];
}
+ // Get cached errors stored in LocalStorage
+ const cachedErrors = getCachedErrors();
+
+ if (!isEmpty(cachedErrors)) {
+ r.ext.ixdiag.err = cachedErrors;
+ }
+
// if an schain is provided, send it along
if (validBidRequests[0].schain) {
r.source = {
@@ -576,7 +609,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
const baseRequestSize = `${baseUrl}${parseQueryStringParameters({ ...payload, r: JSON.stringify(r) })}`.length;
if (baseRequestSize > MAX_REQUEST_SIZE) {
- logError('ix bidder: Base request size has exceeded maximum request size.');
+ logError('IX Bid Adapter: Base request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.EXCEEDS_MAX_SIZE });
return requests;
}
@@ -606,7 +639,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
}
currentRequestSize += fpdRequestSize;
} else {
- logError('ix bidder: IX config FPD request size has exceeded maximum request size.');
+ logError('IX Bid Adapter: IX config FPD request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.IX_FPD_EXCEEDS_MAX_SIZE });
}
}
@@ -713,7 +746,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
const fpdRequestSize = encodeURIComponent(JSON.stringify({ ...site, ...user })).length;
currentRequestSize += fpdRequestSize;
} else {
- logError('ix bidder: FPD request size has exceeded maximum request size.');
+ logError('IX Bid Adapter: FPD request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.PB_FPD_EXCEEDS_MAX_SIZE });
}
}
@@ -946,10 +979,99 @@ function createMissingBannerImp(bid, imp, newSize) {
}
/**
+ * @typedef {Array[message: string, err: Object]} ErrorData
+ * @property {string} message - The error message.
+ * @property {object} err - The error object.
+ * @property {string} err.bidder - The bidder of the error.
+ * @property {string} err.code - The error code.
+ */
+
+/**
+ * Error Event handler that receives type and arguments in a data object.
+ *
+ * @param {ErrorData} data
+ */
+function errorEventHandler(data) {
+ if (!storage.localStorageIsEnabled()) {
+ return;
+ }
+
+ let currentStorage;
+
+ try {
+ currentStorage = JSON.parse(storage.getDataFromLocalStorage(LOCAL_STORAGE_KEY) || '{}');
+ } catch (e) {
+ logWarn('ix can not read ixdiag from localStorage.');
+ }
+
+ const todayDate = new Date();
+
+ Object.keys(currentStorage).map((errorDate) => {
+ const date = new Date(errorDate);
+
+ if (date.setDate(date.getDate() + 7) - todayDate < 0) {
+ delete currentStorage[errorDate];
+ }
+ });
+
+ if (data.type === 'ERROR' && data.arguments && data.arguments[1] && data.arguments[1].bidder === BIDDER_CODE) {
+ const todayString = todayDate.toISOString().slice(0, 10);
+
+ const errorCode = data.arguments[1].code;
+
+ if (errorCode) {
+ currentStorage[todayString] = currentStorage[todayString] || {};
+
+ if (!Number(currentStorage[todayString][errorCode])) {
+ currentStorage[todayString][errorCode] = 0;
+ }
+
+ currentStorage[todayString][errorCode]++;
+ };
+ }
+
+ storage.setDataInLocalStorage(LOCAL_STORAGE_KEY, JSON.stringify(currentStorage));
+}
+
+/**
+ * Get ixdiag stored in LocalStorage and format to be added to request payload
+ *
+ * @returns {Object} Object with error codes and counts
+ */
+function getCachedErrors() {
+ if (!storage.localStorageIsEnabled()) {
+ return;
+ }
+
+ const errors = {};
+ let currentStorage;
+
+ try {
+ currentStorage = JSON.parse(storage.getDataFromLocalStorage(LOCAL_STORAGE_KEY) || '{}');
+ } catch (e) {
+ logError('ix can not read ixdiag from localStorage.');
+ return null;
+ }
+
+ Object.keys(currentStorage).forEach((date) => {
+ Object.keys(currentStorage[date]).forEach((code) => {
+ if (typeof currentStorage[date][code] === 'number') {
+ errors[code] = errors[code]
+ ? errors[code] + currentStorage[date][code]
+ : currentStorage[date][code];
+ }
+ });
+ });
+
+ return errors;
+}
+
+/**
+ *
* Initialize Outstream Renderer
* @param {Object} bid
*/
-function outstreamRenderer (bid) {
+function outstreamRenderer(bid) {
bid.renderer.push(() => {
var config = {
width: bid.width,
@@ -957,7 +1079,13 @@ function outstreamRenderer (bid) {
timeout: 3000
};
- window.IXOutstreamPlayer(bid.vastUrl, bid.adUnitCode, config);
+ // IXOutstreamPlayer supports both vastUrl and vastXml, so we can pass either.
+ // Since vastUrl is going to be deprecated from exchange response, vastXml takes priority.
+ if (bid.vastXml) {
+ window.IXOutstreamPlayer(bid.vastXml, bid.adUnitCode, config);
+ } else {
+ window.IXOutstreamPlayer(bid.vastUrl, bid.adUnitCode, config);
+ }
});
}
@@ -966,7 +1094,7 @@ function outstreamRenderer (bid) {
* @param {string} id
* @returns {Renderer}
*/
-function createRenderer (id) {
+function createRenderer(id) {
const renderer = Renderer.install({
id: id,
url: RENDERER_URL,
@@ -1000,6 +1128,12 @@ export const spec = {
* @return {boolean} True if this is a valid bid, and false otherwise.
*/
isBidRequestValid: function (bid) {
+ if (!hasRegisteredHandler) {
+ events.on(EVENTS.AUCTION_DEBUG, errorEventHandler);
+ events.on(EVENTS.AD_RENDER_FAILED, errorEventHandler);
+ hasRegisteredHandler = true;
+ }
+
const paramsVideoRef = deepAccess(bid, 'params.video');
const paramsSize = deepAccess(bid, 'params.size');
const mediaTypeBannerSizes = deepAccess(bid, 'mediaTypes.banner.sizes');
@@ -1009,6 +1143,7 @@ export const spec = {
const hasBidFloorCur = bid.params.hasOwnProperty('bidFloorCur');
if (bid.hasOwnProperty('mediaType') && !(contains(SUPPORTED_AD_TYPES, bid.mediaType))) {
+ logWarn('IX Bid Adapter: media type is not supported.');
return false;
}
@@ -1020,26 +1155,26 @@ export const spec = {
// since there is an ix bidder level size, make sure its valid
const ixSize = getFirstSize(paramsSize);
if (!ixSize) {
- logError('ix bidder params: size has invalid format.');
+ logError('IX Bid Adapter: size has invalid format.', { bidder: BIDDER_CODE, code: ERROR_CODES.BID_SIZE_INVALID_FORMAT });
return false;
}
// check if the ix bidder level size, is present in ad unit level
if (!includesSize(bid.sizes, ixSize) &&
!(includesSize(mediaTypeVideoPlayerSize, ixSize)) &&
!(includesSize(mediaTypeBannerSizes, ixSize))) {
- logError('ix bidder params: bid size is not included in ad unit sizes or player size.');
+ logError('IX Bid Adapter: bid size is not included in ad unit sizes or player size.', { bidder: BIDDER_CODE, code: ERROR_CODES.BID_SIZE_NOT_INCLUDED });
return false;
}
}
if (typeof bid.params.siteId !== 'string' && typeof bid.params.siteId !== 'number') {
- logError('ix bidder params: siteId must be string or number value.');
+ logError('IX Bid Adapter: siteId must be string or number value.', { bidder: BIDDER_CODE, code: ERROR_CODES.SITE_ID_INVALID_VALUE });
return false;
}
if (hasBidFloor || hasBidFloorCur) {
if (!(hasBidFloor && hasBidFloorCur && isValidBidFloorParams(bid.params.bidFloor, bid.params.bidFloorCur))) {
- logError('ix bidder params: bidFloor / bidFloorCur parameter has invalid format.');
+ logError('IX Bid Adapter: bidFloor / bidFloorCur parameter has invalid format.', { bidder: BIDDER_CODE, code: ERROR_CODES.BID_FLOOR_INVALID_FORMAT });
return false;
}
}
@@ -1048,7 +1183,7 @@ export const spec = {
const errorList = checkVideoParams(mediaTypeVideoRef, paramsVideoRef);
if (errorList.length) {
errorList.forEach((err) => {
- logError(err);
+ logError(err, { bidder: BIDDER_CODE, code: ERROR_CODES.PROPERTY_NOT_INCLUDED });
});
return false;
}
@@ -1169,6 +1304,16 @@ export const spec = {
bids.push(bid);
}
+
+ if (deepAccess(requestBid, 'ext.ixdiag.err')) {
+ if (storage.localStorageIsEnabled()) {
+ try {
+ storage.removeDataFromLocalStorage(LOCAL_STORAGE_KEY);
+ } catch (e) {
+ logError('ix can not clear ixdiag from localStorage.');
+ }
+ }
+ }
}
return bids;
diff --git a/modules/oguryBidAdapter.js b/modules/oguryBidAdapter.js
index 40843d58d02..1654f11249f 100644
--- a/modules/oguryBidAdapter.js
+++ b/modules/oguryBidAdapter.js
@@ -83,7 +83,8 @@ function buildRequests(validBidRequests, bidderRequest) {
bidfloor: getFloor(bidRequest),
banner: {
format: sizes
- }
+ },
+ ext: bidRequest.params
});
}
});
diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js
index eb165e886e8..60b441e2c10 100644
--- a/modules/openxBidAdapter.js
+++ b/modules/openxBidAdapter.js
@@ -42,7 +42,12 @@ export const USER_ID_CODE_TO_QUERY_ARG = {
novatiq: 'novatiqid', // Novatiq ID
mwOpenLinkId: 'mwopenlinkid', // MediaWallah OpenLink ID
dapId: 'dapid', // Akamai DAP ID
- amxId: 'amxid' // AMX RTB ID
+ amxId: 'amxid', // AMX RTB ID
+ kpuid: 'kpuid', // Kinesso ID
+ publinkId: 'publinkid', // Publisher Link
+ naveggId: 'naveggid', // Navegg ID
+ imuid: 'imuid', // IM-UID by Intimate Merger
+ adtelligentId: 'adtelligentid' // Adtelligent ID
};
export const spec = {
diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js
index 2d53bda4e78..74b7b39b0da 100644
--- a/modules/pubmaticBidAdapter.js
+++ b/modules/pubmaticBidAdapter.js
@@ -11,6 +11,7 @@ const USER_SYNC_URL_IFRAME = 'https://ads.pubmatic.com/AdServer/js/user_sync.htm
const USER_SYNC_URL_IMAGE = 'https://image8.pubmatic.com/AdServer/ImgSync?p=';
const DEFAULT_CURRENCY = 'USD';
const AUCTION_TYPE = 1;
+const GROUPM_ALIAS = {code: 'groupm', gvlid: 98};
const UNDEFINED = undefined;
const DEFAULT_WIDTH = 0;
const DEFAULT_HEIGHT = 0;
@@ -1005,6 +1006,7 @@ export const spec = {
code: BIDDER_CODE,
gvlid: 76,
supportedMediaTypes: [BANNER, VIDEO, NATIVE],
+ aliases: [GROUPM_ALIAS],
/**
* Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid
*
diff --git a/modules/saambaaBidAdapter.js b/modules/saambaaBidAdapter.js
new file mode 100644
index 00000000000..2810853532d
--- /dev/null
+++ b/modules/saambaaBidAdapter.js
@@ -0,0 +1,420 @@
+import { deepAccess, isFn, generateUUID, parseUrl, isEmpty, parseSizesInput } from '../src/utils.js';
+import { config } from '../src/config.js';
+import { registerBidder } from '../src/adapters/bidderFactory.js';
+import { VIDEO, BANNER } from '../src/mediaTypes.js';
+import find from 'core-js-pure/features/array/find.js';
+import includes from 'core-js-pure/features/array/includes.js';
+
+const ADAPTER_VERSION = '1.0';
+const BIDDER_CODE = 'saambaa';
+
+export const VIDEO_ENDPOINT = 'https://nep.advangelists.com/xp/get?pubid=';
+export const BANNER_ENDPOINT = 'https://nep.advangelists.com/xp/get?pubid=';
+export const OUTSTREAM_SRC = 'https://player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js';
+export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration', 'skip', 'playerSize', 'context'];
+export const DEFAULT_MIMES = ['video/mp4', 'application/javascript'];
+
+let pubid = '';
+
+export const spec = {
+ code: BIDDER_CODE,
+ supportedMediaTypes: [BANNER, VIDEO],
+
+ isBidRequestValid(bidRequest) {
+ if (typeof bidRequest != 'undefined') {
+ if (bidRequest.bidder !== BIDDER_CODE && typeof bidRequest.params === 'undefined') { return false; }
+ if (bidRequest === '' || bidRequest.params.placement === '' || bidRequest.params.pubid === '') { return false; }
+ return true;
+ } else { return false; }
+ },
+
+ buildRequests(bids, bidderRequest) {
+ let requests = [];
+ let videoBids = bids.filter(bid => isVideoBidValid(bid));
+ let bannerBids = bids.filter(bid => isBannerBidValid(bid));
+ videoBids.forEach(bid => {
+ pubid = getVideoBidParam(bid, 'pubid');
+ requests.push({
+ method: 'POST',
+ url: VIDEO_ENDPOINT + pubid,
+ data: createVideoRequestData(bid, bidderRequest),
+ bidRequest: bid
+ });
+ });
+
+ bannerBids.forEach(bid => {
+ pubid = getBannerBidParam(bid, 'pubid');
+
+ requests.push({
+ method: 'POST',
+ url: BANNER_ENDPOINT + pubid,
+ data: createBannerRequestData(bid, bidderRequest),
+ bidRequest: bid
+ });
+ });
+ return requests;
+ },
+
+ interpretResponse(serverResponse, {bidRequest}) {
+ let response = serverResponse.body;
+ if (response !== null && isEmpty(response) == false) {
+ if (isVideoBid(bidRequest)) {
+ let bidResponse = {
+ requestId: response.id,
+ bidderCode: BIDDER_CODE,
+ cpm: response.seatbid[0].bid[0].price,
+ width: response.seatbid[0].bid[0].w,
+ height: response.seatbid[0].bid[0].h,
+ ttl: response.seatbid[0].bid[0].ttl || 60,
+ creativeId: response.seatbid[0].bid[0].crid,
+ currency: response.cur,
+ meta: { 'advertiserDomains': response.seatbid[0].bid[0].adomain },
+ mediaType: VIDEO,
+ netRevenue: true
+ }
+
+ if (response.seatbid[0].bid[0].adm) {
+ bidResponse.vastXml = response.seatbid[0].bid[0].adm;
+ bidResponse.adResponse = {
+ content: response.seatbid[0].bid[0].adm
+ };
+ } else {
+ bidResponse.vastUrl = response.seatbid[0].bid[0].nurl;
+ }
+
+ return bidResponse;
+ } else {
+ return {
+ requestId: response.id,
+ bidderCode: BIDDER_CODE,
+ cpm: response.seatbid[0].bid[0].price,
+ width: response.seatbid[0].bid[0].w,
+ height: response.seatbid[0].bid[0].h,
+ ad: response.seatbid[0].bid[0].adm,
+ ttl: response.seatbid[0].bid[0].ttl || 60,
+ creativeId: response.seatbid[0].bid[0].crid,
+ currency: response.cur,
+ meta: { 'advertiserDomains': response.seatbid[0].bid[0].adomain },
+ mediaType: BANNER,
+ netRevenue: true
+ }
+ }
+ }
+ }
+};
+
+function isBannerBid(bid) {
+ return deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid);
+}
+
+function isVideoBid(bid) {
+ return deepAccess(bid, 'mediaTypes.video');
+}
+
+function getBannerBidFloor(bid) {
+ let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'banner', size: '*' }) : {};
+ return floorInfo.floor || getBannerBidParam(bid, 'bidfloor');
+}
+
+function getVideoBidFloor(bid) {
+ let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'video', size: '*' }) : {};
+ return floorInfo.floor || getVideoBidParam(bid, 'bidfloor');
+}
+
+function isVideoBidValid(bid) {
+ return isVideoBid(bid) && getVideoBidParam(bid, 'pubid') && getVideoBidParam(bid, 'placement');
+}
+
+function isBannerBidValid(bid) {
+ return isBannerBid(bid) && getBannerBidParam(bid, 'pubid') && getBannerBidParam(bid, 'placement');
+}
+
+function getVideoBidParam(bid, key) {
+ return deepAccess(bid, 'params.video.' + key) || deepAccess(bid, 'params.' + key);
+}
+
+function getBannerBidParam(bid, key) {
+ return deepAccess(bid, 'params.banner.' + key) || deepAccess(bid, 'params.' + key);
+}
+
+function isMobile() {
+ return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent);
+}
+
+function isConnectedTV() {
+ return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent);
+}
+
+function getDoNotTrack() {
+ return navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNoTrack === '1' || navigator.doNotTrack === 'yes';
+}
+
+function findAndFillParam(o, key, value) {
+ try {
+ if (typeof value === 'function') {
+ o[key] = value();
+ } else {
+ o[key] = value;
+ }
+ } catch (ex) {}
+}
+
+function getOsVersion() {
+ let clientStrings = [
+ { s: 'Android', r: /Android/ },
+ { s: 'iOS', r: /(iPhone|iPad|iPod)/ },
+ { s: 'Mac OS X', r: /Mac OS X/ },
+ { s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ },
+ { s: 'Linux', r: /(Linux|X11)/ },
+ { s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ },
+ { s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ },
+ { s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ },
+ { s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ },
+ { s: 'Windows Vista', r: /Windows NT 6.0/ },
+ { s: 'Windows Server 2003', r: /Windows NT 5.2/ },
+ { s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ },
+ { s: 'UNIX', r: /UNIX/ },
+ { s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ }
+ ];
+ let cs = find(clientStrings, cs => cs.r.test(navigator.userAgent));
+ return cs ? cs.s : 'unknown';
+}
+
+function getFirstSize(sizes) {
+ return (sizes && sizes.length) ? sizes[0] : { w: undefined, h: undefined };
+}
+
+function parseSizes(sizes) {
+ return parseSizesInput(sizes).map(size => {
+ let [ width, height ] = size.split('x');
+ return {
+ w: parseInt(width, 10) || undefined,
+ h: parseInt(height, 10) || undefined
+ };
+ });
+}
+
+function getVideoSizes(bid) {
+ return parseSizes(deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes);
+}
+
+function getBannerSizes(bid) {
+ return parseSizes(deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes);
+}
+
+function getTopWindowReferrer() {
+ try {
+ return window.top.document.referrer;
+ } catch (e) {
+ return '';
+ }
+}
+
+function getVideoTargetingParams(bid) {
+ const result = {};
+ const excludeProps = ['playerSize', 'context', 'w', 'h'];
+ Object.keys(Object(bid.mediaTypes.video))
+ .filter(key => !includes(excludeProps, key))
+ .forEach(key => {
+ result[ key ] = bid.mediaTypes.video[ key ];
+ });
+ Object.keys(Object(bid.params.video))
+ .filter(key => includes(VIDEO_TARGETING, key))
+ .forEach(key => {
+ result[ key ] = bid.params.video[ key ];
+ });
+ return result;
+}
+
+function createVideoRequestData(bid, bidderRequest) {
+ let topLocation = getTopWindowLocation(bidderRequest);
+ let topReferrer = getTopWindowReferrer();
+
+ // if size is explicitly given via adapter params
+ let paramSize = getVideoBidParam(bid, 'size');
+ let sizes = [];
+ let coppa = config.getConfig('coppa');
+
+ if (typeof paramSize !== 'undefined' && paramSize != '') {
+ sizes = parseSizes(paramSize);
+ } else {
+ sizes = getVideoSizes(bid);
+ }
+ const firstSize = getFirstSize(sizes);
+ let floor = (getVideoBidFloor(bid) == null || typeof getVideoBidFloor(bid) == 'undefined') ? 0.5 : getVideoBidFloor(bid);
+ let video = getVideoTargetingParams(bid);
+ const o = {
+ 'device': {
+ 'langauge': (global.navigator.language).split('-')[0],
+ 'dnt': (global.navigator.doNotTrack === 1 ? 1 : 0),
+ 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2,
+ 'js': 1,
+ 'os': getOsVersion()
+ },
+ 'at': 2,
+ 'site': {},
+ 'tmax': 3000,
+ 'cur': ['USD'],
+ 'id': bid.bidId,
+ 'imp': [],
+ 'regs': {
+ 'ext': {
+ }
+ },
+ 'user': {
+ 'ext': {
+ }
+ }
+ };
+
+ o.site['page'] = topLocation.href;
+ o.site['domain'] = topLocation.hostname;
+ o.site['search'] = topLocation.search;
+ o.site['domain'] = topLocation.hostname;
+ o.site['ref'] = topReferrer;
+ o.site['mobile'] = isMobile() ? 1 : 0;
+ const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0;
+
+ o.device['dnt'] = getDoNotTrack() ? 1 : 0;
+
+ findAndFillParam(o.site, 'name', function() {
+ return global.top.document.title;
+ });
+
+ findAndFillParam(o.device, 'h', function() {
+ return global.screen.height;
+ });
+ findAndFillParam(o.device, 'w', function() {
+ return global.screen.width;
+ });
+
+ let placement = getVideoBidParam(bid, 'placement');
+
+ for (let j = 0; j < sizes.length; j++) {
+ o.imp.push({
+ 'id': '' + j,
+ 'displaymanager': '' + BIDDER_CODE,
+ 'displaymanagerver': '' + ADAPTER_VERSION,
+ 'tagId': placement,
+ 'bidfloor': floor,
+ 'bidfloorcur': 'USD',
+ 'secure': secure,
+ 'video': Object.assign({
+ 'id': generateUUID(),
+ 'pos': 0,
+ 'w': firstSize.w,
+ 'h': firstSize.h,
+ 'mimes': DEFAULT_MIMES
+ }, video)
+
+ });
+ }
+ if (coppa) {
+ o.regs.ext = {'coppa': 1};
+ }
+ if (bidderRequest && bidderRequest.gdprConsent) {
+ let { gdprApplies, consentString } = bidderRequest.gdprConsent;
+ o.regs.ext = {'gdpr': gdprApplies ? 1 : 0};
+ o.user.ext = {'consent': consentString};
+ }
+
+ return o;
+}
+
+function getTopWindowLocation(bidderRequest) {
+ let url = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer;
+ return parseUrl(config.getConfig('pageUrl') || url, { decodeSearchAsString: true });
+}
+
+function createBannerRequestData(bid, bidderRequest) {
+ let topLocation = getTopWindowLocation(bidderRequest);
+ let topReferrer = getTopWindowReferrer();
+
+ // if size is explicitly given via adapter params
+
+ let paramSize = getBannerBidParam(bid, 'size');
+ let sizes = [];
+ let coppa = config.getConfig('coppa');
+ if (typeof paramSize !== 'undefined' && paramSize != '') {
+ sizes = parseSizes(paramSize);
+ } else {
+ sizes = getBannerSizes(bid);
+ }
+
+ let floor = (getBannerBidFloor(bid) == null || typeof getBannerBidFloor(bid) == 'undefined') ? 0.1 : getBannerBidFloor(bid);
+ const o = {
+ 'device': {
+ 'langauge': (global.navigator.language).split('-')[0],
+ 'dnt': (global.navigator.doNotTrack === 1 ? 1 : 0),
+ 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2,
+ 'js': 1
+ },
+ 'at': 2,
+ 'site': {},
+ 'tmax': 3000,
+ 'cur': ['USD'],
+ 'id': bid.bidId,
+ 'imp': [],
+ 'regs': {
+ 'ext': {
+ }
+ },
+ 'user': {
+ 'ext': {
+ }
+ }
+ };
+
+ o.site['page'] = topLocation.href;
+ o.site['domain'] = topLocation.hostname;
+ o.site['search'] = topLocation.search;
+ o.site['domain'] = topLocation.hostname;
+ o.site['ref'] = topReferrer;
+ o.site['mobile'] = isMobile() ? 1 : 0;
+ const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0;
+
+ o.device['dnt'] = getDoNotTrack() ? 1 : 0;
+
+ findAndFillParam(o.site, 'name', function() {
+ return global.top.document.title;
+ });
+
+ findAndFillParam(o.device, 'h', function() {
+ return global.screen.height;
+ });
+ findAndFillParam(o.device, 'w', function() {
+ return global.screen.width;
+ });
+
+ let placement = getBannerBidParam(bid, 'placement');
+ for (let j = 0; j < sizes.length; j++) {
+ let size = sizes[j];
+
+ o.imp.push({
+ 'id': '' + j,
+ 'displaymanager': '' + BIDDER_CODE,
+ 'displaymanagerver': '' + ADAPTER_VERSION,
+ 'tagId': placement,
+ 'bidfloor': floor,
+ 'bidfloorcur': 'USD',
+ 'secure': secure,
+ 'banner': {
+ 'id': generateUUID(),
+ 'pos': 0,
+ 'w': size['w'],
+ 'h': size['h']
+ }
+ });
+ }
+ if (coppa) {
+ o.regs.ext = {'coppa': 1};
+ }
+ if (bidderRequest && bidderRequest.gdprConsent) {
+ let { gdprApplies, consentString } = bidderRequest.gdprConsent;
+ o.regs.ext = {'gdpr': gdprApplies ? 1 : 0};
+ o.user.ext = {'consent': consentString};
+ }
+
+ return o;
+}
+registerBidder(spec);
diff --git a/modules/saambaaBidAdapter.md b/modules/saambaaBidAdapter.md
index 2d391da7628..d58e3f0abfa 100755
--- a/modules/saambaaBidAdapter.md
+++ b/modules/saambaaBidAdapter.md
@@ -1,69 +1,66 @@
-# Overview
-
-```
-Module Name: Saambaa Bidder Adapter
-Module Type: Bidder Adapter
-Maintainer: matt.voigt@saambaa.com
-```
-
-# Description
-
-Connects to Saambaa exchange for bids.
-
-Saambaa bid adapter supports Banner and Video ads currently.
-
-For more informatio
-
-# Sample Display Ad Unit: For Publishers
-```javascript
-
-var displayAdUnit = [
-{
- code: 'display',
- mediaTypes: {
- banner: {
- sizes: [[300, 250],[320, 50]]
- }
- }
- bids: [{
- bidder: 'saambaa',
- params: {
- pubid: '121ab139faf7ac67428a23f1d0a9a71b',
- placement: 1234,
- size: '320x50'
- }
- }]
-}];
-```
-
-# Sample Video Ad Unit: For Publishers
-```javascript
-
-var videoAdUnit = {
- code: 'video',
- sizes: [320,480],
- mediaTypes: {
- video: {
- playerSize : [[320, 480]],
- context: 'instream'
- }
- },
- bids: [
- {
- bidder: 'saambaa',
- params: {
- pubid: '121ab139faf7ac67428a23f1d0a9a71b',
- placement: 1234,
- size: "320x480",
- video: {
- id: 123,
- skip: 1,
- mimes : ['video/mp4', 'application/javascript'],
- playbackmethod : [2,6],
- maxduration: 30
- }
- }
- }
- ]
- };
+# Overview
+
+```
+Module Name: Saambaa Bidder Adapter
+Module Type: Bidder Adapter
+Maintainer: matt.voigt@saambaa.com
+```
+
+# Description
+
+Connects to Saambaa exchange for bids.
+
+Saambaa bid adapter supports Banner and Video ads currently.
+
+For more informatio
+
+# Sample Display Ad Unit: For Publishers
+```javascript
+
+var displayAdUnit = [
+{
+ code: 'display',
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250],[320, 50]]
+ }
+ }
+ bids: [{
+ bidder: 'saambaa',
+ params: {
+ pubid: '121ab139faf7ac67428a23f1d0a9a71b',
+ placement: 1234,
+ size: '320x50'
+ }
+ }]
+}];
+```
+
+# Sample Video Ad Unit: For Publishers
+```javascript
+
+var videoAdUnit = {
+ code: 'video',
+ sizes: [320,480],
+ mediaTypes: {
+ video: {
+ playerSize : [[320, 480]],
+ context: 'instream',
+ skip: 1,
+ mimes : ['video/mp4', 'application/javascript'],
+ playbackmethod : [2,6],
+ maxduration: 30
+ }
+ },
+ bids: [
+ {
+ bidder: 'saambaa',
+ params: {
+ pubid: '121ab139faf7ac67428a23f1d0a9a71b',
+ placement: 1234,
+ size: "320x480"
+ }
+ }
+ ]
+ };
```
\ No newline at end of file
diff --git a/modules/seedtagBidAdapter.js b/modules/seedtagBidAdapter.js
index cb646fe10c3..bae27d41028 100644
--- a/modules/seedtagBidAdapter.js
+++ b/modules/seedtagBidAdapter.js
@@ -13,6 +13,11 @@ const ALLOWED_PLACEMENTS = {
banner: true,
video: true
}
+
+// Global Vendor List Id
+// https://iabeurope.eu/vendor-list-tcf-v2-0/
+const GVLID = 157;
+
const mediaTypesMap = {
[BANNER]: 'display',
[VIDEO]: 'video'
@@ -158,6 +163,7 @@ export function getTimeoutUrl (data) {
export const spec = {
code: BIDDER_CODE,
+ gvlid: GVLID,
aliases: [SEEDTAG_ALIAS],
supportedMediaTypes: [BANNER, VIDEO],
/**
diff --git a/modules/smaatoBidAdapter.js b/modules/smaatoBidAdapter.js
index dd389b42098..63fdeb2fcef 100644
--- a/modules/smaatoBidAdapter.js
+++ b/modules/smaatoBidAdapter.js
@@ -5,7 +5,7 @@ import {ADPOD, BANNER, VIDEO} from '../src/mediaTypes.js';
const BIDDER_CODE = 'smaato';
const SMAATO_ENDPOINT = 'https://prebid.ad.smaato.net/oapi/prebid';
-const SMAATO_CLIENT = 'prebid_js_$prebid.version$_1.4'
+const SMAATO_CLIENT = 'prebid_js_$prebid.version$_1.5'
const CURRENCY = 'USD';
const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => {
@@ -37,6 +37,11 @@ const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => {
user: {
ext: {}
},
+ source: {
+ ext: {
+ schain: bidRequest.schain
+ }
+ },
ext: {
client: SMAATO_CLIENT
}
diff --git a/modules/trustxBidAdapter.js b/modules/trustxBidAdapter.js
index 9907d1b2ff4..b2f0936e3c7 100644
--- a/modules/trustxBidAdapter.js
+++ b/modules/trustxBidAdapter.js
@@ -76,7 +76,7 @@ export const spec = {
if (!userIdAsEids) {
userIdAsEids = bid.userIdAsEids;
}
- const {params: {uid, keywords}, mediaTypes, bidId, adUnitCode, rtd} = bid;
+ const {params: {uid, keywords}, mediaTypes, bidId, adUnitCode, rtd, ortb2Imp} = bid;
bidsMap[bidId] = bid;
const bidFloor = _getFloor(mediaTypes || {}, bid);
if (rtd) {
@@ -102,6 +102,15 @@ export const spec = {
}
};
+ if (ortb2Imp && ortb2Imp.ext && ortb2Imp.ext.data) {
+ impObj.ext.data = ortb2Imp.ext.data;
+ if (impObj.ext.data.adserver && impObj.ext.data.adserver.adslot) {
+ impObj.ext.gpid = impObj.ext.data.adserver.adslot.toString();
+ } else {
+ impObj.ext.gpid = ortb2Imp.ext.data.pbadslot && ortb2Imp.ext.data.pbadslot.toString();
+ }
+ }
+
if (!isEmpty(keywords)) {
if (!pageKeywords) {
pageKeywords = keywords;
diff --git a/modules/visxBidAdapter.js b/modules/visxBidAdapter.js
index 1d80ea79e99..3442cbc8dd8 100644
--- a/modules/visxBidAdapter.js
+++ b/modules/visxBidAdapter.js
@@ -203,7 +203,7 @@ export const spec = {
},
onTimeout: function(timeoutData) {
// Call '/track/bid_timeout' with timeout data
- triggerPixel(buildUrl(TRACK_TIMEOUT_PATH) + '?data=' + JSON.stringify(timeoutData));
+ triggerPixel(buildUrl(TRACK_TIMEOUT_PATH) + '//' + JSON.stringify(timeoutData));
}
};
diff --git a/package.json b/package.json
index 0c6d2cb34a7..072a0d714b9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "prebid.js",
- "version": "6.1.0-pre",
+ "version": "6.2.0-pre",
"description": "Header Bidding Management Library",
"main": "src/prebid.js",
"scripts": {
@@ -11,6 +11,11 @@
"type": "git",
"url": "https://github.com/prebid/Prebid.js.git"
},
+ "browserslist": [
+ "> 0.25%",
+ "not IE 11",
+ "not op_mini all"
+ ],
"keywords": [
"advertising",
"auction",
diff --git a/test/spec/modules/adheseBidAdapter_spec.js b/test/spec/modules/adheseBidAdapter_spec.js
index 78ca25d6be2..3fe0a62b2a0 100644
--- a/test/spec/modules/adheseBidAdapter_spec.js
+++ b/test/spec/modules/adheseBidAdapter_spec.js
@@ -1,5 +1,6 @@
import {expect} from 'chai';
import {spec} from 'modules/adheseBidAdapter.js';
+import {config} from 'src/config.js';
const BID_ID = 456;
const TTL = 360;
@@ -131,12 +132,21 @@ describe('AdheseAdapter', function () {
expect(JSON.parse(req.data)).to.not.have.key('eids');
});
- it('should request vast content as url', function () {
+ it('should request vast content as url by default', function () {
let req = spec.buildRequests([ minimalBid() ], bidderRequest);
expect(JSON.parse(req.data).vastContentAsUrl).to.equal(true);
});
+ it('should request vast content as markup when configured', function () {
+ sinon.stub(config, 'getConfig').withArgs('adhese').returns({ vastContentAsUrl: false });
+
+ let req = spec.buildRequests([ minimalBid() ], bidderRequest);
+
+ expect(JSON.parse(req.data).vastContentAsUrl).to.equal(false);
+ config.getConfig.restore();
+ });
+
it('should include bids', function () {
let bid = minimalBid();
let req = spec.buildRequests([ bid ], bidderRequest);
@@ -155,6 +165,22 @@ describe('AdheseAdapter', function () {
expect(req.url).to.equal('https://ads-demo.adhese.com/json');
});
+
+ it('should include params specified in the config', function () {
+ sinon.stub(config, 'getConfig').withArgs('adhese').returns({ globalTargets: { 'tl': [ 'all' ] } });
+ let req = spec.buildRequests([ minimalBid() ], bidderRequest);
+
+ expect(JSON.parse(req.data).parameters).to.deep.include({ 'tl': [ 'all' ] });
+ config.getConfig.restore();
+ });
+
+ it('should give priority to bid params over config params', function () {
+ sinon.stub(config, 'getConfig').withArgs('adhese').returns({ globalTargets: { 'xt': ['CONFIG_CONSENT_STRING'] } });
+ let req = spec.buildRequests([ minimalBid() ], bidderRequest);
+
+ expect(JSON.parse(req.data).parameters).to.deep.include({ 'xt': [ 'CONSENT_STRING' ] });
+ config.getConfig.restore();
+ });
});
describe('interpretResponse', () => {
diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js
index 0d553aba705..fbcce5a1322 100644
--- a/test/spec/modules/appnexusBidAdapter_spec.js
+++ b/test/spec/modules/appnexusBidAdapter_spec.js
@@ -1335,6 +1335,20 @@ describe('AppNexusAdapter', function () {
expect(Object.keys(result[0].meta)).to.include.members(['advertiserId']);
});
+ it('should add brand id', function() {
+ let responseBrandId = deepClone(response);
+ responseBrandId.tags[0].ads[0].brand_id = 123;
+
+ let bidderRequest = {
+ bids: [{
+ bidId: '3db3773286ee59',
+ adUnitCode: 'code'
+ }]
+ }
+ let result = spec.interpretResponse({ body: responseBrandId }, {bidderRequest});
+ expect(Object.keys(result[0].meta)).to.include.members(['brandId']);
+ });
+
it('should add advertiserDomains', function() {
let responseAdvertiserId = deepClone(response);
responseAdvertiserId.tags[0].ads[0].adomain = ['123'];
diff --git a/test/spec/modules/datablocksBidAdapter_spec.js b/test/spec/modules/datablocksBidAdapter_spec.js
index 0ec12905430..ff7b0aad48c 100644
--- a/test/spec/modules/datablocksBidAdapter_spec.js
+++ b/test/spec/modules/datablocksBidAdapter_spec.js
@@ -96,8 +96,8 @@ const bidderRequest = {
refererInfo: {
numIframes: 0,
reachedTop: true,
- referer: 'https://v5demo.datablocks.net/test',
- stack: ['https://v5demo.datablocks.net/test']
+ referer: 'https://7560.v5demo.datablocks.net/test',
+ stack: ['https://7560.v5demo.datablocks.net/test']
},
start: Date.now(),
timeout: 10000
@@ -452,7 +452,7 @@ describe('DatablocksAdapter', function() {
it('Returns valid URL', function() {
expect(request.url).to.exist;
- expect(request.url).to.equal('https://7560.v5demo.datablocks.net/openrtb/?sid=7560');
+ expect(request.url).to.equal('https://v5demo.datablocks.net/openrtb/?sid=7560');
});
it('Creates an array of request objects', function() {
diff --git a/test/spec/modules/engageyaBidAdapter_spec.js b/test/spec/modules/engageyaBidAdapter_spec.js
index ae22948994b..7f07e4b9e4a 100644
--- a/test/spec/modules/engageyaBidAdapter_spec.js
+++ b/test/spec/modules/engageyaBidAdapter_spec.js
@@ -4,18 +4,7 @@ import * as utils from 'src/utils.js';
const ENDPOINT_URL = 'https://recs.engageya.com/rec-api/getrecs.json';
-export const _getUrlVars = function (url) {
- var hash;
- var myJson = {};
- var hashes = url.slice(url.indexOf('?') + 1).split('&');
- for (var i = 0; i < hashes.length; i++) {
- hash = hashes[i].split('=');
- myJson[hash[0]] = hash[1];
- }
- return myJson;
-}
-
-describe('engageya adapter', function () {
+describe('Engageya adapter', function () {
let bidRequests;
let nativeBidRequests;
@@ -55,40 +44,57 @@ describe('engageya adapter', function () {
}
]
})
+
describe('isBidRequestValid', function () {
- it('valid bid case', function () {
+ it('Valid bid case', function () {
let validBid = {
bidder: 'engageya',
params: {
widgetId: 85610,
websiteId: 91140,
pageUrl: '[PAGE_URL]'
- }
+ },
+ sizes: [[300, 250]]
}
let isValid = spec.isBidRequestValid(validBid);
- expect(isValid).to.equal(true);
+ expect(isValid).to.be.true;
});
- it('invalid bid case: widgetId and websiteId is not passed', function () {
+ it('Invalid bid case: widgetId and websiteId is not passed', function () {
let validBid = {
bidder: 'engageya',
params: {}
}
let isValid = spec.isBidRequestValid(validBid);
- expect(isValid).to.equal(false);
+ expect(isValid).to.be.false;
})
- it('invalid bid case: widget id must be number', function () {
+ it('Invalid bid case: widget id must be number', function () {
let invalidBid = {
bidder: 'engageya',
params: {
widgetId: '157746a',
websiteId: 91140,
pageUrl: '[PAGE_URL]'
- }
+ },
+ sizes: [[300, 250]]
+ }
+ let isValid = spec.isBidRequestValid(invalidBid);
+ expect(isValid).to.be.false;
+ })
+
+ it('Invalid bid case: unsupported sizes', function () {
+ let invalidBid = {
+ bidder: 'engageya',
+ params: {
+ widgetId: '157746a',
+ websiteId: 91140,
+ pageUrl: '[PAGE_URL]'
+ },
+ sizes: [[250, 250]]
}
let isValid = spec.isBidRequestValid(invalidBid);
- expect(isValid).to.equal(false);
+ expect(isValid).to.be.false;
})
})
@@ -113,36 +119,30 @@ describe('engageya adapter', function () {
it('Request params check', function () {
let request = spec.buildRequests(bidRequests)[0];
- const data = _getUrlVars(request.url)
- expect(parseInt(data.wid)).to.exist.and.to.equal(bidRequests[0].params.widgetId);
- expect(parseInt(data.webid)).to.exist.and.to.equal(bidRequests[0].params.websiteId);
- })
- })
-
- describe('interpretResponse', function () {
- it('should return empty array if no response', function () {
- const result = spec.interpretResponse({}, [])
- expect(result).to.be.an('array').that.is.empty
+ const urlParams = new URL(request.url).searchParams;
+ expect(parseInt(urlParams.get('wid'))).to.exist.and.to.equal(bidRequests[0].params.widgetId);
+ expect(parseInt(urlParams.get('webid'))).to.exist.and.to.equal(bidRequests[0].params.websiteId);
});
- it('should return empty array if no valid bids', function () {
- let response = {
- recs: [],
- imageWidth: 300,
- imageHeight: 250,
- ireqId: '1d236f7890b',
- pbtypeId: 2
- };
- let request = spec.buildRequests(bidRequests)[0];
- const result = spec.interpretResponse({ body: response }, request)
- expect(result).to.be.an('array').that.is.empty
+ it('Request pageUrl - use param', function () {
+ const pageUrl = 'https://url.test';
+ bidRequests[0].params.pageUrl = pageUrl;
+ const request = spec.buildRequests(bidRequests)[0];
+ const urlParams = new URL(request.url).searchParams;
+ expect(urlParams.get('url')).to.exist.and.to.equal(pageUrl);
});
+ })
- it('should interpret native response', function () {
- let serverResponse = {
+ describe('interpretResponse', function () {
+ let nativeResponse;
+ let bannerResponse;
+
+ beforeEach(() => {
+ const recsResponse = {
recs: [
{
- ecpm: 0.0920,
+ ecpm: 9.20,
+ pecpm: 0.0520,
postId: '',
thumbnail_path: 'https://engageya.live/wp-content/uploads/2019/05/images.png',
domain: 'domain.test',
@@ -159,8 +159,80 @@ describe('engageya adapter', function () {
imageWidth: 300,
imageHeight: 250,
ireqId: '1d236f7890b',
- pbtypeId: 1
+ viewPxl: '//view.pixel',
};
+
+ nativeResponse = {
+ ...recsResponse,
+ pbtypeId: 1,
+ }
+
+ bannerResponse = {
+ ...recsResponse,
+ pbtypeId: 2,
+ widget: {
+ additionalData: '{"css":".eng_tag_ttl{display:block!important}"}'
+ },
+ }
+ })
+
+ it('should return empty array if no response', function () {
+ const result = spec.interpretResponse({}, [])
+ expect(result).to.be.an('array').that.is.empty
+ });
+
+ it('should return empty array if no valid bids', function () {
+ let response = {
+ recs: [],
+ imageWidth: 300,
+ imageHeight: 250,
+ ireqId: '1d236f7890b',
+ pbtypeId: 2,
+ viewPxl: '//view.pixel',
+ };
+ let request = spec.buildRequests(bidRequests)[0];
+ const result = spec.interpretResponse({ body: response }, request)
+ expect(result).to.be.an('array').that.is.empty
+ });
+
+ it('should interpret native response', function () {
+ let expectedResult = [
+ {
+ requestId: '1d236f7890b',
+ cpm: 0.0520,
+ width: 300,
+ height: 250,
+ netRevenue: true,
+ currency: 'USD',
+ creativeId: '',
+ ttl: 360,
+ meta: {
+ advertiserDomains: ['domain.test']
+ },
+ native: {
+ title: 'Test title',
+ body: '',
+ image: {
+ url: 'https://engageya.live/wp-content/uploads/2019/05/images.png',
+ width: 300,
+ height: 250
+ },
+ privacyLink: '',
+ clickUrl: '//click.test',
+ displayUrl: '//url.test',
+ cta: '',
+ sponsoredBy: 'Test displayName',
+ impressionTrackers: ['//impression.test', '//view.test', '//view.pixel'],
+ },
+ }
+ ];
+ let request = spec.buildRequests(bidRequests)[0];
+ let result = spec.interpretResponse({ body: nativeResponse }, request);
+ expect(result).to.deep.equal(expectedResult);
+ });
+
+ it('should interpret native response - without pecpm', function () {
+ delete nativeResponse.recs[0].pecpm;
let expectedResult = [
{
requestId: '1d236f7890b',
@@ -187,81 +259,76 @@ describe('engageya adapter', function () {
displayUrl: '//url.test',
cta: '',
sponsoredBy: 'Test displayName',
- impressionTrackers: ['//impression.test', '//view.test'],
+ impressionTrackers: ['//impression.test', '//view.test', '//view.pixel'],
},
}
];
let request = spec.buildRequests(bidRequests)[0];
- let result = spec.interpretResponse({ body: serverResponse }, request);
+ let result = spec.interpretResponse({ body: nativeResponse }, request);
expect(result).to.deep.equal(expectedResult);
});
- it('should interpret display response', function () {
- let serverResponse = {
- recs: [
- {
- ecpm: 0.0920,
- postId: '',
- thumbnail_path: 'https://engageya.live/wp-content/uploads/2019/05/images.png',
- domain: 'domain.test',
+ it('should interpret native response - without trackers', function () {
+ delete nativeResponse.recs[0].trackers;
+ let expectedResult = [
+ {
+ requestId: '1d236f7890b',
+ cpm: 0.0520,
+ width: 300,
+ height: 250,
+ netRevenue: true,
+ currency: 'USD',
+ creativeId: '',
+ ttl: 360,
+ meta: {
+ advertiserDomains: ['domain.test']
+ },
+ native: {
title: 'Test title',
+ body: '',
+ image: {
+ url: 'https://engageya.live/wp-content/uploads/2019/05/images.png',
+ width: 300,
+ height: 250
+ },
+ privacyLink: '',
clickUrl: '//click.test',
- url: '//url.test',
- displayName: 'Test displayName',
- trackers: {
- impressionPixels: ['//impression.test'],
- viewPixels: ['//view.test'],
- }
- }
- ],
- imageWidth: 300,
- imageHeight: 250,
- ireqId: '1d236f7890b',
- pbtypeId: 2,
- widget: {
- additionalData: '{"css":".eng_tag_ttl{display:block!important}"}'
+ displayUrl: '//url.test',
+ cta: '',
+ sponsoredBy: 'Test displayName',
+ impressionTrackers: ['//view.pixel'],
+ },
}
- };
+ ];
+ let request = spec.buildRequests(bidRequests)[0];
+ let result = spec.interpretResponse({ body: nativeResponse }, request);
+ expect(result).to.deep.equal(expectedResult);
+ });
+
+ it('should interpret display response', function () {
let expectedResult = [
{
requestId: '1d236f7890b',
- cpm: 0.0920,
+ cpm: 0.0520,
width: 300,
height: 250,
- netRevenue: false,
+ netRevenue: true,
currency: 'USD',
creativeId: '',
ttl: 360,
meta: {
advertiserDomains: ['domain.test']
},
- ad: ``,
+ ad: ``,
}
];
let request = spec.buildRequests(bidRequests)[0];
- let result = spec.interpretResponse({ body: serverResponse }, request);
+ let result = spec.interpretResponse({ body: bannerResponse }, request);
expect(result).to.deep.equal(expectedResult);
});
- it('should interpret display response without title', function () {
- let serverResponse = {
- recs: [
- {
- ecpm: 0.0920,
- postId: '',
- thumbnail_path: 'https://engageya.live/wp-content/uploads/2019/05/images.png',
- domain: 'domain.test',
- title: ' ',
- clickUrl: '//click.test',
- url: '//url.test',
- displayName: 'Test displayName',
- }
- ],
- imageWidth: 300,
- imageHeight: 250,
- ireqId: '1d236f7890b',
- pbtypeId: 2,
- };
+ it('should interpret display response - without pecpm', function () {
+ delete bannerResponse.recs[0].pecpm;
let expectedResult = [
{
requestId: '1d236f7890b',
@@ -275,11 +342,80 @@ describe('engageya adapter', function () {
meta: {
advertiserDomains: ['domain.test']
},
- ad: ``,
+ ad: ``,
+ }
+ ];
+ let request = spec.buildRequests(bidRequests)[0];
+ let result = spec.interpretResponse({ body: bannerResponse }, request);
+ expect(result).to.deep.equal(expectedResult);
+ });
+
+ it('should interpret display response - without title', function () {
+ bannerResponse.recs[0].title = ' ';
+ let expectedResult = [
+ {
+ requestId: '1d236f7890b',
+ cpm: 0.0520,
+ width: 300,
+ height: 250,
+ netRevenue: true,
+ currency: 'USD',
+ creativeId: '',
+ ttl: 360,
+ meta: {
+ advertiserDomains: ['domain.test']
+ },
+ ad: ``,
+ }
+ ];
+ let request = spec.buildRequests(bidRequests)[0];
+ let result = spec.interpretResponse({ body: bannerResponse }, request);
+ expect(result).to.deep.equal(expectedResult);
+ });
+
+ it('should interpret display response - without widget additional data', function () {
+ bannerResponse.widget.additionalData = null;
+ let expectedResult = [
+ {
+ requestId: '1d236f7890b',
+ cpm: 0.0520,
+ width: 300,
+ height: 250,
+ netRevenue: true,
+ currency: 'USD',
+ creativeId: '',
+ ttl: 360,
+ meta: {
+ advertiserDomains: ['domain.test']
+ },
+ ad: ``,
+ }
+ ];
+ let request = spec.buildRequests(bidRequests)[0];
+ let result = spec.interpretResponse({ body: bannerResponse }, request);
+ expect(result).to.deep.equal(expectedResult);
+ });
+
+ it('should interpret display response - without trackers', function () {
+ bannerResponse.recs[0].trackers = null;
+ let expectedResult = [
+ {
+ requestId: '1d236f7890b',
+ cpm: 0.0520,
+ width: 300,
+ height: 250,
+ netRevenue: true,
+ currency: 'USD',
+ creativeId: '',
+ ttl: 360,
+ meta: {
+ advertiserDomains: ['domain.test']
+ },
+ ad: ``,
}
];
let request = spec.buildRequests(bidRequests)[0];
- let result = spec.interpretResponse({ body: serverResponse }, request);
+ let result = spec.interpretResponse({ body: bannerResponse }, request);
expect(result).to.deep.equal(expectedResult);
});
})
diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js
index c6104a23a1c..117208f9d00 100644
--- a/test/spec/modules/eplanningBidAdapter_spec.js
+++ b/test/spec/modules/eplanningBidAdapter_spec.js
@@ -328,26 +328,25 @@ describe('E-Planning Adapter', function () {
describe('buildRequests', function () {
let bidRequests = [validBid];
let sandbox;
+ let getWindowSelfStub;
+ let innerWidth;
beforeEach(() => {
sandbox = sinon.sandbox.create();
+ getWindowSelfStub = sandbox.stub(utils, 'getWindowSelf');
+ getWindowSelfStub.returns(createWindow(800));
});
afterEach(() => {
sandbox.restore();
});
- const createWindow = () => {
+ const createWindow = (innerWidth) => {
const win = {};
win.self = win;
- win.innerWidth = 1025;
+ win.innerWidth = innerWidth;
return win;
};
- function setupSingleWindow(sandBox) {
- const win = createWindow();
- sandBox.stub(utils, 'getWindowSelf').returns(win);
- }
-
it('should create the url correctly', function () {
const url = spec.buildRequests(bidRequests, bidderRequest).url;
expect(url).to.equal('https://pbjs.e-planning.net/pbjs/1/' + CI + '/1/localhost/ROS');
@@ -516,7 +515,8 @@ describe('E-Planning Adapter', function () {
it('should return the e parameter with a value according to the sizes in order corresponding to the desktop priority list of the ad units', function () {
let bidRequestsPrioritySizes = [validBidExistingSizesInPriorityListForDesktop];
- setupSingleWindow(sandbox);
+ // overwrite default innerWdith for tests with a larger one we consider "Desktop" or NOT Mobile
+ getWindowSelfStub.returns(createWindow(1025));
const e = spec.buildRequests(bidRequestsPrioritySizes, bidderRequest).data.e;
expect(e).to.equal('300x250_0:300x250,300x600,970x250');
});
diff --git a/test/spec/modules/glimpseBidAdapter_spec.js b/test/spec/modules/glimpseBidAdapter_spec.js
index 98e1a1bb451..c139a7ab8d3 100644
--- a/test/spec/modules/glimpseBidAdapter_spec.js
+++ b/test/spec/modules/glimpseBidAdapter_spec.js
@@ -1,3 +1,4 @@
+import { BANNER } from '../../../src/mediaTypes'
import { expect } from 'chai'
import { newBidder } from 'src/adapters/bidderFactory.js'
import { spec } from 'modules/glimpseBidAdapter.js'
@@ -79,6 +80,20 @@ function getDeepCopy(object) {
describe('GlimpseProtocolAdapter', () => {
const glimpseAdapter = newBidder(spec)
+ describe('spec', () => {
+ it('Has defined the glimpse gvlid', () => {
+ expect(spec.gvlid).to.equal(1012)
+ })
+
+ it('Has defined glimpse as the bidder', () => {
+ expect(spec.code).to.equal('glimpse')
+ })
+
+ it('Has defined valid mediaTypes', () => {
+ expect(spec.supportedMediaTypes).to.deep.equal([BANNER])
+ })
+ })
+
describe('Inherited functions', () => {
it('Functions exist and are valid types', () => {
expect(glimpseAdapter.callBids).to.exist.and.to.be.a('function')
@@ -163,6 +178,24 @@ describe('GlimpseProtocolAdapter', () => {
const bidRequests = [getBidRequest()]
const bidderRequest = getBidderRequest()
+ it('Adds a demo flag', () => {
+ const request = spec.buildRequests(bidRequests, bidderRequest)
+ const payload = JSON.parse(request.data)
+ expect(payload.data.demo).to.be.false
+ })
+
+ it('Adds an account id', () => {
+ const request = spec.buildRequests(bidRequests, bidderRequest)
+ const payload = JSON.parse(request.data)
+ expect(payload.data.account).to.equal(-1)
+ })
+
+ it('Adds a demand provider', () => {
+ const request = spec.buildRequests(bidRequests, bidderRequest)
+ const payload = JSON.parse(request.data)
+ expect(payload.data.demand).to.equal('glimpse')
+ })
+
it('Adds GDPR consent', () => {
const request = spec.buildRequests(bidRequests, bidderRequest)
const payload = JSON.parse(request.data)
diff --git a/test/spec/modules/gptPreAuction_spec.js b/test/spec/modules/gptPreAuction_spec.js
index 3e8dbfe8d92..9e81aea80d1 100644
--- a/test/spec/modules/gptPreAuction_spec.js
+++ b/test/spec/modules/gptPreAuction_spec.js
@@ -197,15 +197,69 @@ describe('GPT pre-auction module', () => {
code: 'slotCode3',
}];
+ // first two adUnits directly pass in pbadslot => gpid is same
const expectedAdUnits = [{
code: 'adUnit1',
- ortb2Imp: { ext: { data: { pbadslot: '12345' } } }
- }, {
+ ortb2Imp: {
+ ext: {
+ data: {
+ pbadslot: '12345'
+ },
+ gpid: '12345'
+ }
+ }
+ },
+ // second adunit
+ {
code: 'slotCode1',
- ortb2Imp: { ext: { data: { pbadslot: '67890', adserver: { name: 'gam', adslot: 'slotCode1' } } } }
+ ortb2Imp: {
+ ext: {
+ data: {
+ pbadslot: '67890',
+ adserver: {
+ name: 'gam',
+ adslot: 'slotCode1'
+ }
+ },
+ gpid: '67890'
+ }
+ }
}, {
code: 'slotCode3',
- ortb2Imp: { ext: { data: { pbadslot: 'slotCode3', adserver: { name: 'gam', adslot: 'slotCode3' } } } }
+ ortb2Imp: {
+ ext: {
+ data: {
+ pbadslot: 'slotCode3',
+ adserver: {
+ name: 'gam',
+ adslot: 'slotCode3'
+ }
+ },
+ gpid: 'slotCode3'
+ }
+ }
+ }];
+
+ window.googletag.pubads().setSlots(testSlots);
+ runMakeBidRequests(testAdUnits);
+ expect(returnedAdUnits).to.deep.equal(expectedAdUnits);
+ });
+
+ it('should not apply gpid if pbadslot was set by adUnitCode', () => {
+ const testAdUnits = [{
+ code: 'noMatchCode',
+ }];
+
+ // first two adUnits directly pass in pbadslot => gpid is same
+ const expectedAdUnits = [{
+ code: 'noMatchCode',
+ ortb2Imp: {
+ ext: {
+ data: {
+ pbadslot: 'noMatchCode'
+ },
+ }
+ }
}];
window.googletag.pubads().setSlots(testSlots);
diff --git a/test/spec/modules/imRtdProvider_spec.js b/test/spec/modules/imRtdProvider_spec.js
index 58410dc0e38..e3365e8eaf2 100644
--- a/test/spec/modules/imRtdProvider_spec.js
+++ b/test/spec/modules/imRtdProvider_spec.js
@@ -1,6 +1,7 @@
import {
imRtdSubmodule,
storage,
+ getBidderFunction,
getCustomBidderFunction,
setRealTimeData,
getRealTimeData,
@@ -47,6 +48,30 @@ describe('imRtdProvider', function () {
})
})
+ describe('getBidderFunction', function () {
+ const assumedBidder = [
+ 'ix',
+ 'pubmatic'
+ ];
+ assumedBidder.forEach(bidderName => {
+ it(`should return bidderFunction with assumed bidder: ${bidderName}`, function () {
+ expect(getBidderFunction(bidderName)).to.exist.and.to.be.a('function');
+ });
+
+ it(`should return bid with correct key data: ${bidderName}`, function () {
+ const bid = {bidder: bidderName};
+ expect(getBidderFunction(bidderName)(bid, {'im_segments': ['12345', '67890']})).to.equal(bid);
+ });
+ it(`should return bid without data: ${bidderName}`, function () {
+ const bid = {bidder: bidderName};
+ expect(getBidderFunction(bidderName)(bid, '')).to.equal(bid);
+ });
+ });
+ it(`should return null with unexpected bidder`, function () {
+ expect(getBidderFunction('test')).to.equal(null);
+ });
+ })
+
describe('getCustomBidderFunction', function () {
it('should return config function', function () {
const config = {
diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js
index 8b92e0ee81b..a61c4fa5267 100644
--- a/test/spec/modules/invibesBidAdapter_spec.js
+++ b/test/spec/modules/invibesBidAdapter_spec.js
@@ -15,7 +15,7 @@ describe('invibesBidAdapter:', function () {
params: {
placementId: PLACEMENT_ID
},
- adUnitCode: 'test-div',
+ adUnitCode: 'test-div1',
auctionId: 'a1',
sizes: [
[300, 250],
@@ -30,7 +30,7 @@ describe('invibesBidAdapter:', function () {
params: {
placementId: 'abcde'
},
- adUnitCode: 'test-div',
+ adUnitCode: 'test-div2',
auctionId: 'a2',
sizes: [
[300, 250],
@@ -48,7 +48,7 @@ describe('invibesBidAdapter:', function () {
params: {
placementId: PLACEMENT_ID
},
- adUnitCode: 'test-div',
+ adUnitCode: 'test-div1',
auctionId: 'a1',
sizes: [
[300, 250],
@@ -67,7 +67,7 @@ describe('invibesBidAdapter:', function () {
params: {
placementId: 'abcde'
},
- adUnitCode: 'test-div',
+ adUnitCode: 'test-div2',
auctionId: 'a2',
sizes: [
[300, 250],
@@ -223,6 +223,12 @@ describe('invibesBidAdapter:', function () {
expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[1].params.placementId);
});
+ it('sends all adUnitCodes', function () {
+ const request = spec.buildRequests(bidRequests);
+ expect(JSON.parse(request.data.bidParamsJson).adUnitCodes).to.contain(bidRequests[0].adUnitCode);
+ expect(JSON.parse(request.data.bidParamsJson).adUnitCodes).to.contain(bidRequests[1].adUnitCode);
+ });
+
it('sends all Placement Ids and userId', function () {
const request = spec.buildRequests(bidRequestsWithUserId);
expect(JSON.parse(request.data.bidParamsJson).userId).to.exist;
@@ -823,6 +829,20 @@ describe('invibesBidAdapter:', function () {
}
};
+ let responseWithAdUnit = {
+ Ads: [{
+ BidPrice: 0.5,
+ VideoExposedId: 123
+ }],
+ BidModel: {
+ BidVersion: 1,
+ PlacementId: '12345_test-div1',
+ AuctionStartTime: Date.now(),
+ CreativeHtml: ''
+ },
+ UseAdUnitCode: true
+ };
+
var buildResponse = function(placementId, cid, blcids, creativeId) {
return {
MultipositionEnabled: true,
@@ -911,6 +931,11 @@ describe('invibesBidAdapter:', function () {
let secondResult = spec.interpretResponse({body: response}, {bidRequests});
expect(secondResult).to.be.empty;
});
+
+ it('bids using the adUnitCode', function () {
+ let result = spec.interpretResponse({body: responseWithAdUnit}, {bidRequests});
+ expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
+ });
});
context('when the response has meta', function () {
diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js
index 59eb9e76c9a..32ce40f25cb 100644
--- a/test/spec/modules/ixBidAdapter_spec.js
+++ b/test/spec/modules/ixBidAdapter_spec.js
@@ -2,7 +2,7 @@ import * as utils from 'src/utils.js';
import { config } from 'src/config.js';
import { expect } from 'chai';
import { newBidder } from 'src/adapters/bidderFactory.js';
-import { spec } from 'modules/ixBidAdapter.js';
+import { spec, storage, ERROR_CODES } from '../../../modules/ixBidAdapter.js';
import { createEidsArray } from 'modules/userId/eids.js';
describe('IndexexchangeAdapter', function () {
@@ -353,6 +353,37 @@ describe('IndexexchangeAdapter', function () {
]
};
+ const DEFAULT_VIDEO_BID_RESPONSE_WITH_MTYPE_SET = {
+ cur: 'USD',
+ id: '1aa2bb3cc4de',
+ seatbid: [
+ {
+ bid: [
+ {
+ crid: '12346',
+ adomain: ['www.abcd.com'],
+ adid: '14851456',
+ impid: '1a2b3c4e',
+ cid: '3051267',
+ price: 110,
+ id: '2',
+ mtype: 2,
+ adm: ' Test In-Stream Video Test In-Stream Video {
+ let TODAY = new Date().toISOString().slice(0, 10);
+ const key = 'ixdiag';
+
+ let sandbox;
+ let setDataInLocalStorageStub;
+ let getDataFromLocalStorageStub;
+ let removeDataFromLocalStorageStub;
+ let localStorageValues = {};
+
+ beforeEach(() => {
+ sandbox = sinon.sandbox.create();
+ setDataInLocalStorageStub = sandbox.stub(storage, 'setDataInLocalStorage').callsFake((key, value) => localStorageValues[key] = value)
+ getDataFromLocalStorageStub = sandbox.stub(storage, 'getDataFromLocalStorage').callsFake((key) => localStorageValues[key])
+ removeDataFromLocalStorageStub = sandbox.stub(storage, 'removeDataFromLocalStorage').callsFake((key) => delete localStorageValues[key])
+ sandbox.stub(storage, 'localStorageIsEnabled').returns(true);
+ });
+
+ afterEach(() => {
+ setDataInLocalStorageStub.restore();
+ getDataFromLocalStorageStub.restore();
+ removeDataFromLocalStorageStub.restore();
+ localStorageValues = {};
+ sandbox.restore();
+
+ config.setConfig({
+ fpd: {},
+ ix: {},
+ })
+ });
+
+ it('should not log error in LocalStorage when there is no logError called.', () => {
+ const bid = DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0];
+ expect(spec.isBidRequestValid(bid)).to.be.true;
+ expect(localStorageValues[key]).to.be.undefined;
+ });
+
+ it('should log ERROR_CODES.BID_SIZE_INVALID_FORMAT in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.size = ['400', 100];
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.BID_SIZE_INVALID_FORMAT]: 1 } });
+ });
+
+ it('should log ERROR_CODES.BID_SIZE_NOT_INCLUDED in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.size = [407, 100];
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.BID_SIZE_NOT_INCLUDED]: 1 } });
+ });
+
+ it('should log ERROR_CODES.PROPERTY_NOT_INCLUDED in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.video = {};
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.PROPERTY_NOT_INCLUDED]: 4 } });
+ });
+
+ it('should log ERROR_CODES.SITE_ID_INVALID_VALUE in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.siteId = false;
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.SITE_ID_INVALID_VALUE]: 1 } });
+ });
+
+ it('should log ERROR_CODES.BID_FLOOR_INVALID_FORMAT in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.bidFloor = true;
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.BID_FLOOR_INVALID_FORMAT]: 1 } });
+ });
+
+ it('should log ERROR_CODES.IX_FPD_EXCEEDS_MAX_SIZE in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+
+ config.setConfig({
+ ix: {
+ firstPartyData: {
+ cd: Array(1700).join('#')
+ }
+ }
+ });
+
+ expect(spec.isBidRequestValid(bid)).to.be.true;
+ spec.buildRequests([bid]);
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.IX_FPD_EXCEEDS_MAX_SIZE]: 2 } });
+ });
+
+ it('should log ERROR_CODES.EXCEEDS_MAX_SIZE in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.bidderRequestId = Array(8000).join('#');
+
+ expect(spec.isBidRequestValid(bid)).to.be.true;
+ spec.buildRequests([bid]);
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.EXCEEDS_MAX_SIZE]: 2 } });
+ });
+
+ it('should log ERROR_CODES.PB_FPD_EXCEEDS_MAX_SIZE in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+
+ config.setConfig({
+ fpd: {
+ site: {
+ data: {
+ pageType: Array(5700).join('#')
+ }
+ }
+ }
+ });
+
+ expect(spec.isBidRequestValid(bid)).to.be.true;
+ spec.buildRequests([bid]);
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.PB_FPD_EXCEEDS_MAX_SIZE]: 2 } });
+ });
+
+ it('should log ERROR_CODES.VIDEO_DURATION_INVALID in LocalStorage when there is logError called.', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.video.minduration = 1;
+ bid.params.video.maxduration = 0;
+
+ expect(spec.isBidRequestValid(bid)).to.be.true;
+ spec.buildRequests([bid]);
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.VIDEO_DURATION_INVALID]: 2 } });
+ });
+
+ it('should increment errors for errorCode', () => {
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.video = {};
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.PROPERTY_NOT_INCLUDED]: 4 } });
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.PROPERTY_NOT_INCLUDED]: 8 } });
+ });
+
+ it('should add new errorCode to ixdiag.', () => {
+ let bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.size = ['400', 100];
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { [ERROR_CODES.BID_SIZE_INVALID_FORMAT]: 1 } });
+
+ bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.siteId = false;
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({
+ [TODAY]: {
+ [ERROR_CODES.BID_SIZE_INVALID_FORMAT]: 1,
+ [ERROR_CODES.SITE_ID_INVALID_VALUE]: 1
+ }
+ });
+ });
+
+ it('should clear errors with successful response', () => {
+ const ixdiag = { [TODAY]: { '1': 1, '3': 8, '4': 1 } };
+ setDataInLocalStorageStub(key, JSON.stringify(ixdiag));
+
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal(ixdiag);
+
+ const request = DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0];
+ expect(spec.isBidRequestValid(request)).to.be.true;
+
+ const data = {
+ ...utils.deepClone(DEFAULT_BIDDER_REQUEST_DATA[0]),
+ r: JSON.stringify({
+ id: '345',
+ imp: [
+ {
+ id: '1a2b3c4e',
+ }
+ ],
+ ext: {
+ ixdiag: {
+ err: {
+ '4': 8
+ }
+ }
+ }
+ }),
+ };
+
+ const validBidRequests = [
+ DEFAULT_MULTIFORMAT_BANNER_VALID_BID[0],
+ DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]
+ ];
+
+ spec.interpretResponse({ body: DEFAULT_BANNER_BID_RESPONSE }, { data, validBidRequests });
+
+ expect(localStorageValues[key]).to.be.undefined;
+ });
+
+ it('should clear errors after 7 day expiry errorCode', () => {
+ const EXPIRED_DATE = '2019-12-12';
+
+ const ixdiag = { [EXPIRED_DATE]: { '1': 1, '3': 8, '4': 1 }, [TODAY]: { '3': 8, '4': 1 } };
+ setDataInLocalStorageStub(key, JSON.stringify(ixdiag));
+
+ const bid = utils.deepClone(DEFAULT_MULTIFORMAT_VIDEO_VALID_BID[0]);
+ bid.params.size = ['400', 100];
+
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ expect(JSON.parse(localStorageValues[key])[EXPIRED_DATE]).to.be.undefined;
+ expect(JSON.parse(localStorageValues[key])).to.deep.equal({ [TODAY]: { '1': 1, '3': 8, '4': 1 } })
+ });
+ });
});
diff --git a/test/spec/modules/oguryBidAdapter_spec.js b/test/spec/modules/oguryBidAdapter_spec.js
index 883119d2707..13bffc8075c 100644
--- a/test/spec/modules/oguryBidAdapter_spec.js
+++ b/test/spec/modules/oguryBidAdapter_spec.js
@@ -119,7 +119,7 @@ describe('OguryBidAdapter', function () {
};
});
- it('should return sync array with two elements of type image', () => {
+ it('should return syncs array with two elements of type image', () => {
const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent);
expect(userSyncs).to.have.lengthOf(2);
@@ -129,7 +129,7 @@ describe('OguryBidAdapter', function () {
expect(userSyncs[1].url).to.contain('https://ms-cookie-sync.presage.io/ttd/init-sync');
});
- it('should set the same source as query param', () => {
+ it('should set the source as query param', () => {
const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent);
expect(userSyncs[0].url).to.contain('source=prebid');
expect(userSyncs[1].url).to.contain('source=prebid');
@@ -146,7 +146,7 @@ describe('OguryBidAdapter', function () {
expect(spec.getUserSyncs(syncOptions, [], gdprConsent)).to.have.lengthOf(0);
});
- it('should return sync array with two elements of type image when consentString is undefined', () => {
+ it('should return syncs array with two elements of type image when consentString is undefined', () => {
gdprConsent = {
gdprApplies: true,
consentString: undefined
@@ -160,7 +160,7 @@ describe('OguryBidAdapter', function () {
expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid')
});
- it('should return sync array with two elements of type image when consentString is null', () => {
+ it('should return syncs array with two elements of type image when consentString is null', () => {
gdprConsent = {
gdprApplies: true,
consentString: null
@@ -174,7 +174,7 @@ describe('OguryBidAdapter', function () {
expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid')
});
- it('should return sync array with two elements of type image when gdprConsent is undefined', () => {
+ it('should return syncs array with two elements of type image when gdprConsent is undefined', () => {
gdprConsent = undefined;
const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent);
@@ -185,7 +185,7 @@ describe('OguryBidAdapter', function () {
expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid')
});
- it('should return sync array with two elements of type image when gdprConsent is null', () => {
+ it('should return syncs array with two elements of type image when gdprConsent is null', () => {
gdprConsent = null;
const userSyncs = spec.getUserSyncs(syncOptions, [], gdprConsent);
@@ -196,7 +196,7 @@ describe('OguryBidAdapter', function () {
expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid')
});
- it('should return sync array with two elements of type image when gdprConsent is null and gdprApplies is false', () => {
+ it('should return syncs array with two elements of type image when gdprConsent is null and gdprApplies is false', () => {
gdprConsent = {
gdprApplies: false,
consentString: null
@@ -210,7 +210,7 @@ describe('OguryBidAdapter', function () {
expect(userSyncs[1].url).to.equal('https://ms-cookie-sync.presage.io/ttd/init-sync?iab_string=&source=prebid')
});
- it('should return sync array with two elements of type image when gdprConsent is empty string and gdprApplies is false', () => {
+ it('should return syncs array with two elements of type image when gdprConsent is empty string and gdprApplies is false', () => {
gdprConsent = {
gdprApplies: false,
consentString: ''
@@ -240,7 +240,8 @@ describe('OguryBidAdapter', function () {
w: 300,
h: 250
}]
- }
+ },
+ ext: bidRequests[0].params
}, {
id: bidRequests[1].bidId,
tagid: bidRequests[1].params.adUnitId,
@@ -250,7 +251,8 @@ describe('OguryBidAdapter', function () {
w: 600,
h: 500
}]
- }
+ },
+ ext: bidRequests[1].params
}],
regs: {
ext: {
@@ -549,7 +551,7 @@ describe('OguryBidAdapter', function () {
xhr.restore()
})
- it('should send notification on bid timeout', function() {
+ it('should send on bid timeout notification', function() {
const bid = {
ad: '
',
cpm: 3
diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js
index 783449723ae..3bc53e30eb8 100644
--- a/test/spec/modules/openxBidAdapter_spec.js
+++ b/test/spec/modules/openxBidAdapter_spec.js
@@ -1102,6 +1102,11 @@ describe('OpenxAdapter', function () {
mwOpenLinkId: '1111-mwopenlinkid',
dapId: '1111-dapId',
amxId: '1111-amxid',
+ kpuid: '1111-kpuid',
+ publinkId: '1111-publinkid',
+ naveggId: '1111-naveggid',
+ imuid: '1111-imuid',
+ adtelligentId: '1111-adtelligentid'
};
// generates the same set of tests for each id provider
diff --git a/test/spec/modules/seedtagBidAdapter_spec.js b/test/spec/modules/seedtagBidAdapter_spec.js
index 3aa378379dd..159645ff6d6 100644
--- a/test/spec/modules/seedtagBidAdapter_spec.js
+++ b/test/spec/modules/seedtagBidAdapter_spec.js
@@ -274,6 +274,9 @@ describe('Seedtag Adapter', function() {
expect(data.ga).to.equal(true)
expect(data.cd).to.equal('consentString')
})
+ it('should expose gvlid', function() {
+ expect(spec.gvlid).to.equal(157)
+ })
})
})
diff --git a/test/spec/modules/smaatoBidAdapter_spec.js b/test/spec/modules/smaatoBidAdapter_spec.js
index faa288306a5..801aef514fc 100644
--- a/test/spec/modules/smaatoBidAdapter_spec.js
+++ b/test/spec/modules/smaatoBidAdapter_spec.js
@@ -287,6 +287,13 @@ describe('smaatoBidAdapterTest', () => {
expect(req.regs.ext.us_privacy).to.equal('uspConsentString');
});
+ it('sends no schain if no schain exists', () => {
+ const reqs = spec.buildRequests([singleBannerBidRequest], defaultBidderRequest);
+
+ const req = extractPayloadOfFirstAndOnlyRequest(reqs);
+ expect(req.source.ext.schain).to.not.exist;
+ });
+
it('sends tmax', () => {
const reqs = spec.buildRequests([singleBannerBidRequest], defaultBidderRequest);
@@ -854,6 +861,29 @@ describe('smaatoBidAdapterTest', () => {
expect(req.user.ext.eids).to.have.length(2);
});
});
+
+ describe('schain in request', () => {
+ it('schain is added to source.ext.schain', () => {
+ const schain = {
+ ver: '1.0',
+ complete: 1,
+ nodes: [
+ {
+ 'asi': 'asi',
+ 'sid': 'sid',
+ 'rid': 'rid',
+ 'hp': 1
+ }
+ ]
+ };
+ const bidRequestWithSchain = Object.assign({}, singleBannerBidRequest, {schain: schain});
+
+ const reqs = spec.buildRequests([bidRequestWithSchain], defaultBidderRequest);
+
+ const req = extractPayloadOfFirstAndOnlyRequest(reqs);
+ expect(req.source.ext.schain).to.deep.equal(schain);
+ });
+ });
});
describe('interpretResponse', () => {
diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js
index 73bc9d45365..e710bd6d00f 100644
--- a/test/spec/modules/trustxBidAdapter_spec.js
+++ b/test/spec/modules/trustxBidAdapter_spec.js
@@ -519,6 +519,48 @@ describe('TrustXAdapter', function () {
expect(payload.tmax).to.equal(3000);
getConfigStub.restore();
});
+ it('should contain imp[].ext.data.adserver if available', function() {
+ const ortb2Imp = [{
+ ext: {
+ data: {
+ adserver: {
+ name: 'ad_server_name',
+ adslot: '/111111/slot'
+ },
+ pbadslot: '/111111/slot'
+ }
+ }
+ }, {
+ ext: {
+ data: {
+ adserver: {
+ name: 'ad_server_name',
+ adslot: '/222222/slot'
+ },
+ pbadslot: '/222222/slot'
+ }
+ }
+ }];
+ const bidRequestsWithOrtb2Imp = bidRequests.slice(0, 3).map((bid, ind) => {
+ return Object.assign(ortb2Imp[ind] ? { ortb2Imp: ortb2Imp[ind] } : {}, bid);
+ });
+ const request = spec.buildRequests(bidRequestsWithOrtb2Imp, bidderRequest);
+ expect(request.data).to.be.an('string');
+ const payload = parseRequest(request.data);
+ expect(payload.imp[0].ext).to.deep.equal({
+ divid: bidRequests[0].adUnitCode,
+ data: ortb2Imp[0].ext.data,
+ gpid: ortb2Imp[0].ext.data.adserver.adslot
+ });
+ expect(payload.imp[1].ext).to.deep.equal({
+ divid: bidRequests[1].adUnitCode,
+ data: ortb2Imp[1].ext.data,
+ gpid: ortb2Imp[1].ext.data.adserver.adslot
+ });
+ expect(payload.imp[2].ext).to.deep.equal({
+ divid: bidRequests[2].adUnitCode
+ });
+ });
it('all id like request fields must be a string', function () {
const bidderRequestWithNumId = Object.assign({}, bidderRequest, { bidderRequestId: 123123, auctionId: 345345543 });
diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js
index c3d2d216586..f0c3007b4c3 100755
--- a/test/spec/modules/visxBidAdapter_spec.js
+++ b/test/spec/modules/visxBidAdapter_spec.js
@@ -1149,7 +1149,7 @@ describe('VisxAdapter', function () {
it('onTimeout', function () {
const data = { timeout: 3000, bidId: '23423', params: { uid: 1 } };
spec.onTimeout(data);
- expect(utils.triggerPixel.calledOnceWith('https://t.visx.net/track/bid_timeout?data=' + JSON.stringify(data))).to.equal(true);
+ expect(utils.triggerPixel.calledOnceWith('https://t.visx.net/track/bid_timeout//' + JSON.stringify(data))).to.equal(true);
});
});
diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js
index 5b37f64688f..f414febcebe 100644
--- a/test/spec/unit/core/adapterManager_spec.js
+++ b/test/spec/unit/core/adapterManager_spec.js
@@ -1712,14 +1712,17 @@ describe('adapterManager tests', function () {
});
describe('sizeMapping', function () {
+ let sandbox;
beforeEach(function () {
+ sandbox = sinon.sandbox.create();
allS2SBidders.length = 0;
clientTestAdapters.length = 0;
- sinon.stub(window, 'matchMedia').callsFake(() => ({matches: true}));
+ // always have matchMedia return true for us
+ sandbox.stub(utils.getWindowTop(), 'matchMedia').callsFake(() => ({matches: true}));
});
afterEach(function () {
- matchMedia.restore();
+ sandbox.restore();
config.resetConfig();
setSizeConfig([]);
});