Skip to content

Commit

Permalink
Ventes Bid Adapter: fix web placement support (#7715)
Browse files Browse the repository at this point in the history
* Ventes Avenues initial changes

* Ventes Avenues initial changes

* Support Web Placments

* Support Web Placements

* Support Web Placements

* Support Web Placements

* Support Web Placements

* Support Web Placements
  • Loading branch information
jessoventes authored Nov 17, 2021
1 parent 05f25c3 commit 76a5864
Show file tree
Hide file tree
Showing 3 changed files with 175 additions and 65 deletions.
71 changes: 71 additions & 0 deletions modules/ventes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
layout: bidder
title: ventes
description: Prebid ventes Bidder Adapter
pbjs: false
biddercode: ventes
gdpr_supported: false
usp_supported: false
media_types: banner
coppa_supported: false
schain_supported: false
dchain_supported: false
prebid_member: false
---

### BidParams
{: .table .table-bordered .table-striped }
| Name | Scope | Description | Example | Type |
|-----------------|----------|-----------------------------------------------------------|----------------------------------------------|---------------|
| `placementId` | required | Placement ID from Ventes Avenues | `'VA-062-0013-0183'` | `string` |
| `publisherId` | required | Publisher ID from Ventes Avenues | `'VA-062'` | `string` |
| `user` | optional | Object that specifies information about an external user. | `user: { age: 25, gender: 0, dnt: true}` | `object` |
| `app` | optional | Object containing mobile app parameters. | `app : { id: 'app-id'}` | `object` |

#### User Object

{: .table .table-bordered .table-striped }
| Name | Description | Example | Type |
|-------------------|-------------------------------------------------------------------------------------------|-----------------------|-----------------------|
| `age` | The age of the user. | `35` | `integer` |
| `externalUid` | Specifies a string that corresponds to an external user ID for this user. | `'1234567890abcdefg'` | `string` |
| `segments` | Specifies the segments to which the user belongs. | `[1, 2]` | `Array<integer>` |
| `gender` | Specifies the gender of the user. Allowed values: Unknown: `0`; Male: `1`; Female: `2` | `1` | `integer` |
| `dnt` | Do not track flag. Indicates if tracking cookies should be disabled for this auction | `true` | `boolean` |
| `language` | Two-letter ANSI code for this user's language. | `EN` | `string` |


### Ad Unit Setup for Banner
```javascript
var adUnits = [
{
code: 'test-hb-ad-11111-1',
mediaTypes: {
banner: {
sizes: [
[300, 250]
]
}
},
bids: [{
bidder: 'ventes',
params: {
placementId: 'VA-062-0013-0183',
publisherId: '5cebea3c9eea646c7b623d5e',
IABCategories: "['IAB1', 'IAB5']",
device:{
ip: '123.145.167.189',
ifa:"AEBE52E7-03EE-455A-B3C4-E57283966239",
},
app: {
id: "agltb3B1Yi1pbmNyDAsSA0FwcBiJkfIUDA",
name: "Yahoo Weather",
bundle: 'com.kiloo.subwaysurf',
storeurl: 'https://play.google.com/store/apps/details?id=com.kiloo.subwaysurf&hl=en',
domain: 'somoaudience.com',
}
}
}]
}
]
```
168 changes: 104 additions & 64 deletions modules/ventesBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js';
import {convertCamelToUnderscore, isStr, isArray, isNumber, isPlainObject, replaceAuctionPrice} from '../src/utils.js';
import {
BANNER,
NATIVE,
VIDEO
} from '../src/mediaTypes.js';
import {
convertCamelToUnderscore,
isStr,
isArray,
isNumber,
isPlainObject,
replaceAuctionPrice
} from '../src/utils.js';
import find from 'core-js-pure/features/array/find.js';
import includes from 'core-js-pure/features/array/includes.js';
import {
registerBidder
} from '../src/adapters/bidderFactory.js';

const BID_METHOD = 'POST';
const BIDDER_URL = 'http://13.234.201.146:8088/va/ad';
const FIRST_PRICE = 1;
const NET_REVENUE = true;
const TTL = 10;
const USER_PARAMS = ['age', 'externalUid', 'segments', 'gender', 'dnt', 'language'];
const DEVICE_PARAMS = ['ua', 'geo', 'dnt', 'lmt', 'ip', 'ipv6', 'devicetype'];
const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately

const DOMAIN_REGEX = new RegExp('//([^/]*)');

function groupBy(values, key) {
Expand All @@ -26,7 +33,11 @@ function groupBy(values, key) {

return Object
.keys(groups)
.map(id => ({id, key, values: groups[id]}));
.map(id => ({
id,
key,
values: groups[id]
}));
}

function validateMediaTypes(mediaTypes, allowedMediaTypes) {
Expand All @@ -45,22 +56,22 @@ function isBanner(mediaTypes) {

function validateBanner(banner) {
return isPlainObject(banner) &&
isArray(banner.sizes) &&
(banner.sizes.length > 0) &&
banner.sizes.every(validateMediaSizes);
isArray(banner.sizes) &&
(banner.sizes.length > 0) &&
banner.sizes.every(validateMediaSizes);
}

function validateMediaSizes(mediaSize) {
return isArray(mediaSize) &&
(mediaSize.length === 2) &&
mediaSize.every(size => (isNumber(size) && size >= 0));
(mediaSize.length === 2) &&
mediaSize.every(size => (isNumber(size) && size >= 0));
}

function hasUserInfo(bid) {
return !!bid.params.user;
}

function validateParameters(parameters, adUnit) {
function validateParameters(parameters) {
if (!(parameters.placementId)) {
return false;
}
Expand Down Expand Up @@ -101,8 +112,8 @@ function generateSiteFromAdUnitContext(bidRequests, adUnitContext) {

function validateServerRequest(serverRequest) {
return isPlainObject(serverRequest) &&
isPlainObject(serverRequest.data) &&
isArray(serverRequest.data.imp)
isPlainObject(serverRequest.data) &&
isArray(serverRequest.data.imp)
}

function createServerRequestFromAdUnits(adUnits, bidRequestId, adUnitContext) {
Expand All @@ -122,14 +133,15 @@ function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext
let userObj = {};
if (userObjBid) {
Object.keys(userObjBid.params.user)
.filter(param => includes(USER_PARAMS, param))
.forEach((param) => {
let uparam = convertCamelToUnderscore(param);
if (param === 'segments' && isArray(userObjBid.params.user[param])) {
let segs = [];
userObjBid.params.user[param].forEach(val => {
if (isNumber(val)) {
segs.push({'id': val});
segs.push({
'id': val
});
} else if (isPlainObject(val)) {
segs.push(val);
}
Expand All @@ -146,7 +158,6 @@ function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext
if (deviceObjBid && deviceObjBid.params && deviceObjBid.params.device) {
deviceObj = {};
Object.keys(deviceObjBid.params.device)
.filter(param => includes(DEVICE_PARAMS, param))
.forEach(param => deviceObj[param] = deviceObjBid.params.device[param]);
if (!deviceObjBid.hasOwnProperty('ua')) {
deviceObj.ua = navigator.userAgent;
Expand All @@ -159,37 +170,41 @@ function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext
deviceObj.ua = navigator.userAgent;
deviceObj.language = navigator.language;
}
const appDeviceObjBid = find(bidRequests, hasAppInfo);
let appIdObj;
if (appDeviceObjBid && appDeviceObjBid.params && appDeviceObjBid.params.app && appDeviceObjBid.params.app.id) {
Object.keys(appDeviceObjBid.params.app)
.filter(param => includes(APP_DEVICE_PARAMS, param))
.forEach(param => appDeviceObjBid[param] = appDeviceObjBid.params.app[param]);
}

const payload = {}
payload.id = bidRequestId
payload.at = FIRST_PRICE
payload.at = 1
payload.cur = ['USD']
payload.imp = bidRequests.reduce(generateImpressionsFromAdUnit, [])
payload.site = generateSiteFromAdUnitContext(bidRequests, adUnitContext)
payload.device = deviceObj
if (appDeviceObjBid && payload.site != null) {
const appDeviceObjBid = find(bidRequests, hasAppInfo);
if (!appDeviceObjBid) {
payload.site = generateSiteFromAdUnitContext(bidRequests, adUnitContext)
} else {
let appIdObj;
if (appDeviceObjBid && appDeviceObjBid.params && appDeviceObjBid.params.app && appDeviceObjBid.params.app.id) {
appIdObj = {};
Object.keys(appDeviceObjBid.params.app)
.forEach(param => appIdObj[param] = appDeviceObjBid.params.app[param]);
}
payload.app = appIdObj;
}
payload.device = deviceObj;
payload.user = userObj
// payload.regs = getRegulationFromAdUnitContext(adUnitContext)
// payload.ext = generateBidRequestExtension()

return payload
}

function generateImpressionsFromAdUnit(acc, adUnit) {
const {bidId, mediaTypes, params} = adUnit;
const {placementId} = params;
const {
bidId,
mediaTypes,
params
} = adUnit;
const {
placementId
} = params;
const pmp = {};

if (placementId) pmp.deals = [{id: placementId}]
if (placementId) pmp.deals = [{ id: placementId }]

const imps = Object
.keys(mediaTypes)
Expand All @@ -204,21 +219,40 @@ function generateImpressionsFromAdUnit(acc, adUnit) {
}

function generateBannerFromAdUnit(impId, data, params) {
const {position, placementId} = params;
const {
position,
placementId
} = params;
const pos = position || 0;
const pmp = {};
const ext = {placementId};

if (placementId) pmp.deals = [{id: placementId}]
const ext = {
placementId
};

return data.sizes.map(([w, h]) => ({id: `${impId}`, banner: {format: [{w, h}], w, h, pos}, pmp, ext, tagid: placementId}));
if (placementId) pmp.deals = [{ id: placementId }]

return data.sizes.map(([w, h]) => ({
id: `${impId}`,
banner: {
format: [{
w,
h
}],
w,
h,
pos
},
pmp,
ext,
tagid: placementId
}));
}

function validateServerResponse(serverResponse) {
return isPlainObject(serverResponse) &&
isPlainObject(serverResponse.body) &&
isStr(serverResponse.body.cur) &&
isArray(serverResponse.body.seatbid);
isPlainObject(serverResponse.body) &&
isStr(serverResponse.body.cur) &&
isArray(serverResponse.body.seatbid);
}

function seatBidsToAds(seatBid, bidResponse, serverRequest) {
Expand All @@ -241,10 +275,8 @@ function validateBids(bid) {
return true;
}

const VAST_REGEXP = /VAST\s+version/;

function getMediaType(adm) {
const videoRegex = new RegExp(VAST_REGEXP);
const videoRegex = new RegExp(/VAST\s+version/);

if (videoRegex.test(adm)) {
return VIDEO;
Expand Down Expand Up @@ -273,14 +305,16 @@ function generateAdFromBid(bid, bidResponse) {
requestId: bid.impid,
cpm: bid.price,
currency: bidResponse.cur,
ttl: TTL,
ttl: 10,
creativeId: bid.crid,
mediaType: mediaType,
netRevenue: NET_REVENUE
netRevenue: true
};

if (bid.adomain) {
base.meta = { advertiserDomains: bid.adomain };
base.meta = {
advertiserDomains: bid.adomain
};
}

const size = getSizeFromBid(bid);
Expand All @@ -292,17 +326,21 @@ function generateAdFromBid(bid, bidResponse) {
width: size.width,
ad: creative.markup,
adUrl: creative.markupUrl,
// vastXml: isVideo && !isStr(creative.markupUrl) ? creative.markup : null,
// vastUrl: isVideo && isStr(creative.markupUrl) ? creative.markupUrl : null,
renderer: creative.renderer
};
}

function getSizeFromBid(bid) {
if (isNumber(bid.w) && isNumber(bid.h)) {
return { width: bid.w, height: bid.h };
return {
width: bid.w,
height: bid.h
};
}
return { width: null, height: null };
return {
width: null,
height: null
};
}

function getCreativeFromBid(bid) {
Expand Down Expand Up @@ -333,12 +371,12 @@ const venavenBidderSpec = {
const allowedBidderCodes = [this.code];

return isPlainObject(adUnit) &&
allowedBidderCodes.indexOf(adUnit.bidder) !== -1 &&
isStr(adUnit.adUnitCode) &&
isStr(adUnit.bidderRequestId) &&
isStr(adUnit.bidId) &&
validateMediaTypes(adUnit.mediaTypes, this.supportedMediaTypes) &&
validateParameters(adUnit.params, adUnit);
allowedBidderCodes.indexOf(adUnit.bidder) !== -1 &&
isStr(adUnit.adUnitCode) &&
isStr(adUnit.bidderRequestId) &&
isStr(adUnit.bidId) &&
validateMediaTypes(adUnit.mediaTypes, this.supportedMediaTypes) &&
validateParameters(adUnit.params);
},
buildRequests(bidRequests, bidderRequest) {
if (!bidRequests) return null;
Expand Down Expand Up @@ -367,4 +405,6 @@ const venavenBidderSpec = {

registerBidder(venavenBidderSpec);

export {venavenBidderSpec as spec};
export {
venavenBidderSpec as spec
};
1 change: 0 additions & 1 deletion modules/ventesBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ var adUnits = [
publisherId: '5cebea3c9eea646c7b623d5e',
IABCategories: "['IAB1', 'IAB5']",
device:{
ip: '123.145.167.189',
ifa:"AEBE52E7-03EE-455A-B3C4-E57283966239",
},
app: {
Expand Down

0 comments on commit 76a5864

Please sign in to comment.