diff --git a/modules/dasBidAdapter.js b/modules/dasBidAdapter.js
new file mode 100644
index 00000000000..5d85644531f
--- /dev/null
+++ b/modules/dasBidAdapter.js
@@ -0,0 +1,373 @@
+import { getAllOrtbKeywords } from '../libraries/keywords/keywords.js';
+import { getAdUnitSizes } from '../libraries/sizeUtils/sizeUtils.js';
+import { registerBidder } from '../src/adapters/bidderFactory.js';
+import { BANNER, NATIVE } from '../src/mediaTypes.js';
+import { deepAccess, safeJSONParse } from '../src/utils.js';
+
+const BIDDER_CODE = 'das';
+const GDE_SCRIPT_URL = 'https://ocdn.eu/adp/static/embedgde/latest/bundle.min.js';
+const GDE_PARAM_PREFIX = 'gde_';
+const REQUIRED_GDE_PARAMS = [
+ 'gde_subdomena',
+ 'gde_id',
+ 'gde_stparam',
+ 'gde_fastid',
+ 'gde_inscreen'
+];
+
+function parseNativeResponse(ad) {
+ if (!(ad.data?.fields && ad.data?.meta)) {
+ return false;
+ }
+
+ const { click, Thirdpartyimpressiontracker, Thirdpartyimpressiontracker2, thirdPartyClickTracker2, imp, impression, impression1, impressionJs1, image, Image, title, leadtext, url, Calltoaction, Body, Headline, Thirdpartyclicktracker, adInfo, partner_logo: partnerLogo } = ad.data.fields;
+
+ const { dsaurl, height, width, adclick } = ad.data.meta;
+ const emsLink = ad.ems_link;
+ const link = adclick + (url || click);
+ const nativeResponse = {
+ sendTargetingKeys: false,
+ title: title || Headline || '',
+ image: {
+ url: image || Image || '',
+ width,
+ height
+ },
+ icon: {
+ url: partnerLogo || '',
+ width,
+ height
+ },
+ clickUrl: link,
+ cta: Calltoaction || '',
+ body: leadtext || Body || '',
+ body2: adInfo || '',
+ sponsoredBy: deepAccess(ad, 'data.meta.advertiser_name', null) || '',
+ };
+
+ nativeResponse.impressionTrackers = [emsLink, imp, impression, impression1, Thirdpartyimpressiontracker, Thirdpartyimpressiontracker2].filter(Boolean);
+ nativeResponse.javascriptTrackers = [impressionJs1, getGdeScriptUrl(ad.data.fields)].map(url => url ? `` : null).filter(Boolean);
+ nativeResponse.clickTrackers = [Thirdpartyclicktracker, thirdPartyClickTracker2].filter(Boolean);
+
+ if (dsaurl) {
+ nativeResponse.privacyLink = dsaurl;
+ }
+
+ return nativeResponse
+}
+
+function getGdeScriptUrl(adDataFields) {
+ if (REQUIRED_GDE_PARAMS.every(param => adDataFields[param])) {
+ const params = new URLSearchParams();
+ Object.entries(adDataFields)
+ .filter(([key]) => key.startsWith(GDE_PARAM_PREFIX))
+ .forEach(([key, value]) => params.append(key, value));
+
+ return `${GDE_SCRIPT_URL}?${params.toString()}`;
+ }
+ return null;
+}
+
+function getEndpoint(network) {
+ return `https://csr.onet.pl/${encodeURIComponent(network)}/bid`;
+}
+
+function parseParams(params, bidderRequest) {
+ const customParams = {};
+ const keyValues = {};
+
+ if (params.adbeta) {
+ customParams.adbeta = params.adbeta;
+ }
+
+ if (params.site) {
+ customParams.site = params.site;
+ }
+
+ if (params.area) {
+ customParams.area = params.area;
+ }
+
+ if (params.network) {
+ customParams.network = params.network;
+ }
+
+ // Custom parameters
+ if (params.customParams && typeof params.customParams === 'object') {
+ Object.assign(customParams, params.customParams);
+ }
+
+ const pageContext = params.pageContext;
+ if (pageContext) {
+ // Document URL override
+ if (pageContext.du) {
+ customParams.du = pageContext.du;
+ }
+
+ // Referrer override
+ if (pageContext.dr) {
+ customParams.dr = pageContext.dr;
+ }
+
+ // Document virtual address
+ if (pageContext.dv) {
+ customParams.DV = pageContext.dv;
+ }
+
+ // Keywords
+ const keywords = getAllOrtbKeywords(
+ bidderRequest?.ortb2,
+ pageContext.keyWords,
+ );
+ if (keywords.length > 0) {
+ customParams.kwrd = keywords.join('+');
+ }
+
+ // Local capping
+ if (pageContext.capping) {
+ customParams.local_capping = pageContext.capping;
+ }
+
+ // Key values
+ if (pageContext.keyValues && typeof pageContext.keyValues === 'object') {
+ Object.entries(pageContext.keyValues).forEach(([key, value]) => {
+ keyValues[`kv${key}`] = value;
+ });
+ }
+ }
+
+ const du = customParams.du || deepAccess(bidderRequest, 'refererInfo.page');
+ const dr = customParams.dr || deepAccess(bidderRequest, 'refererInfo.ref');
+
+ if (du) customParams.du = du;
+ if (dr) customParams.dr = dr;
+
+ const dsaRequired = deepAccess(bidderRequest, 'ortb2.regs.ext.dsa.required');
+ if (dsaRequired !== undefined) {
+ customParams.dsainfo = dsaRequired;
+ }
+
+ return {
+ customParams,
+ keyValues,
+ };
+}
+
+function buildUserIds(customParams) {
+ const userIds = {};
+ if (customParams.lu) {
+ userIds.lu = customParams.lu;
+ }
+ if (customParams.aid) {
+ userIds.aid = customParams.aid;
+ }
+ return userIds;
+}
+
+function getNpaFromPubConsent(pubConsent) {
+ const params = new URLSearchParams(pubConsent);
+ return params.get('npa') === '1';
+}
+
+function buildOpenRTBRequest(bidRequests, bidderRequest) {
+ const { customParams, keyValues } = parseParams(
+ bidRequests[0].params,
+ bidderRequest,
+ );
+ const imp = bidRequests.map((bid) => {
+ const sizes = getAdUnitSizes(bid);
+ const imp = {
+ id: bid.bidId,
+ tagid: bid.params.slot,
+ secure: 1,
+ };
+ if (bid.params.slotSequence) {
+ imp.ext = {
+ pos: String(bid.params.slotSequence)
+ }
+ }
+
+ if (bid.mediaTypes?.banner) {
+ imp.banner = {
+ format: sizes.map((size) => ({
+ w: size[0],
+ h: size[1],
+ })),
+ };
+ }
+ if (bid.mediaTypes?.native) {
+ imp.native = {
+ request: '{}',
+ ver: '1.2',
+ };
+ }
+
+ return imp;
+ });
+
+ const request = {
+ id: bidderRequest.bidderRequestId,
+ imp,
+ site: {
+ ...bidderRequest.ortb2?.site,
+ id: customParams.site,
+ page: customParams.du,
+ ref: customParams.dr,
+ ext: {
+ ...bidderRequest.ortb2?.site?.ext,
+ area: customParams.area,
+ kwrd: customParams.kwrd,
+ dv: customParams.DV
+ },
+ },
+ user: {
+ ext: {
+ ids: buildUserIds(customParams),
+ },
+ },
+ ext: {
+ network: customParams.network,
+ keyvalues: keyValues,
+ },
+ at: 1,
+ tmax: bidderRequest.timeout
+ };
+
+ if (customParams.adbeta) {
+ request.ext.adbeta = customParams.adbeta;
+ }
+
+ if (bidderRequest.device) {
+ request.device = bidderRequest.device;
+ }
+
+ if (bidderRequest.gdprConsent) {
+ request.user = {
+ ext: {
+ npa: getNpaFromPubConsent(customParams.pubconsent),
+ localcapping: customParams.local_capping,
+ localadpproduts: customParams.adp_products,
+ ...request.user.ext,
+ },
+ };
+ request.regs = {
+ gpp: bidderRequest.gdprConsent.consentString,
+ gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0,
+ ext: {
+ dsa: customParams.dsainfo,
+ },
+ }
+ }
+
+ return request;
+}
+
+function prepareNativeMarkup(bid) {
+ const parsedNativeMarkup = safeJSONParse(bid.adm)
+ const ad = {
+ data: parsedNativeMarkup || {},
+ ems_link: bid.ext?.ems_link || '',
+ };
+ const nativeResponse = parseNativeResponse(ad) || {};
+ return nativeResponse;
+}
+
+function interpretResponse(serverResponse) {
+ const bidResponses = [];
+ const response = serverResponse.body;
+
+ if (!response || !response.seatbid || !response.seatbid.length) {
+ return bidResponses;
+ }
+
+ response.seatbid.forEach((seatbid) => {
+ seatbid.bid.forEach((bid) => {
+ const bidResponse = {
+ requestId: bid.impid,
+ cpm: bid.price,
+ currency: response.cur || 'USD',
+ width: bid.w,
+ height: bid.h,
+ creativeId: bid.crid || bid.id,
+ netRevenue: true,
+ dealId: bid.dealid || null,
+ actgMatch: bid.ext?.actgMatch || 0,
+ ttl: 300,
+ meta: {
+ advertiserDomains: bid.adomain || [],
+ },
+ };
+
+ if (bid.mtype === 1) {
+ bidResponse.mediaType = BANNER;
+ bidResponse.ad = bid.adm;
+ } else if (bid.mtype === 4) {
+ bidResponse.mediaType = NATIVE;
+ bidResponse.native = prepareNativeMarkup(bid);
+ delete bidResponse.ad;
+ }
+ bidResponses.push(bidResponse);
+ });
+ });
+
+ return bidResponses;
+}
+
+export const spec = {
+ code: BIDDER_CODE,
+ aliases: ['ringieraxelspringer'],
+ supportedMediaTypes: [BANNER, NATIVE],
+
+ isBidRequestValid: function (bid) {
+ if (!bid || !bid.params) {
+ return false;
+ }
+ return !!(
+ bid.params?.network &&
+ bid.params?.site &&
+ bid.params?.area &&
+ bid.params?.slot
+ );
+ },
+
+ buildRequests: function (validBidRequests, bidderRequest) {
+ const data = buildOpenRTBRequest(validBidRequests, bidderRequest);
+ const jsonData = JSON.stringify(data);
+ const baseUrl = getEndpoint(data.ext.network);
+ const fullUrl = `${baseUrl}?data=${encodeURIComponent(jsonData)}`;
+
+ // adbeta needs credentials omitted to avoid CORS issues, especially in Firefox
+ const useCredentials = !data.ext?.adbeta;
+
+ // Switch to POST if URL exceeds 8k characters
+ if (fullUrl.length > 8192) {
+ return {
+ method: 'POST',
+ url: baseUrl,
+ data: jsonData,
+ options: {
+ withCredentials: useCredentials,
+ crossOrigin: true,
+ customHeaders: {
+ 'Content-Type': 'text/plain'
+ }
+ },
+ };
+ }
+
+ return {
+ method: 'GET',
+ url: fullUrl,
+ options: {
+ withCredentials: useCredentials,
+ crossOrigin: true,
+ },
+ };
+ },
+
+ interpretResponse: function (serverResponse) {
+ return interpretResponse(serverResponse);
+ },
+};
+
+registerBidder(spec);
diff --git a/modules/dasBidAdapter.md b/modules/dasBidAdapter.md
new file mode 100644
index 00000000000..2b28415df9b
--- /dev/null
+++ b/modules/dasBidAdapter.md
@@ -0,0 +1,52 @@
+# Overview
+
+```
+Module Name: DAS Bidder Adapter
+Module Type: Bidder Adapter
+Maintainer: support@ringpublishing.com
+```
+
+# Description
+
+Module that connects to DAS demand sources.
+Only banner and native format is supported.
+
+# Test Parameters
+```js
+var adUnits = [{
+ code: 'test-div-ad',
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250], [300, 600]]
+ }
+ },
+ bids: [{
+ bidder: 'das',
+ params: {
+ network: '4178463',
+ site: 'test',
+ area: 'areatest',
+ slot: 'slot'
+ }
+ }]
+}];
+```
+
+# Parameters
+
+| Name | Scope | Type | Description | Example |
+|------------------------------|----------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
+| network | required | String | Specific identifier provided by DAS | `"4178463"` |
+| site | required | String | Specific identifier name (case-insensitive) that is associated with this ad unit. Represents the website/domain in the ad unit hierarchy | `"example_com"` |
+| area | required | String | Ad unit category name; only case-insensitive alphanumeric with underscores and hyphens are allowed. Represents the content section or category | `"sport"` |
+| slot | required | String | Ad unit placement name (case-insensitive) | `"slot"` |
+| slotSequence | optional | Number | Ad unit sequence position provided by DAS | `1` |
+| pageContext | optional | Object | Web page context data | `{}` |
+| pageContext.dr | optional | String | Document referrer URL address | `"https://example.com/"` |
+| pageContext.du | optional | String | Document URL address | `"https://example.com/sport/football/article.html?id=932016a5-02fc-4d5c-b643-fafc2f270f06"` |
+| pageContext.dv | optional | String | Document virtual address as slash-separated path that may consist of any number of parts (case-insensitive alphanumeric with underscores and hyphens); first part should be the same as `site` value and second as `area` value; next parts may reflect website navigation | `"example_com/sport/football"` |
+| pageContext.keyWords | optional | String[] | List of keywords associated with this ad unit; only case-insensitive alphanumeric with underscores and hyphens are allowed | `["euro", "lewandowski"]` |
+| pageContext.keyValues | optional | Object | Key-values associated with this ad unit (case-insensitive); following characters are not allowed in the values: `" ' = ! + # * ~ ; ^ ( ) < > [ ] & @` | `{}` |
+| pageContext.keyValues.ci | optional | String | Content unique identifier | `"932016a5-02fc-4d5c-b643-fafc2f270f06"` |
+| pageContext.keyValues.adunit | optional | String | Ad unit name | `"example_com/sport"` |
+| customParams | optional | Object | Custom request params | `{}` |
diff --git a/modules/ringieraxelspringerBidAdapter.js b/modules/ringieraxelspringerBidAdapter.js
index 10cccecccf4..c5b7e000f87 100644
--- a/modules/ringieraxelspringerBidAdapter.js
+++ b/modules/ringieraxelspringerBidAdapter.js
@@ -1,402 +1,8 @@
-import { registerBidder } from '../src/adapters/bidderFactory.js';
-import { BANNER, NATIVE } from '../src/mediaTypes.js';
-import {
- isEmpty,
- parseSizesInput,
- deepAccess
-} from '../src/utils.js';
-import { getAllOrtbKeywords } from '../libraries/keywords/keywords.js';
-import { getAdUnitSizes } from '../libraries/sizeUtils/sizeUtils.js';
-import { BO_CSR_ONET } from '../libraries/paapiTools/buyerOrigins.js';
-
-const BIDDER_CODE = 'ringieraxelspringer';
-const VERSION = '1.0';
-
-const getEndpoint = (network) => {
- return `https://csr.onet.pl/${encodeURIComponent(network)}/csr-006/csr.json?nid=${encodeURIComponent(network)}&`;
-};
-
-function parseParams(params, bidderRequest) {
- const newParams = {};
- if (params.customParams && typeof params.customParams === 'object') {
- for (const param in params.customParams) {
- if (params.customParams.hasOwnProperty(param)) {
- newParams[param] = params.customParams[param];
- }
- }
- }
- const du = deepAccess(bidderRequest, 'refererInfo.page');
- const dr = deepAccess(bidderRequest, 'refererInfo.ref');
- if (du) {
- newParams.du = du;
- }
- if (dr) {
- newParams.dr = dr;
- }
- const pageContext = params.pageContext;
- if (!pageContext) {
- return newParams;
- }
- if (pageContext.du) {
- newParams.du = pageContext.du;
- }
- if (pageContext.dr) {
- newParams.dr = pageContext.dr;
- }
- if (pageContext.dv) {
- newParams.DV = pageContext.dv;
- }
- const keywords = getAllOrtbKeywords(bidderRequest?.ortb2, pageContext.keyWords)
- if (keywords.length > 0) {
- newParams.kwrd = keywords.join('+')
- }
- if (pageContext.capping) {
- newParams.local_capping = pageContext.capping;
- }
- if (pageContext.keyValues && typeof pageContext.keyValues === 'object') {
- for (const param in pageContext.keyValues) {
- if (pageContext.keyValues.hasOwnProperty(param)) {
- const kvName = 'kv' + param;
- newParams[kvName] = pageContext.keyValues[param];
- }
- }
- }
- if (bidderRequest?.ortb2?.regs?.ext?.dsa?.required !== undefined) {
- newParams.dsainfo = bidderRequest?.ortb2?.regs?.ext?.dsa?.required;
- }
- return newParams;
-}
-
/**
- * @param url string
- * @param type number // 1 - img, 2 - js
- * @returns an object { event: 1, method: 1 or 2, url: 'string' }
+ * Backward-compatibility shim for ringieraxelspringer bidder.
+ * This bidder has been renamed to 'das'.
+ *
+ * This file will be removed in Prebid 11.
+ * See dasBidAdapter.js for implementation.
*/
-function prepareItemEventtrackers(url, type) {
- return {
- event: 1,
- method: type,
- url: url
- };
-}
-
-function prepareEventtrackers(emsLink, imp, impression, impression1, impressionJs1) {
- const eventtrackers = [prepareItemEventtrackers(emsLink, 1)];
-
- if (imp) {
- eventtrackers.push(prepareItemEventtrackers(imp, 1));
- }
-
- if (impression) {
- eventtrackers.push(prepareItemEventtrackers(impression, 1));
- }
-
- if (impression1) {
- eventtrackers.push(prepareItemEventtrackers(impression1, 1));
- }
-
- if (impressionJs1) {
- eventtrackers.push(prepareItemEventtrackers(impressionJs1, 2));
- }
-
- return eventtrackers;
-}
-
-function parseOrtbResponse(ad) {
- if (!(ad.data?.fields && ad.data?.meta)) {
- return false;
- }
-
- const { image, Image, title, url, Headline, Thirdpartyclicktracker, thirdPartyClickTracker2, imp, impression, impression1, impressionJs1, partner_logo: partnerLogo, adInfo, body } = ad.data.fields;
- const { dsaurl, height, width, adclick } = ad.data.meta;
- const emsLink = ad.ems_link;
- const link = adclick + (url || Thirdpartyclicktracker);
- const eventtrackers = prepareEventtrackers(emsLink, imp, impression, impression1, impressionJs1);
- const clicktrackers = thirdPartyClickTracker2 ? [thirdPartyClickTracker2] : [];
-
- const ortb = {
- ver: '1.2',
- assets: [
- {
- id: 0,
- data: {
- value: body || '',
- type: 2
- },
- },
- {
- id: 1,
- data: {
- value: adInfo || '',
- // Body2 type
- type: 10
- },
- },
- {
- id: 3,
- img: {
- type: 1,
- url: partnerLogo || '',
- w: width,
- h: height
- }
- },
- {
- id: 4,
- img: {
- type: 3,
- url: image || Image || '',
- w: width,
- h: height
- }
- },
- {
- id: 5,
- data: {
- value: deepAccess(ad, 'data.meta.advertiser_name', null),
- type: 1
- }
- },
- {
- id: 6,
- title: {
- text: title || Headline || ''
- }
- },
- ],
- link: {
- url: link,
- clicktrackers
- },
- eventtrackers
- };
-
- if (dsaurl) {
- ortb.privacy = dsaurl
- }
-
- return ortb
-}
-
-function parseNativeResponse(ad) {
- if (!(ad.data?.fields && ad.data?.meta)) {
- return false;
- }
-
- const { image, Image, title, leadtext, url, Calltoaction, Body, Headline, Thirdpartyclicktracker, adInfo, partner_logo: partnerLogo } = ad.data.fields;
- const { dsaurl, height, width, adclick } = ad.data.meta;
- const link = adclick + (url || Thirdpartyclicktracker);
- const nativeResponse = {
- title: title || Headline || '',
- image: {
- url: image || Image || '',
- width,
- height
- },
- icon: {
- url: partnerLogo || '',
- width,
- height
- },
- clickUrl: link,
- cta: Calltoaction || '',
- body: leadtext || Body || '',
- body2: adInfo || '',
- sponsoredBy: deepAccess(ad, 'data.meta.advertiser_name', null) || '',
- ortb: parseOrtbResponse(ad)
- };
-
- if (dsaurl) {
- nativeResponse.privacyLink = dsaurl;
- }
-
- return nativeResponse
-}
-
-const buildBid = (ad, mediaType) => {
- if (ad.type === 'empty' || mediaType === undefined) {
- return null;
- }
-
- const data = {
- requestId: ad.id,
- cpm: ad.bid_rate ? ad.bid_rate.toFixed(2) : 0,
- ttl: 300,
- creativeId: ad.adid ? parseInt(ad.adid.split(',')[2], 10) : 0,
- netRevenue: true,
- currency: ad.currency || 'USD',
- dealId: ad.prebid_deal || null,
- actgMatch: ad.actg_match || 0,
- meta: { mediaType: BANNER },
- mediaType: BANNER,
- ad: ad.html || null,
- width: ad.width || 0,
- height: ad.height || 0
- }
-
- if (mediaType === 'native') {
- data.meta = { mediaType: NATIVE };
- data.mediaType = NATIVE;
- data.native = parseNativeResponse(ad) || {};
-
- delete data.ad;
- }
-
- return data;
-};
-
-const getContextParams = (bidRequests, bidderRequest) => {
- const bid = bidRequests[0];
- const { params } = bid;
- const requestParams = {
- site: params.site,
- area: params.area,
- cre_format: 'html',
- systems: 'das',
- kvprver: VERSION,
- ems_url: 1,
- bid_rate: 1,
- ...parseParams(params, bidderRequest)
- };
- return Object.keys(requestParams).map((key) => encodeURIComponent(key) + '=' + encodeURIComponent(requestParams[key])).join('&');
-};
-
-const getSlots = (bidRequests) => {
- let queryString = '';
- const batchSize = bidRequests.length;
- for (let i = 0; i < batchSize; i++) {
- const adunit = bidRequests[i];
- const slotSequence = deepAccess(adunit, 'params.slotSequence');
- const creFormat = getAdUnitCreFormat(adunit);
- const sizes = creFormat === 'native' ? 'fluid' : parseSizesInput(getAdUnitSizes(adunit)).join(',');
-
- queryString += `&slot${i}=${encodeURIComponent(adunit.params.slot)}&id${i}=${encodeURIComponent(adunit.bidId)}&composition${i}=CHILD`;
-
- if (creFormat === 'native') {
- queryString += `&cre_format${i}=native`;
- }
-
- queryString += `&kvhb_format${i}=${creFormat === 'native' ? 'native' : 'banner'}`;
-
- if (sizes) {
- queryString += `&iusizes${i}=${encodeURIComponent(sizes)}`;
- }
-
- if (slotSequence !== undefined && slotSequence !== null) {
- queryString += `&pos${i}=${encodeURIComponent(slotSequence)}`;
- }
- }
-
- return queryString;
-};
-
-const getGdprParams = (bidderRequest) => {
- const gdprApplies = deepAccess(bidderRequest, 'gdprConsent.gdprApplies');
- const consentString = deepAccess(bidderRequest, 'gdprConsent.consentString');
- let queryString = '';
- if (gdprApplies !== undefined) {
- queryString += `&gdpr_applies=${encodeURIComponent(gdprApplies)}`;
- }
- if (consentString !== undefined) {
- queryString += `&euconsent=${encodeURIComponent(consentString)}`;
- }
- return queryString;
-};
-
-const parseAuctionConfigs = (serverResponse, bidRequest) => {
- if (isEmpty(bidRequest)) {
- return null;
- }
- const auctionConfigs = [];
- const gctx = serverResponse && serverResponse.body?.gctx;
-
- bidRequest.bidIds.filter(bid => bid.fledgeEnabled).forEach((bid) => {
- auctionConfigs.push({
- 'bidId': bid.bidId,
- 'config': {
- 'seller': BO_CSR_ONET,
- 'decisionLogicUrl': `${BO_CSR_ONET}/${encodeURIComponent(bid.params.network)}/v1/protected-audience-api/decision-logic.js`,
- 'interestGroupBuyers': [ BO_CSR_ONET ],
- 'auctionSignals': {
- 'params': bid.params,
- 'sizes': bid.sizes,
- 'gctx': gctx
- }
- }
- });
- });
-
- if (auctionConfigs.length === 0) {
- return null;
- } else {
- return auctionConfigs;
- }
-}
-
-const getAdUnitCreFormat = (adUnit) => {
- if (!adUnit) {
- return;
- }
-
- let creFormat = 'html';
- const mediaTypes = Object.keys(adUnit.mediaTypes);
-
- if (mediaTypes && mediaTypes.length === 1 && mediaTypes.includes('native')) {
- creFormat = 'native';
- }
-
- return creFormat;
-}
-
-export const spec = {
- code: BIDDER_CODE,
- supportedMediaTypes: [BANNER, NATIVE],
-
- isBidRequestValid: function (bidRequest) {
- if (!bidRequest || !bidRequest.params || typeof bidRequest.params !== 'object') {
- return;
- }
- const { params } = bidRequest;
- return Boolean(params.network && params.site && params.area && params.slot);
- },
-
- buildRequests: function (bidRequests, bidderRequest) {
- const slotsQuery = getSlots(bidRequests);
- const contextQuery = getContextParams(bidRequests, bidderRequest);
- const gdprQuery = getGdprParams(bidderRequest);
- const fledgeEligible = Boolean(bidderRequest?.paapi?.enabled);
- const network = bidRequests[0].params.network;
- const bidIds = bidRequests.map((bid) => ({
- slot: bid.params.slot,
- bidId: bid.bidId,
- sizes: getAdUnitSizes(bid),
- params: bid.params,
- fledgeEnabled: fledgeEligible,
- mediaType: (bid.mediaTypes && bid.mediaTypes.banner) ? 'display' : NATIVE
- }));
-
- return [{
- method: 'GET',
- url: getEndpoint(network) + contextQuery + slotsQuery + gdprQuery,
- bidIds: bidIds
- }];
- },
-
- interpretResponse: function (serverResponse, bidRequest) {
- const response = serverResponse.body;
- const fledgeAuctionConfigs = parseAuctionConfigs(serverResponse, bidRequest);
- const bids = (!response || !response.ads || response.ads.length === 0) ? [] : response.ads.map((ad, index) => buildBid(
- ad,
- bidRequest?.bidIds?.[index]?.mediaType || 'banner'
- )).filter((bid) => !isEmpty(bid));
-
- if (fledgeAuctionConfigs) {
- // Return a tuple of bids and auctionConfigs. It is possible that bids could be null.
- return {bids, paapi: fledgeAuctionConfigs};
- } else {
- return bids;
- }
- }
-};
-
-registerBidder(spec);
+export { spec } from './dasBidAdapter.js'; // eslint-disable-line prebid/validate-imports
diff --git a/modules/ringieraxelspringerBidAdapter.md b/modules/ringieraxelspringerBidAdapter.md
index b3a716f9f56..4527d9f8c6d 100644
--- a/modules/ringieraxelspringerBidAdapter.md
+++ b/modules/ringieraxelspringerBidAdapter.md
@@ -1,52 +1,8 @@
# Overview
-```
-Module Name: Ringier Axel Springer Bidder Adapter
-Module Type: Bidder Adapter
-Maintainer: support@ringpublishing.com
-```
+The `ringieraxelspringer` bidder has been renamed to `das`.
+Please use the `das` bidder code instead.
-# Description
+See [dasBidAdapter.md](./dasBidAdapter.md) for documentation.
-Module that connects to Ringer Axel Springer demand sources.
-Only banner and native format is supported.
-
-# Test Parameters
-```js
-var adUnits = [{
- code: 'test-div-ad',
- mediaTypes: {
- banner: {
- sizes: [[300, 250], [300, 600]]
- }
- },
- bids: [{
- bidder: 'ringieraxelspringer',
- params: {
- network: '4178463',
- site: 'test',
- area: 'areatest',
- slot: 'slot'
- }
- }]
-}];
-```
-
-# Parameters
-
-| Name | Scope | Type | Description | Example |
-|------------------------------|----------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
-| network | required | String | Specific identifier provided by Ringier Axel Springer | `"4178463"` |
-| site | required | String | Specific identifier name (case-insensitive) that is associated with this ad unit and provided by Ringier Axel Springer | `"example_com"` |
-| area | required | String | Ad unit category name; only case-insensitive alphanumeric with underscores and hyphens are allowed | `"sport"` |
-| slot | required | String | Ad unit placement name (case-insensitive) provided by Ringier Axel Springer | `"slot"` |
-| slotSequence | optional | Number | Ad unit sequence position provided by Ringier Axel Springer | `1` |
-| pageContext | optional | Object | Web page context data | `{}` |
-| pageContext.dr | optional | String | Document referrer URL address | `"https://example.com/"` |
-| pageContext.du | optional | String | Document URL address | `"https://example.com/sport/football/article.html?id=932016a5-02fc-4d5c-b643-fafc2f270f06"` |
-| pageContext.dv | optional | String | Document virtual address as slash-separated path that may consist of any number of parts (case-insensitive alphanumeric with underscores and hyphens); first part should be the same as `site` value and second as `area` value; next parts may reflect website navigation | `"example_com/sport/football"` |
-| pageContext.keyWords | optional | String[] | List of keywords associated with this ad unit; only case-insensitive alphanumeric with underscores and hyphens are allowed | `["euro", "lewandowski"]` |
-| pageContext.keyValues | optional | Object | Key-values associated with this ad unit (case-insensitive); following characters are not allowed in the values: `" ' = ! + # * ~ ; ^ ( ) < > [ ] & @` | `{}` |
-| pageContext.keyValues.ci | optional | String | Content unique identifier | `"932016a5-02fc-4d5c-b643-fafc2f270f06"` |
-| pageContext.keyValues.adunit | optional | String | Ad unit name | `"example_com/sport"` |
-| customParams | optional | Object | Custom request params | `{}` |
+This adapter will be removed in Prebid 11.
diff --git a/test/spec/modules/dasBidAdapter_spec.js b/test/spec/modules/dasBidAdapter_spec.js
new file mode 100644
index 00000000000..edb7a85ee0f
--- /dev/null
+++ b/test/spec/modules/dasBidAdapter_spec.js
@@ -0,0 +1,507 @@
+import { expect } from 'chai';
+import { spec } from 'modules/dasBidAdapter.js';
+import { newBidder } from 'src/adapters/bidderFactory.js';
+
+describe('dasBidAdapter', function () {
+ const adapter = newBidder(spec);
+
+ describe('inherited functions', function () {
+ it('exists and is a function', function () {
+ expect(adapter.callBids).to.exist.and.to.be.a('function');
+ });
+ });
+
+ describe('isBidRequestValid', function () {
+ const validBid = {
+ params: {
+ site: 'site1',
+ area: 'area1',
+ slot: 'slot1',
+ network: 'network1'
+ }
+ };
+
+ it('should return true when required params are present', function () {
+ expect(spec.isBidRequestValid(validBid)).to.be.true;
+ });
+
+ it('should return false when required params are missing', function () {
+ expect(spec.isBidRequestValid({})).to.be.false;
+ expect(spec.isBidRequestValid({ params: {} })).to.be.false;
+ expect(spec.isBidRequestValid({ params: { site: 'site1' } })).to.be.false;
+ expect(spec.isBidRequestValid({ params: { area: 'area1' } })).to.be.false;
+ expect(spec.isBidRequestValid({ params: { slot: 'slot1' } })).to.be.false;
+ });
+
+ it('should return true with additional optional params', function () {
+ const bidWithOptional = {
+ params: {
+ site: 'site1',
+ area: 'area1',
+ slot: 'slot1',
+ network: 'network1',
+ customParams: {
+ param1: 'value1'
+ },
+ pageContext: {
+ du: 'https://example.com',
+ dr: 'https://referrer.com',
+ dv: '1.0',
+ keyWords: ['key1', 'key2'],
+ capping: 'cap1',
+ keyValues: {
+ key1: 'value1'
+ }
+ }
+ }
+ };
+ expect(spec.isBidRequestValid(bidWithOptional)).to.be.true;
+ });
+
+ it('should return false when params is undefined', function () {
+ expect(spec.isBidRequestValid()).to.be.false;
+ });
+
+ it('should return false when required params are empty strings', function () {
+ const bidWithEmptyStrings = {
+ params: {
+ site: '',
+ area: '',
+ slot: ''
+ }
+ };
+ expect(spec.isBidRequestValid(bidWithEmptyStrings)).to.be.false;
+ });
+
+ it('should return false when required params are non-string values', function () {
+ const bidWithNonStringValues = {
+ params: {
+ site: 123,
+ area: true,
+ slot: {}
+ }
+ };
+ expect(spec.isBidRequestValid(bidWithNonStringValues)).to.be.false;
+ });
+
+ it('should return false when params is null', function () {
+ const bidWithNullParams = {
+ params: null
+ };
+ expect(spec.isBidRequestValid(bidWithNullParams)).to.be.false;
+ });
+
+ it('should return true with minimal valid params', function () {
+ const minimalBid = {
+ params: {
+ site: 'site1',
+ area: 'area1',
+ slot: 'slot1',
+ network: 'network1'
+ }
+ };
+ expect(spec.isBidRequestValid(minimalBid)).to.be.true;
+ });
+
+ it('should return false with partial required params', function () {
+ const partialBids = [
+ { params: { site: 'site1', area: 'area1' } },
+ { params: { site: 'site1', slot: 'slot1' } },
+ { params: { area: 'area1', slot: 'slot1' } }
+ ];
+
+ partialBids.forEach(bid => {
+ expect(spec.isBidRequestValid(bid)).to.be.false;
+ });
+ });
+ });
+
+ describe('buildRequests', function () {
+ const bidRequests = [{
+ bidId: 'bid123',
+ params: {
+ site: 'site1',
+ area: 'area1',
+ slot: 'slot1',
+ network: 'network1',
+ pageContext: {
+ du: 'https://example.com',
+ dr: 'https://referrer.com',
+ dv: '1.0',
+ keyWords: ['key1', 'key2'],
+ capping: 'cap1',
+ keyValues: { key1: 'value1' }
+ }
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250]]
+ }
+ }
+ }];
+
+ const bidderRequest = {
+ bidderRequestId: 'reqId123',
+ timeout: 1000,
+ refererInfo: {
+ page: 'https://example.com',
+ ref: 'https://referrer.com'
+ },
+ gdprConsent: {
+ consentString: 'consent123',
+ gdprApplies: true
+ },
+ ortb2: {
+ site: {}
+ }
+ };
+
+ it('should return proper request object', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+
+ expect(request.method).to.equal('GET');
+ expect(request.options.withCredentials).to.be.true;
+ expect(request.options.crossOrigin).to.be.true;
+
+ expect(request.url).to.include('https://csr.onet.pl/network1/bid?data=');
+ const urlParts = request.url.split('?');
+ expect(urlParts.length).to.equal(2);
+
+ const params = new URLSearchParams(urlParts[1]);
+ expect(params.has('data')).to.be.true;
+
+ const payload = JSON.parse(decodeURIComponent(params.get('data')));
+ expect(payload.id).to.equal('reqId123');
+ expect(payload.imp[0].id).to.equal('bid123');
+ expect(payload.imp[0].tagid).to.equal('slot1');
+ expect(payload.imp[0].banner.format[0]).to.deep.equal({ w: 300, h: 250 });
+ });
+
+ it('should use GET method when URL is under 8192 characters', function () {
+ const request = spec.buildRequests(bidRequests, bidderRequest);
+ expect(request.method).to.equal('GET');
+ expect(request.url).to.include('?data=');
+ expect(request.data).to.be.undefined;
+ });
+
+ it('should switch to POST method when URL exceeds 8192 characters', function () {
+ // Create a large bid request that will result in URL > 8k characters
+ const largeBidRequests = [];
+ for (let i = 0; i < 50; i++) {
+ largeBidRequests.push({
+ bidId: `bid${i}`.repeat(20), // Make bid IDs longer
+ params: {
+ site: `site${i}`.repeat(50),
+ area: `area${i}`.repeat(50),
+ slot: `slot${i}`.repeat(50),
+ network: 'network1',
+ pageContext: {
+ du: `https://very-long-url-example-${i}.com`.repeat(10),
+ dr: `https://very-long-referrer-url-${i}.com`.repeat(10),
+ dv: `version-${i}`.repeat(20),
+ keyWords: Array(20).fill(`keyword${i}`),
+ capping: `cap${i}`.repeat(20),
+ keyValues: {
+ [`key${i}`]: `value${i}`.repeat(50)
+ }
+ },
+ customParams: {
+ [`param${i}`]: `value${i}`.repeat(50)
+ }
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250], [728, 90], [970, 250]]
+ }
+ }
+ });
+ }
+
+ const request = spec.buildRequests(largeBidRequests, bidderRequest);
+
+ expect(request.method).to.equal('POST');
+ expect(request.url).to.equal('https://csr.onet.pl/network1/bid');
+ expect(request.data).to.be.a('string');
+
+ // Check if data is valid JSON (not URL-encoded form data)
+ const payload = JSON.parse(request.data);
+ expect(payload.id).to.equal('reqId123');
+ expect(payload.imp).to.be.an('array');
+ expect(request.options.customHeaders['Content-Type']).to.equal('text/plain');
+ });
+
+ it('should create valid POST data format', function () {
+ // Create a request that will trigger POST
+ const largeBidRequests = Array(50).fill(0).map((_, i) => ({
+ bidId: `bid${i}`.repeat(20),
+ params: {
+ site: `site${i}`.repeat(50),
+ area: `area${i}`.repeat(50),
+ slot: `slot${i}`.repeat(50),
+ network: 'network1',
+ pageContext: {
+ du: `https://very-long-url-example-${i}.com`.repeat(10),
+ dr: `https://very-long-referrer-url-${i}.com`.repeat(10),
+ keyWords: Array(10).fill(`keyword${i}`)
+ }
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250]]
+ }
+ }
+ }));
+
+ const request = spec.buildRequests(largeBidRequests, bidderRequest);
+
+ expect(request.method).to.equal('POST');
+
+ // Parse the POST data as JSON (not URL-encoded)
+ const payload = JSON.parse(request.data);
+ expect(payload.id).to.equal('reqId123');
+ expect(payload.imp).to.be.an('array').with.length(50);
+ expect(payload.ext.network).to.equal('network1');
+ });
+
+ it('should set withCredentials to false when adbeta flag is present', function () {
+ const bidRequestsWithAdbeta = [{
+ bidId: 'bid123',
+ params: {
+ site: 'site1',
+ area: 'area1',
+ slot: 'slot1',
+ network: 'network1',
+ adbeta: 'l1021885!slot.nativestd',
+ pageContext: {}
+ },
+ mediaTypes: {
+ banner: {
+ sizes: [[300, 250]]
+ }
+ }
+ }];
+
+ const bidderRequestWithAdbeta = {
+ bidderRequestId: 'reqId123',
+ ortb2: {},
+ adbeta: true
+ };
+
+ const request = spec.buildRequests(bidRequestsWithAdbeta, bidderRequestWithAdbeta);
+
+ expect(request.options.withCredentials).to.be.false;
+ });
+
+ describe('interpretResponse', function () {
+ const serverResponse = {
+ body: {
+ seatbid: [{
+ bid: [{
+ impid: 'bid123',
+ price: 3.5,
+ w: 300,
+ h: 250,
+ adm: '',
+ crid: 'crid123',
+ mtype: 1,
+ adomain: ['advertiser.com']
+ }]
+ }],
+ cur: 'USD'
+ }
+ };
+
+ it('should return proper bid response', function () {
+ const bidResponses = spec.interpretResponse(serverResponse);
+
+ expect(bidResponses).to.be.an('array').with.lengthOf(1);
+ expect(bidResponses[0]).to.deep.include({
+ requestId: 'bid123',
+ cpm: 3.5,
+ currency: 'USD',
+ width: 300,
+ height: 250,
+ ad: '',
+ creativeId: 'crid123',
+ netRevenue: true,
+ ttl: 300,
+ mediaType: 'banner'
+ });
+ expect(bidResponses[0].meta.advertiserDomains).to.deep.equal(['advertiser.com']);
+ });
+
+ it('should return empty array when no valid responses', function () {
+ expect(spec.interpretResponse({ body: null })).to.be.an('array').that.is.empty;
+ expect(spec.interpretResponse({ body: {} })).to.be.an('array').that.is.empty;
+ expect(spec.interpretResponse({ body: { seatbid: [] } })).to.be.an('array').that.is.empty;
+ });
+
+ it('should return proper bid response for native', function () {
+ const nativeResponse = {
+ body: {
+ seatbid: [{
+ bid: [{
+ impid: 'bid123',
+ price: 3.5,
+ w: 1,
+ h: 1,
+ adm: JSON.stringify({
+ fields: {
+ Body: 'Ruszyła sprzedaż mieszkań przy Metrze Dworzec Wileński',
+ Calltoaction: 'SPRAWDŹ',
+ Headline: 'Gotowe mieszkania w świetnej lokalizacji (test)',
+ Image: 'https://ocdn.eu/example.jpg',
+ Sponsorlabel: 'tak',
+ Thirdpartyclicktracker: '',
+ Thirdpartyimpressiontracker: '',
+ Thirdpartyimpressiontracker2: '',
+ borderColor: '#CECECE',
+ click: 'https://mieszkaniaprzymetrodworzec.pl',
+ responsive: 'nie'
+ },
+ tplCode: '1746213/Native-In-Feed',
+ meta: {
+ inIFrame: false,
+ autoscale: 0,
+ width: '1',
+ height: '1',
+ adid: 'das,1778361,669261',
+ actioncount: 'https://csr.onet.pl/eclk/...',
+ slot: 'right2',
+ adclick: 'https://csr.onet.pl/clk/...',
+ container_wrapper: '',
+ prebid_native: true
+ }
+ }),
+ mtype: 4
+ }]
+ }],
+ cur: 'USD'
+ }
+ };
+
+ const bidResponses = spec.interpretResponse(nativeResponse);
+
+ expect(bidResponses).to.be.an('array').with.lengthOf(1);
+ expect(bidResponses[0]).to.deep.include({
+ requestId: 'bid123',
+ cpm: 3.5,
+ currency: 'USD',
+ width: 1,
+ height: 1,
+ native: {
+ title: 'Gotowe mieszkania w świetnej lokalizacji (test)',
+ body: 'Ruszyła sprzedaż mieszkań przy Metrze Dworzec Wileński',
+ cta: 'SPRAWDŹ',
+ image: {
+ url: 'https://ocdn.eu/example.jpg',
+ width: '1',
+ height: '1'
+ },
+ icon: {
+ url: '',
+ width: '1',
+ height: '1'
+ },
+ clickUrl: 'https://csr.onet.pl/clk/...https://mieszkaniaprzymetrodworzec.pl',
+ body2: '',
+ sponsoredBy: '',
+ clickTrackers: [],
+ impressionTrackers: [],
+ javascriptTrackers: [],
+ sendTargetingKeys: false
+ },
+ netRevenue: true,
+ ttl: 300,
+ mediaType: 'native'
+ });
+
+ expect(bidResponses[0]).to.not.have.property('ad');
+ });
+ });
+
+ it('should return empty object when adm in a native response is not JSON', function () {
+ const nativeResponse = {
+ body: {
+ seatbid: [{
+ bid: [{
+ impid: 'bad1',
+ price: 2.0,
+ w: 1,
+ h: 1,
+ adm: 'not-a-json-string',
+ mtype: 4
+ }]
+ }],
+ cur: 'USD'
+ }
+ };
+
+ const bidResponses = spec.interpretResponse(nativeResponse);
+ expect(bidResponses[0].native).to.deep.equal({});
+ });
+
+ it('should return empty object when adm in a native response is missing required fields/meta', function () {
+ const nativeResponse = {
+ body: {
+ seatbid: [{
+ bid: [{
+ impid: 'bad2',
+ price: 2.0,
+ w: 1,
+ h: 1,
+ adm: JSON.stringify({ fields: {} }),
+ mtype: 4
+ }]
+ }],
+ cur: 'USD'
+ }
+ };
+
+ const bidResponses = spec.interpretResponse(nativeResponse);
+ expect(bidResponses[0].native).to.deep.equal({});
+ });
+
+ it('should return empty object when adm in a native response is empty JSON object', function () {
+ const nativeResponse = {
+ body: {
+ seatbid: [{
+ bid: [{
+ impid: 'bad3',
+ price: 2.0,
+ w: 1,
+ h: 1,
+ adm: JSON.stringify({}),
+ mtype: 4
+ }]
+ }],
+ cur: 'USD'
+ }
+ };
+
+ const bidResponses = spec.interpretResponse(nativeResponse);
+ expect(bidResponses[0].native).to.deep.equal({});
+ });
+
+ it('should return empty object when adm in a native response is null or missing', function () {
+ const nativeResponse = {
+ body: {
+ seatbid: [{
+ bid: [{
+ impid: 'bad4',
+ price: 2.0,
+ w: 1,
+ h: 1,
+ adm: null,
+ mtype: 4
+ }]
+ }],
+ cur: 'USD'
+ }
+ };
+
+ const bidResponses = spec.interpretResponse(nativeResponse);
+ expect(bidResponses[0].native).to.deep.equal({});
+ });
+ });
+});
diff --git a/test/spec/modules/ringieraxelspringerBidAdapter_spec.js b/test/spec/modules/ringieraxelspringerBidAdapter_spec.js
index 08587e5174f..0318a6987c6 100644
--- a/test/spec/modules/ringieraxelspringerBidAdapter_spec.js
+++ b/test/spec/modules/ringieraxelspringerBidAdapter_spec.js
@@ -1,676 +1,10 @@
import { expect } from 'chai';
import { spec } from 'modules/ringieraxelspringerBidAdapter.js';
-import { newBidder } from 'src/adapters/bidderFactory.js';
-const CSR_ENDPOINT = 'https://csr.onet.pl/4178463/csr-006/csr.json?nid=4178463&';
-
-describe('ringieraxelspringerBidAdapter', function () {
- const adapter = newBidder(spec);
-
- describe('inherited functions', function () {
- it('exists and is a function', function () {
- expect(adapter.callBids).to.exist.and.to.be.a('function');
- });
- });
-
- describe('isBidRequestValid', function () {
- it('should return true when required params found', function () {
- const bid = {
- sizes: [[300, 250], [300, 600]],
- bidder: 'ringieraxelspringer',
- params: {
- slot: 'slot',
- area: 'areatest',
- site: 'test',
- network: '4178463'
- }
- };
- expect(spec.isBidRequestValid(bid)).to.equal(true);
- });
-
- it('should return false when required params not found', function () {
- const failBid = {
- sizes: [[300, 250], [300, 300]],
- bidder: 'ringieraxelspringer',
- params: {
- site: 'test',
- network: '4178463'
- }
- };
- expect(spec.isBidRequestValid(failBid)).to.equal(false);
- });
-
- it('should return nothing when bid request is malformed', function () {
- const failBid = {
- sizes: [[300, 250], [300, 300]],
- bidder: 'ringieraxelspringer',
- };
- expect(spec.isBidRequestValid(failBid)).to.equal(undefined);
- });
- });
-
- describe('buildRequests', function () {
- const bid = {
- sizes: [[300, 250], [300, 600]],
- bidder: 'ringieraxelspringer',
- bidId: 1,
- params: {
- slot: 'test',
- area: 'areatest',
- site: 'test',
- slotSequence: '0',
- network: '4178463',
- customParams: {
- test: 'name=value'
- }
- },
- mediaTypes: {
- banner: {
- sizes: [
- [
- 300,
- 250
- ],
- [
- 300,
- 600
- ]
- ]
- }
- }
- };
- const bid2 = {
- sizes: [[750, 300]],
- bidder: 'ringieraxelspringer',
- bidId: 2,
- params: {
- slot: 'test2',
- area: 'areatest',
- site: 'test',
- network: '4178463'
- },
- mediaTypes: {
- banner: {
- sizes: [
- [
- 750,
- 300
- ]
- ]
- }
- }
- };
-
- it('should parse bids to request', function () {
- const requests = spec.buildRequests([bid], {
- 'gdprConsent': {
- 'gdprApplies': true,
- 'consentString': 'some-consent-string'
- },
- 'refererInfo': {
- 'ref': 'https://example.org/',
- 'page': 'https://example.com/'
- }
- });
- expect(requests[0].url).to.have.string(CSR_ENDPOINT);
- expect(requests[0].url).to.have.string('slot0=test');
- expect(requests[0].url).to.have.string('id0=1');
- expect(requests[0].url).to.have.string('site=test');
- expect(requests[0].url).to.have.string('area=areatest');
- expect(requests[0].url).to.have.string('cre_format=html');
- expect(requests[0].url).to.have.string('systems=das');
- expect(requests[0].url).to.have.string('ems_url=1');
- expect(requests[0].url).to.have.string('bid_rate=1');
- expect(requests[0].url).to.have.string('gdpr_applies=true');
- expect(requests[0].url).to.have.string('euconsent=some-consent-string');
- expect(requests[0].url).to.have.string('du=https%3A%2F%2Fexample.com%2F');
- expect(requests[0].url).to.have.string('dr=https%3A%2F%2Fexample.org%2F');
- expect(requests[0].url).to.have.string('test=name%3Dvalue');
- });
-
- it('should return empty consent string when undefined', function () {
- const requests = spec.buildRequests([bid]);
- const gdpr = requests[0].url.search('gdpr_applies');
- const euconsent = requests[0].url.search('euconsent=');
- expect(gdpr).to.equal(-1);
- expect(euconsent).to.equal(-1);
- });
-
- it('should parse bids to request from pageContext', function () {
- const bidCopy = { ...bid };
- bidCopy.params = {
- ...bid.params,
- pageContext: {
- dv: 'test/areatest',
- du: 'https://example.com/',
- dr: 'https://example.org/',
- keyWords: ['val1', 'val2'],
- keyValues: {
- adunit: 'test/areatest'
- }
- }
- };
- const requests = spec.buildRequests([bidCopy, bid2]);
-
- expect(requests[0].url).to.have.string(CSR_ENDPOINT);
- expect(requests[0].url).to.have.string('slot0=test');
- expect(requests[0].url).to.have.string('id0=1');
- expect(requests[0].url).to.have.string('iusizes0=300x250%2C300x600');
- expect(requests[0].url).to.have.string('slot1=test2');
- expect(requests[0].url).to.have.string('kvhb_format0=banner');
- expect(requests[0].url).to.have.string('id1=2');
- expect(requests[0].url).to.have.string('iusizes1=750x300');
- expect(requests[0].url).to.have.string('kvhb_format1=banner');
- expect(requests[0].url).to.have.string('site=test');
- expect(requests[0].url).to.have.string('area=areatest');
- expect(requests[0].url).to.have.string('cre_format=html');
- expect(requests[0].url).to.have.string('systems=das');
- expect(requests[0].url).to.have.string('ems_url=1');
- expect(requests[0].url).to.have.string('bid_rate=1');
- expect(requests[0].url).to.have.string('du=https%3A%2F%2Fexample.com%2F');
- expect(requests[0].url).to.have.string('dr=https%3A%2F%2Fexample.org%2F');
- expect(requests[0].url).to.have.string('DV=test%2Fareatest');
- expect(requests[0].url).to.have.string('kwrd=val1%2Bval2');
- expect(requests[0].url).to.have.string('kvadunit=test%2Fareatest');
- expect(requests[0].url).to.have.string('pos0=0');
- });
-
- it('should parse dsainfo when available', function () {
- const bidCopy = { ...bid };
- bidCopy.params = {
- ...bid.params,
- pageContext: {
- dv: 'test/areatest',
- du: 'https://example.com/',
- dr: 'https://example.org/',
- keyWords: ['val1', 'val2'],
- keyValues: {
- adunit: 'test/areatest'
- }
- }
- };
- const bidderRequest = {
- ortb2: {
- regs: {
- ext: {
- dsa: {
- required: 1
- }
- }
- }
- }
- };
- let requests = spec.buildRequests([bidCopy], bidderRequest);
- expect(requests[0].url).to.have.string('dsainfo=1');
-
- bidderRequest.ortb2.regs.ext.dsa.required = 0;
- requests = spec.buildRequests([bidCopy], bidderRequest);
- expect(requests[0].url).to.have.string('dsainfo=0');
- });
- });
-
- describe('interpretResponse', function () {
- const response = {
- 'adsCheck': 'ok',
- 'geoloc': {},
- 'ir': '92effd60-0c84-4dac-817e-763ea7b8ac65',
- 'ads': [
- {
- 'id': 'flat-belkagorna',
- 'slot': 'flat-belkagorna',
- 'prio': 10,
- 'type': 'html',
- 'bid_rate': 0.321123,
- 'adid': 'das,50463,152276',
- 'id_3': '12734',
- 'html': ''
- }
- ],
- 'iv': '202003191334467636346500'
- };
-
- it('should get correct bid response', function () {
- const resp = spec.interpretResponse({ body: response }, { bidIds: [{ slot: 'flat-belkagorna', bidId: 1 }] });
- expect(resp[0]).to.have.all.keys('cpm', 'currency', 'netRevenue', 'requestId', 'ttl', 'width', 'height', 'creativeId', 'dealId', 'ad', 'meta', 'actgMatch', 'mediaType');
- expect(resp.length).to.equal(1);
- });
-
- it('should handle empty ad', function () {
- const res = {
- 'ads': [{
- type: 'empty'
- }]
- };
- const resp = spec.interpretResponse({ body: res }, {});
- expect(resp).to.deep.equal([]);
- });
-
- it('should handle empty server response', function () {
- const res = {
- 'ads': []
- };
- const resp = spec.interpretResponse({ body: res }, {});
- expect(resp).to.deep.equal([]);
- });
-
- it('should generate auctionConfig when fledge is enabled', function () {
- const bidRequest = {
- method: 'GET',
- url: 'https://example.com',
- bidIds: [{
- slot: 'top',
- bidId: '123',
- network: 'testnetwork',
- sizes: ['300x250'],
- params: {
- site: 'testsite',
- area: 'testarea',
- network: 'testnetwork'
- },
- fledgeEnabled: true
- },
- {
- slot: 'top',
- bidId: '456',
- network: 'testnetwork',
- sizes: ['300x250'],
- params: {
- site: 'testsite',
- area: 'testarea',
- network: 'testnetwork'
- },
- fledgeEnabled: false
- }]
- };
-
- const auctionConfigs = [{
- 'bidId': '123',
- 'config': {
- 'seller': 'https://csr.onet.pl',
- 'decisionLogicUrl': 'https://csr.onet.pl/testnetwork/v1/protected-audience-api/decision-logic.js',
- 'interestGroupBuyers': ['https://csr.onet.pl'],
- 'auctionSignals': {
- 'params': {
- site: 'testsite',
- area: 'testarea',
- network: 'testnetwork'
- },
- 'sizes': ['300x250'],
- 'gctx': '1234567890'
- }
- }
- }];
- const resp = spec.interpretResponse({body: {gctx: '1234567890'}}, bidRequest);
- expect(resp).to.deep.equal({bids: [], paapi: auctionConfigs});
- });
- });
-
- describe('buildNativeRequests', function () {
- const bid = {
- sizes: 'fluid',
- bidder: 'ringieraxelspringer',
- bidId: 1,
- params: {
- slot: 'nativestd',
- area: 'areatest',
- site: 'test',
- slotSequence: '0',
- network: '4178463',
- customParams: {
- test: 'name=value'
- }
- },
- mediaTypes: {
- native: {
- clickUrl: {
- required: true
- },
- image: {
- required: true
- },
- sponsoredBy: {
- len: 25,
- required: true
- },
- title: {
- len: 50,
- required: true
- }
- }
- }
- };
-
- it('should parse bids to native request', function () {
- const requests = spec.buildRequests([bid], {
- 'gdprConsent': {
- 'gdprApplies': true,
- 'consentString': 'some-consent-string'
- },
- 'refererInfo': {
- 'ref': 'https://example.org/',
- 'page': 'https://example.com/'
- }
- });
-
- expect(requests[0].url).to.have.string(CSR_ENDPOINT);
- expect(requests[0].url).to.have.string('slot0=nativestd');
- expect(requests[0].url).to.have.string('id0=1');
- expect(requests[0].url).to.have.string('site=test');
- expect(requests[0].url).to.have.string('area=areatest');
- expect(requests[0].url).to.have.string('cre_format=html');
- expect(requests[0].url).to.have.string('systems=das');
- expect(requests[0].url).to.have.string('ems_url=1');
- expect(requests[0].url).to.have.string('bid_rate=1');
- expect(requests[0].url).to.have.string('gdpr_applies=true');
- expect(requests[0].url).to.have.string('euconsent=some-consent-string');
- expect(requests[0].url).to.have.string('du=https%3A%2F%2Fexample.com%2F');
- expect(requests[0].url).to.have.string('dr=https%3A%2F%2Fexample.org%2F');
- expect(requests[0].url).to.have.string('test=name%3Dvalue');
- expect(requests[0].url).to.have.string('cre_format0=native');
- expect(requests[0].url).to.have.string('kvhb_format0=native');
- expect(requests[0].url).to.have.string('iusizes0=fluid');
- });
- });
-
- describe('interpretNativeResponse', function () {
- const response = {
- 'adsCheck': 'ok',
- 'geoloc': {},
- 'ir': '92effd60-0c84-4dac-817e-763ea7b8ac65',
- 'iv': '202003191334467636346500',
- 'ads': [
- {
- 'id': 'nativestd',
- 'slot': 'nativestd',
- 'prio': 10,
- 'type': 'native',
- 'bid_rate': 0.321123,
- 'adid': 'das,50463,152276',
- 'id_3': '12734'
- }
- ]
- };
- const responseTeaserStandard = {
- adsCheck: 'ok',
- geoloc: {},
- ir: '92effd60-0c84-4dac-817e-763ea7b8ac65',
- iv: '202003191334467636346500',
- ads: [
- {
- id: 'nativestd',
- slot: 'nativestd',
- prio: 10,
- type: 'native',
- bid_rate: 0.321123,
- adid: 'das,50463,152276',
- id_3: '12734',
- data: {
- fields: {
- leadtext: 'BODY',
- title: 'Headline',
- image: '//img.url',
- url: '//link.url',
- partner_logo: '//logo.url',
- adInfo: 'REKLAMA',
- impression: '//impression.url',
- impression1: '//impression1.url',
- impressionJs1: '//impressionJs1.url'
- },
- meta: {
- slot: 'nativestd',
- height: 1,
- width: 1,
- advertiser_name: 'Test Onet',
- dsaurl: '//dsa.url',
- adclick: '//adclick.url'
- }
- },
- ems_link: '//ems.url'
- }
- ]
- };
- const responseNativeInFeed = {
- adsCheck: 'ok',
- geoloc: {},
- ir: '92effd60-0c84-4dac-817e-763ea7b8ac65',
- iv: '202003191334467636346500',
- ads: [
- {
- id: 'nativestd',
- slot: 'nativestd',
- prio: 10,
- type: 'native',
- bid_rate: 0.321123,
- adid: 'das,50463,152276',
- id_3: '12734',
- data: {
- fields: {
- Body: 'BODY',
- Calltoaction: 'Calltoaction',
- Headline: 'Headline',
- Image: '//img.url',
- adInfo: 'REKLAMA',
- Thirdpartyclicktracker: '//link.url',
- imp: '//imp.url',
- thirdPartyClickTracker2: '//thirdPartyClickTracker.url'
- },
- meta: {
- slot: 'nativestd',
- height: 1,
- width: 1,
- advertiser_name: 'Test Onet',
- dsaurl: '//dsa.url',
- adclick: '//adclick.url'
- }
- },
- ems_link: '//ems.url'
- }
- ]
- };
- const expectedTeaserStandardOrtbResponse = {
- ver: '1.2',
- assets: [
- {
- id: 0,
- data: {
- value: '',
- type: 2
- },
- },
- {
- id: 1,
- data: {
- value: 'REKLAMA',
- type: 10
- },
- },
- {
- id: 3,
- img: {
- type: 1,
- url: '//logo.url',
- w: 1,
- h: 1
- }
- },
- {
- id: 4,
- img: {
- type: 3,
- url: '//img.url',
- w: 1,
- h: 1
- }
- },
- {
- id: 5,
- data: {
- value: 'Test Onet',
- type: 1
- },
- },
- {
- id: 6,
- title: {
- text: 'Headline'
- }
- },
- ],
- link: {
- url: '//adclick.url//link.url',
- clicktrackers: []
- },
- eventtrackers: [
- {
- event: 1,
- method: 1,
- url: '//ems.url'
- },
- {
- event: 1,
- method: 1,
- url: '//impression.url'
- },
- {
- event: 1,
- method: 1,
- url: '//impression1.url'
- },
- {
- event: 1,
- method: 2,
- url: '//impressionJs1.url'
- }
- ],
- privacy: '//dsa.url'
- };
- const expectedTeaserStandardResponse = {
- title: 'Headline',
- image: {
- url: '//img.url',
- width: 1,
- height: 1
- },
- icon: {
- url: '//logo.url',
- width: 1,
- height: 1
- },
- clickUrl: '//adclick.url//link.url',
- cta: '',
- body: 'BODY',
- body2: 'REKLAMA',
- sponsoredBy: 'Test Onet',
- ortb: expectedTeaserStandardOrtbResponse,
- privacyLink: '//dsa.url'
- };
- const expectedNativeInFeedOrtbResponse = {
- ver: '1.2',
- assets: [
- {
- id: 0,
- data: {
- value: '',
- type: 2
- },
- },
- {
- id: 1,
- data: {
- value: 'REKLAMA',
- type: 10
- },
- },
- {
- id: 3,
- img: {
- type: 1,
- url: '',
- w: 1,
- h: 1
- }
- },
- {
- id: 4,
- img: {
- type: 3,
- url: '//img.url',
- w: 1,
- h: 1
- }
- },
- {
- id: 5,
- data: {
- value: 'Test Onet',
- type: 1
- },
- },
- {
- id: 6,
- title: {
- text: 'Headline'
- }
- },
- ],
- link: {
- url: '//adclick.url//link.url',
- clicktrackers: ['//thirdPartyClickTracker.url']
- },
- eventtrackers: [
- {
- event: 1,
- method: 1,
- url: '//ems.url'
- },
- {
- event: 1,
- method: 1,
- url: '//imp.url'
- }
- ],
- privacy: '//dsa.url',
- };
- const expectedNativeInFeedResponse = {
- title: 'Headline',
- image: {
- url: '//img.url',
- width: 1,
- height: 1
- },
- icon: {
- url: '',
- width: 1,
- height: 1
- },
- clickUrl: '//adclick.url//link.url',
- cta: 'Calltoaction',
- body: 'BODY',
- body2: 'REKLAMA',
- sponsoredBy: 'Test Onet',
- ortb: expectedNativeInFeedOrtbResponse,
- privacyLink: '//dsa.url'
- };
-
- it('should get correct bid native response', function () {
- const resp = spec.interpretResponse({ body: response }, { bidIds: [{ slot: 'nativestd', bidId: 1, mediaType: 'native' }] });
-
- expect(resp[0]).to.have.all.keys('cpm', 'currency', 'netRevenue', 'requestId', 'ttl', 'width', 'height', 'creativeId', 'dealId', 'meta', 'actgMatch', 'mediaType', 'native');
- expect(resp.length).to.equal(1);
- });
-
- it('should get correct native response for TeaserStandard', function () {
- const resp = spec.interpretResponse({ body: responseTeaserStandard }, { bidIds: [{ slot: 'nativestd', bidId: 1, mediaType: 'native' }] });
- const teaserStandardResponse = resp[0].native;
-
- expect(JSON.stringify(teaserStandardResponse)).to.equal(JSON.stringify(expectedTeaserStandardResponse));
- });
-
- it('should get correct native response for NativeInFeed', function () {
- const resp = spec.interpretResponse({ body: responseNativeInFeed }, { bidIds: [{ slot: 'nativestd', bidId: 1, mediaType: 'native' }] });
- const nativeInFeedResponse = resp[0].native;
-
- expect(JSON.stringify(nativeInFeedResponse)).to.equal(JSON.stringify(expectedNativeInFeedResponse));
- });
+describe('ringieraxelspringer backward-compatibility shim', function () {
+ it('should re-export spec from dasBidAdapter', function () {
+ expect(spec).to.exist;
+ expect(spec.code).to.equal('das');
+ expect(spec.aliases).to.include('ringieraxelspringer');
});
});