diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js
index 6f7feec59c9..892411837dd 100644
--- a/modules/adagioBidAdapter.js
+++ b/modules/adagioBidAdapter.js
@@ -8,16 +8,16 @@ import sha256 from 'crypto-js/sha256.js';
import { getStorageManager } from '../src/storageManager.js';
import { getRefererInfo } from '../src/refererDetection.js';
import { createEidsArray } from './userId/eids.js';
-import { BANNER, VIDEO } from '../src/mediaTypes.js';
+import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
import { Renderer } from '../src/Renderer.js';
import { OUTSTREAM } from '../src/video.js';
export const BIDDER_CODE = 'adagio';
export const LOG_PREFIX = 'Adagio:';
-export const VERSION = '2.6.0';
+export const VERSION = '2.7.0';
export const FEATURES_VERSION = '1';
export const ENDPOINT = 'https://mp.4dex.io/prebid';
-export const SUPPORTED_MEDIA_TYPES = [BANNER, VIDEO];
+export const SUPPORTED_MEDIA_TYPES = [BANNER, NATIVE, VIDEO];
export const ADAGIO_TAG_URL = 'https://script.4dex.io/localstore.js';
export const ADAGIO_LOCALSTORAGE_KEY = 'adagioScript';
export const GVLID = 617;
@@ -687,6 +687,112 @@ function _renderer(bid) {
});
}
+function _parseNativeBidResponse(bid) {
+ if (!bid.admNative || !Array.isArray(bid.admNative.assets)) {
+ utils.logError(`${LOG_PREFIX} Invalid native response`);
+ return;
+ }
+
+ const native = {}
+
+ function addAssetDataValue(data) {
+ const map = {
+ 1: 'sponsoredBy', // sponsored
+ 2: 'body', // desc
+ 3: 'rating',
+ 4: 'likes',
+ 5: 'downloads',
+ 6: 'price',
+ 7: 'salePrice',
+ 8: 'phone',
+ 9: 'address',
+ 10: 'body2', // desc2
+ 11: 'displayUrl',
+ 12: 'cta'
+ }
+ if (map.hasOwnProperty(data.type) && typeof data.value === 'string') {
+ native[map[data.type]] = data.value;
+ }
+ }
+
+ // assets
+ bid.admNative.assets.forEach(asset => {
+ if (asset.title) {
+ native.title = asset.title.text
+ } else if (asset.data) {
+ addAssetDataValue(asset.data)
+ } else if (asset.img) {
+ switch (asset.img.type) {
+ case 1:
+ native.icon = {
+ url: asset.img.url,
+ width: asset.img.w,
+ height: asset.img.h
+ };
+ break;
+ default:
+ native.image = {
+ url: asset.img.url,
+ width: asset.img.w,
+ height: asset.img.h
+ };
+ break;
+ }
+ }
+ });
+
+ if (bid.admNative.link) {
+ if (bid.admNative.link.url) {
+ native.clickUrl = bid.admNative.link.url;
+ }
+ if (Array.isArray(bid.admNative.link.clickTrackers)) {
+ native.clickTrackers = bid.admNative.link.clickTrackers
+ }
+ }
+
+ if (Array.isArray(bid.admNative.eventtrackers)) {
+ native.impressionTrackers = [];
+ bid.admNative.eventtrackers.forEach(tracker => {
+ // Only Impression events are supported. Prebid does not support Viewability events yet.
+ if (tracker.event !== 1) {
+ return;
+ }
+
+ // methods:
+ // 1: image
+ // 2: js
+ // note: javascriptTrackers is a string. If there's more than one JS tracker in bid response, the last script will be used.
+ switch (tracker.method) {
+ case 1:
+ native.impressionTrackers.push(tracker.url);
+ break;
+ case 2:
+ native.javascriptTrackers = ``;
+ break;
+ }
+ });
+ } else {
+ native.impressionTrackers = Array.isArray(bid.admNative.imptrackers) ? bid.admNative.imptrackers : [];
+ if (bid.admNative.jstracker) {
+ native.javascriptTrackers = bid.admNative.jstracker;
+ }
+ }
+
+ if (bid.admNative.privacy) {
+ native.privacyLink = bid.admNative.privacy;
+ }
+
+ if (bid.admNative.ext) {
+ native.ext = {}
+
+ if (bid.admNative.ext.bvw) {
+ native.ext.adagio_bvw = bid.admNative.ext.bvw;
+ }
+ }
+
+ bid.native = native
+}
+
export const spec = {
code: BIDDER_CODE,
gvlid: GVLID,
@@ -873,6 +979,10 @@ export const spec = {
}
}
+ if (bidObj.mediaType === NATIVE) {
+ _parseNativeBidResponse(bidObj);
+ }
+
bidObj.site = bidReq.params.site;
bidObj.placement = bidReq.params.placement;
bidObj.pagetype = bidReq.params.pagetype;
diff --git a/modules/adagioBidAdapter.md b/modules/adagioBidAdapter.md
index aa79338d79e..46656d88d37 100644
--- a/modules/adagioBidAdapter.md
+++ b/modules/adagioBidAdapter.md
@@ -38,8 +38,8 @@ Connects to Adagio demand source to fetch bids.
category: 'sport', // Recommended. Category of the content displayed in the page.
subcategory: 'handball', // Optional. Subcategory of the content displayed in the page.
postBid: false, // Optional. Use it in case of Post-bid integration only.
- useAdUnitCodeAsAdUnitElementId: false // Optional. Use it by-pass adUnitElementId and use the adUnit code as value
- useAdUnitCodeAsPlacement: false // Optional. Use it to by-pass placement and use the adUnit code as value
+ useAdUnitCodeAsAdUnitElementId: false, // Optional. Use it by-pass adUnitElementId and use the adUnit code as value
+ useAdUnitCodeAsPlacement: false, // Optional. Use it to by-pass placement and use the adUnit code as value
// Optional debug mode, used to get a bid response with expected cpm.
debug: {
enabled: true,
@@ -78,8 +78,8 @@ Connects to Adagio demand source to fetch bids.
category: 'sport', // Recommended. Category of the content displayed in the page.
subcategory: 'handball', // Optional. Subcategory of the content displayed in the page.
postBid: false, // Optional. Use it in case of Post-bid integration only.
- useAdUnitCodeAsAdUnitElementId: false // Optional. Use it by-pass adUnitElementId and use the adUnit code as value
- useAdUnitCodeAsPlacement: false // Optional. Use it to by-pass placement and use the adUnit code as value
+ useAdUnitCodeAsAdUnitElementId: false, // Optional. Use it by-pass adUnitElementId and use the adUnit code as value
+ useAdUnitCodeAsPlacement: false, // Optional. Use it to by-pass placement and use the adUnit code as value
video: {
skip: 0
// OpenRTB 2.5 video options defined here override ones defined in mediaTypes.
@@ -91,6 +91,58 @@ Connects to Adagio demand source to fetch bids.
}
}
}]
+ },
+ {
+ code: 'article_native',
+ mediaTypes: {
+ native: {
+ // generic Prebid options
+ title: {
+ required: true,
+ len: 80
+ },
+ // …
+ // Custom Adagio data assets
+ ext: {
+ adagio_bvw: {
+ required: false
+ }
+ }
+ }
+ },
+ bids: [{
+ bidder: 'adagio', // Required
+ params: {
+ organizationId: '1002', // Required - Organization ID provided by Adagio.
+ site: 'adagio-io', // Required - Site Name provided by Adagio.
+ placement: 'in_article', // Required. Refers to the placement of an adunit in a page. Must not contain any information about the type of device. Other example: `mpu_btf'.
+ adUnitElementId: 'article_native', // Required - AdUnit element id. Refers to the adunit id in a page. Usually equals to the adunit code above.
+
+ // The following params are limited to 30 characters,
+ // and can only contain the following characters:
+ // - alphanumeric (A-Z+a-z+0-9, case-insensitive)
+ // - dashes `-`
+ // - underscores `_`
+ // Also, each param can have at most 50 unique active values (case-insensitive).
+ pagetype: 'article', // Highly recommended. The pagetype describes what kind of content will be present in the page.
+ environment: 'mobile', // Recommended. Environment where the page is displayed.
+ category: 'sport', // Recommended. Category of the content displayed in the page.
+ subcategory: 'handball', // Optional. Subcategory of the content displayed in the page.
+ postBid: false, // Optional. Use it in case of Post-bid integration only.
+ useAdUnitCodeAsAdUnitElementId: false, // Optional. Use it by-pass adUnitElementId and use the adUnit code as value
+ useAdUnitCodeAsPlacement: false, // Optional. Use it to by-pass placement and use the adUnit code as value
+ // Optional OpenRTB Native 1.2 request object. Only `context`, `plcmttype` fields are supported.
+ native: {
+ context: 1,
+ plcmttype: 2
+ },
+ // Optional debug mode, used to get a bid response with expected cpm.
+ debug: {
+ enabled: true,
+ cpm: 3.00 // default to 1.00
+ }
+ }
+ }]
}
];
diff --git a/test/spec/modules/adagioBidAdapter_spec.js b/test/spec/modules/adagioBidAdapter_spec.js
index 0a585caaa1a..999773f1a1f 100644
--- a/test/spec/modules/adagioBidAdapter_spec.js
+++ b/test/spec/modules/adagioBidAdapter_spec.js
@@ -1,5 +1,5 @@
import find from 'core-js-pure/features/array/find.js';
-import { expect } from 'chai';
+import { expect, util } from 'chai';
import {
_features,
internal as adagio,
@@ -13,7 +13,8 @@ import {
} from '../../../modules/adagioBidAdapter.js';
import { loadExternalScript } from '../../../src/adloader.js';
import * as utils from '../../../src/utils.js';
-import { config } from 'src/config.js';
+import { config } from '../../../src/config.js';
+import { NATIVE } from '../../../src/mediaTypes.js';
const BidRequestBuilder = function BidRequestBuilder(options) {
const defaults = {
@@ -879,6 +880,174 @@ describe('Adagio bid adapter', () => {
expect(bidResponse.vastUrl).to.match(/^data:text\/xml;/)
});
});
+
+ describe('Response with native add', () => {
+ const serverResponseWithNative = utils.deepClone(serverResponse)
+ serverResponseWithNative.body.bids[0].mediaType = 'native';
+ serverResponseWithNative.body.bids[0].admNative = {
+ ver: '1.2',
+ link: {
+ url: 'https://i.am.a.click.url',
+ clickTrackers: [
+ 'https://i.am.a.clicktracker.url'
+ ]
+ },
+ privacy: 'http://www.myprivacyurl.url',
+ ext: {
+ bvw: 'test'
+ },
+ eventtrackers: [
+ {
+ event: 1,
+ method: 1,
+ url: 'https://eventrack.local/impression'
+ },
+ {
+ event: 1,
+ method: 2,
+ url: 'https://eventrack.local/impression'
+ },
+ {
+ event: 2,
+ method: 1,
+ url: 'https://eventrack.local/viewable-mrc50'
+ }
+ ],
+ assets: [
+ {
+ required: 1,
+ title: {
+ text: 'My title'
+ }
+ },
+ {
+ img: {
+ url: 'https://images.local/image.jpg',
+ w: 100,
+ h: 250
+ }
+ },
+ {
+ img: {
+ type: 1,
+ url: 'https://images.local/icon.png',
+ w: 40,
+ h: 40
+ }
+ },
+ {
+ data: {
+ type: 1, // sponsored
+ value: 'Adagio'
+ }
+ },
+ {
+ data: {
+ type: 2, // desc / body
+ value: 'The super ad text'
+ }
+ },
+ {
+ data: {
+ type: 3, // rating
+ value: '10 from 10'
+ }
+ },
+ {
+ data: {
+ type: 11, // displayUrl
+ value: 'https://i.am.a.display.url'
+ }
+ }
+ ]
+ };
+
+ const bidRequestNative = utils.deepClone(bidRequest)
+ bidRequestNative.mediaTypes = {
+ native: {
+ sendTargetingKeys: false,
+
+ clickUrl: {
+ required: true,
+ },
+ title: {
+ required: true,
+ },
+ body: {
+ required: true,
+ },
+ sponsoredBy: {
+ required: false
+ },
+ image: {
+ required: true
+ },
+ icon: {
+ required: true
+ },
+ privacyLink: {
+ required: false
+ },
+ ext: {
+ adagio_bvw: {}
+ }
+ }
+ };
+
+ it('Should ignore native parsing due to missing raw admNative property', () => {
+ const alternateServerResponse = utils.deepClone(serverResponseWithNative);
+ delete alternateServerResponse.body.bids[0].admNative
+ const r = spec.interpretResponse(alternateServerResponse, bidRequestNative);
+ expect(r[0].mediaType).to.equal(NATIVE);
+ expect(r[0].native).not.ok;
+ utilsMock.expects('logError').once();
+ });
+
+ it('Should ignore native parsing due to invalid raw admNative.assets property', () => {
+ const alternateServerResponse = utils.deepClone(serverResponseWithNative);
+ alternateServerResponse.body.bids[0].admNative.assets = { title: { text: 'test' } };
+ const r = spec.interpretResponse(alternateServerResponse, bidRequestNative);
+ expect(r[0].mediaType).to.equal(NATIVE);
+ expect(r[0].native).not.ok;
+ utilsMock.expects('logError').once();
+ });
+
+ it('Should handle and return a formated Native ad', () => {
+ const r = spec.interpretResponse(serverResponseWithNative, bidRequestNative);
+ const expected = {
+ displayUrl: 'https://i.am.a.display.url',
+ sponsoredBy: 'Adagio',
+ body: 'The super ad text',
+ rating: '10 from 10',
+ clickUrl: 'https://i.am.a.click.url',
+ title: 'My title',
+ impressionTrackers: [
+ 'https://eventrack.local/impression'
+ ],
+ javascriptTrackers: '',
+ clickTrackers: [
+ 'https://i.am.a.clicktracker.url'
+ ],
+ image: {
+ url: 'https://images.local/image.jpg',
+ width: 100,
+ height: 250
+ },
+ icon: {
+ url: 'https://images.local/icon.png',
+ width: 40,
+ height: 40
+ },
+ ext: {
+ adagio_bvw: 'test'
+ },
+ privacyLink: 'http://www.myprivacyurl.url'
+ }
+ expect(r[0].mediaType).to.equal(NATIVE);
+ expect(r[0].native).ok;
+ expect(r[0].native).to.deep.equal(expected);
+ });
+ });
});
describe('getUserSyncs()', function() {