Skip to content

Commit

Permalink
Adman Bid Adapter: add support for idx UserID(#8370)
Browse files Browse the repository at this point in the history
* Add Adman bid adapter

* Add supportedMediaTypes property

* Update ADman Media bidder adapter

* Remove console.log

* Fix typo

* revert package-json.lock

* Delete package-lock.json

* back to original package-lock.json

* catch pbjs error

* catch pbjs error

* catch pbjs error

* log

* remove eu url

* remove eu url

* remove eu url

* remove eu url

* remove eu url

* Update admanBidAdapter.js

add consnet to sync url

* Update admanBidAdapter.js

fix import

* Update admanBidAdapter.js

lint fix

* Update admanBidAdapter.js

lint fix

* Update admanBidAdapter.js

check consent object data availability

* сompatible with prebid v5

* add Lotame Panorama ID

* update getUserSyncs

* fix

* fix tests

* remove package-lock.json

* update sync url

* update test

* add idx (UserID Module)

* update tests

Co-authored-by: minoru katogi <[email protected]>
Co-authored-by: minoru katogi <[email protected]>
Co-authored-by: ADman Media <[email protected]>
Co-authored-by: SmartyAdman <[email protected]>
  • Loading branch information
5 people authored May 6, 2022
1 parent 8e903db commit 1a2ed86
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 38 deletions.
1 change: 1 addition & 0 deletions modules/admanBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export const spec = {
if (bid.userId) {
getUserId(placement.eids, bid.userId.uid2 && bid.userId.uid2.id, 'uidapi.com');
getUserId(placement.eids, bid.userId.lotamePanoramaId, 'lotame.com');
getUserId(placement.eids, bid.userId.idx, 'idx.lat');
}
if (traff === VIDEO) {
placement.playerSize = bid.mediaTypes[VIDEO].playerSize;
Expand Down
227 changes: 189 additions & 38 deletions test/spec/modules/admanBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {expect} from 'chai';
import {spec} from '../../../modules/admanBidAdapter.js';
import {deepClone} from '../../../src/utils'

describe('AdmanAdapter', function () {
let bid = {
let bidBanner = {
bidId: '2dd581a2b6281d',
bidder: 'adman',
bidderRequestId: '145e1d6a7837c9',
Expand Down Expand Up @@ -32,6 +33,20 @@ describe('AdmanAdapter', function () {
]
}
};

let bidVideo = deepClone({
...bidBanner,
params: {
placementId: 0,
traffic: 'video'
},
mediaTypes: {
video: {
playerSize: [300, 250]
}
}
});

let bidderRequest = {
bidderCode: 'adman',
auctionId: 'fffffff-ffff-ffff-ffff-ffffffffffff',
Expand All @@ -40,25 +55,27 @@ describe('AdmanAdapter', function () {
auctionStart: 1472239426000,
timeout: 5000,
uspConsent: '1YN-',
gdprConsent: 'gdprConsent',
refererInfo: {
referer: 'http://www.example.com',
reachedTop: true,
},
bids: [bid]
bids: [bidBanner, bidVideo]
}

describe('isBidRequestValid', function () {
it('Should return true when placementId can be cast to a number', function () {
expect(spec.isBidRequestValid(bid)).to.be.true;
expect(spec.isBidRequestValid(bidBanner)).to.be.true;
});
it('Should return false when placementId is not a number', function () {
bid.params.placementId = 'aaa';
expect(spec.isBidRequestValid(bid)).to.be.false;
bidBanner.params.placementId = 'aaa';
expect(spec.isBidRequestValid(bidBanner)).to.be.false;
bidBanner.params.placementId = 0;
});
});

describe('buildRequests', function () {
let serverRequest = spec.buildRequests([bid], bidderRequest);
let serverRequest = spec.buildRequests([bidBanner], bidderRequest);
it('Creates a ServerRequest object with method, URL and data', function () {
expect(serverRequest).to.exist;
expect(serverRequest.method).to.exist;
Expand All @@ -75,10 +92,11 @@ describe('AdmanAdapter', function () {
expect(serverRequest.data.ccpa).to.be.an('string')
})

it('Returns valid data if array of bids is valid', function () {
it('Returns valid BANNER data if array of bids is valid', function () {
serverRequest = spec.buildRequests([bidBanner], bidderRequest);
let data = serverRequest.data;
expect(data).to.be.an('object');
expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'ccpa');
expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'ccpa', 'gdpr');
expect(data.deviceWidth).to.be.a('number');
expect(data.deviceHeight).to.be.a('number');
expect(data.language).to.be.a('string');
Expand All @@ -97,6 +115,33 @@ describe('AdmanAdapter', function () {
expect(placement.bidFloor).to.be.an('number');
}
});

it('Returns valid VIDEO data if array of bids is valid', function () {
serverRequest = spec.buildRequests([bidVideo], bidderRequest);
let data = serverRequest.data;
expect(data).to.be.an('object');
expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements', 'ccpa', 'gdpr');
expect(data.deviceWidth).to.be.a('number');
expect(data.deviceHeight).to.be.a('number');
expect(data.language).to.be.a('string');
expect(data.secure).to.be.within(0, 1);
expect(data.host).to.be.a('string');
expect(data.page).to.be.a('string');
let placements = data['placements'];
for (let i = 0; i < placements.length; i++) {
let placement = placements[i];
expect(placement).to.have.all.keys('placementId', 'eids', 'bidId', 'traffic', 'sizes', 'schain', 'bidFloor',
'playerSize', 'minduration', 'maxduration', 'mimes', 'protocols', 'startdelay', 'placement', 'skip',
'skipafter', 'minbitrate', 'maxbitrate', 'delivery', 'playbackmethod', 'api', 'linearity');
expect(placement.schain).to.be.an('object')
expect(placement.placementId).to.be.a('number');
expect(placement.bidId).to.be.a('string');
expect(placement.traffic).to.be.a('string');
expect(placement.sizes).to.be.an('array');
expect(placement.bidFloor).to.be.an('number');
}
});

it('Returns empty data if no valid requests are passed', function () {
serverRequest = spec.buildRequests([]);
let data = serverRequest.data;
Expand All @@ -105,9 +150,9 @@ describe('AdmanAdapter', function () {
});

describe('buildRequests with user ids', function () {
bid.userId = {}
bid.userId.uid2 = { id: 'uid2id123' };
let serverRequest = spec.buildRequests([bid], bidderRequest);
bidBanner.userId = {}
bidBanner.userId.uid2 = { id: 'uid2id123' };
let serverRequest = spec.buildRequests([bidBanner], bidderRequest);
it('Returns valid data if array of bids is valid', function () {
let data = serverRequest.data;
let placements = data['placements'];
Expand All @@ -130,31 +175,34 @@ describe('AdmanAdapter', function () {
});

describe('interpretResponse', function () {
let resObject = {
body: [ {
requestId: '123',
mediaType: 'banner',
cpm: 0.3,
width: 320,
height: 50,
ad: '<h1>Hello ad</h1>',
ttl: 1000,
creativeId: '123asd',
netRevenue: true,
currency: 'USD',
meta: {
advertiserDomains: ['google.com'],
advertiserId: 1234
}
} ]
};
let serverResponses = spec.interpretResponse(resObject);
it('Returns an array of valid server responses if response object is valid', function () {
it('(BANNER) Returns an array of valid server responses if response object is valid', function () {
const resBannerObject = {
body: [ {
requestId: '123',
mediaType: 'banner',
cpm: 0.3,
width: 320,
height: 50,
ad: '<h1>Hello ad</h1>',
ttl: 1000,
creativeId: '123asd',
netRevenue: true,
currency: 'USD',
adomain: ['example.com'],
meta: {
advertiserDomains: ['google.com'],
advertiserId: 1234
}
} ]
};

const serverResponses = spec.interpretResponse(resBannerObject);

expect(serverResponses).to.be.an('array').that.is.not.empty;
for (let i = 0; i < serverResponses.length; i++) {
let dataItem = serverResponses[i];
expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId',
'netRevenue', 'currency', 'mediaType', 'meta');
'netRevenue', 'currency', 'mediaType', 'meta', 'adomain');
expect(dataItem.requestId).to.be.a('string');
expect(dataItem.cpm).to.be.a('number');
expect(dataItem.width).to.be.a('number');
Expand All @@ -167,21 +215,124 @@ describe('AdmanAdapter', function () {
expect(dataItem.mediaType).to.be.a('string');
expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains');
}
it('Returns an empty array if invalid response is passed', function () {
serverResponses = spec.interpretResponse('invalid_response');
expect(serverResponses).to.be.an('array').that.is.empty;
});
});

it('(VIDEO) Returns an array of valid server responses if response object is valid', function () {
const resVideoObject = {
body: [ {
requestId: '123',
mediaType: 'video',
cpm: 0.3,
width: 320,
height: 50,
vastUrl: 'https://',
ttl: 1000,
creativeId: '123asd',
netRevenue: true,
currency: 'USD',
adomain: ['example.com'],
meta: {
advertiserDomains: ['google.com'],
advertiserId: 1234
}
} ]
};

const serverResponses = spec.interpretResponse(resVideoObject);

expect(serverResponses).to.be.an('array').that.is.not.empty;
for (let i = 0; i < serverResponses.length; i++) {
let dataItem = serverResponses[i];
expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'vastUrl', 'ttl', 'creativeId',
'netRevenue', 'currency', 'mediaType', 'meta', 'adomain');
expect(dataItem.requestId).to.be.a('string');
expect(dataItem.cpm).to.be.a('number');
expect(dataItem.width).to.be.a('number');
expect(dataItem.height).to.be.a('number');
expect(dataItem.vastUrl).to.be.a('string');
expect(dataItem.ttl).to.be.a('number');
expect(dataItem.creativeId).to.be.a('string');
expect(dataItem.netRevenue).to.be.a('boolean');
expect(dataItem.currency).to.be.a('string');
expect(dataItem.mediaType).to.be.a('string');
expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains');
}
});

it('(NATIVE) Returns an array of valid server responses if response object is valid', function () {
const resNativeObject = {
body: [ {
requestId: '123',
mediaType: 'native',
cpm: 0.3,
width: 320,
height: 50,
native: {
title: 'title',
image: 'image',
impressionTrackers: [ 'https://' ]
},
ttl: 1000,
creativeId: '123asd',
netRevenue: true,
currency: 'USD',
adomain: ['example.com'],
meta: {
advertiserDomains: ['google.com'],
advertiserId: 1234
}
} ]
};

const serverResponses = spec.interpretResponse(resNativeObject);

expect(serverResponses).to.be.an('array').that.is.not.empty;
for (let i = 0; i < serverResponses.length; i++) {
let dataItem = serverResponses[i];
expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'native', 'ttl', 'creativeId',
'netRevenue', 'currency', 'mediaType', 'meta', 'adomain');
expect(dataItem.requestId).to.be.a('string');
expect(dataItem.cpm).to.be.a('number');
expect(dataItem.width).to.be.a('number');
expect(dataItem.height).to.be.a('number');
expect(dataItem.native).to.be.an('object');
expect(dataItem.ttl).to.be.a('number');
expect(dataItem.creativeId).to.be.a('string');
expect(dataItem.netRevenue).to.be.a('boolean');
expect(dataItem.currency).to.be.a('string');
expect(dataItem.mediaType).to.be.a('string');
expect(dataItem.meta).to.be.an('object').that.has.any.key('advertiserDomains');
}
});

it('Invalid mediaType in response', function () {
const resBadObject = {
body: [ {
mediaType: 'other',
requestId: '123',
cpm: 0.3,
ttl: 1000,
creativeId: '123asd',
currency: 'USD'
} ]
};

const serverResponses = spec.interpretResponse(resBadObject);

expect(serverResponses).to.be.an('array').that.is.empty;
});
});

describe('getUserSyncs', function () {
let userSync = spec.getUserSyncs({});
const gdprConsent = { consentString: 'consentString', gdprApplies: 1 };
const consentString = { consentString: 'consentString' }
let userSync = spec.getUserSyncs({}, {}, gdprConsent, consentString);
it('Returns valid URL and type', function () {
expect(userSync).to.be.an('array').with.lengthOf(1);
expect(userSync[0].type).to.exist;
expect(userSync[0].url).to.exist;
expect(userSync[0].type).to.be.equal('image');
expect(userSync[0].url).to.be.equal('https://sync.admanmedia.com/image?pbjs=1&coppa=0');
expect(userSync[0].url).to.be.equal('https://sync.admanmedia.com/image?pbjs=1&gdpr=0&gdpr_consent=consentString&ccpa_consent=consentString&coppa=0');
});
});
});

0 comments on commit 1a2ed86

Please sign in to comment.