Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

in-app support in kumma adapter #2631

Merged
merged 1 commit into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 217 additions & 30 deletions modules/kummaBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@

import {logError, getTopWindowLocation, getTopWindowReferrer, parseSizesInput} from 'src/utils';
import * as utils from 'src/utils';
import { registerBidder } from 'src/adapters/bidderFactory';
import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes';
import includes from 'core-js/library/fn/array/includes';

const NATIVE_DEFAULTS = {
TITLE_LEN: 100,
DESCR_LEN: 200,
SPONSORED_BY_LEN: 50,
IMG_MIN: 150,
ICON_MIN: 50,
};
const DEFAULT_MIMES = ['video/mp4', 'video/webm', 'application/x-shockwave-flash', 'application/javascript'];
const VIDEO_TARGETING = ['mimes', 'skippable', 'playback_method', 'protocols', 'api'];
const DEFAULT_PROTOCOLS = [2, 3, 5, 6];
const DEFAULT_APIS = [1, 2];

export const spec = {

code: 'kumma',
supportedMediaTypes: [BANNER, NATIVE, VIDEO],

isBidRequestValid: bid => (
!!(bid && bid.params && bid.params.pubId && bid.params.siteId)
!!(bid && bid.params && bid.params.pubId && bid.params.placementId)
),
buildRequests: bidRequests => {
const request = {
id: bidRequests[0].bidderRequestId,
at: 2,
imp: bidRequests.map(slot => impression(slot)),
site: site(bidRequests),
device: device(),
app: app(bidRequests),
device: device(bidRequests),
};
return {
method: 'POST',
Expand All @@ -27,15 +42,11 @@ export const spec = {
bidResponseAvailable(request, response.body)
),
};

function bidResponseAvailable(bidRequest, bidResponse) {
const idToImpMap = {};
const idToBidMap = {};
let ortbRequest = null;
try {
ortbRequest = JSON.parse(bidRequest.data);
} catch (ex) {
logError('kumma.parse', 'ERROR', ex);
}
const ortbRequest = parse(bidRequest.data);
ortbRequest.imp.forEach(imp => {
idToImpMap[imp.id] = imp;
});
Expand All @@ -49,19 +60,39 @@ function bidResponseAvailable(bidRequest, bidResponse) {
if (idToBidMap[id]) {
const bid = {};
bid.requestId = id;
bid.creativeId = idToBidMap[id].adid;
bid.adId = id;
bid.creativeId = id;
bid.cpm = idToBidMap[id].price;
bid.currency = bidResponse.cur;
bid.ttl = 360;
bid.netRevenue = true;
bid.ad = idToBidMap[id].adm;
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid);
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid);
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price);
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur);
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid);
bid.width = idToImpMap[id].banner.w;
bid.height = idToImpMap[id].banner.h;
if (idToImpMap[id]['native']) {
bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]);
let nurl = idToBidMap[id].nurl;
nurl = nurl.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid);
nurl = nurl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price);
nurl = nurl.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur);
nurl = nurl.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid);
bid['native']['impressionTrackers'] = [nurl];
bid.mediaType = 'native';
} else if (idToImpMap[id]['video']) {
bid.vastUrl = idToBidMap[id].adm;
bid.vastUrl = bid.vastUrl.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price);
bid.crid = idToBidMap[id].crid;
bid.width = idToImpMap[id].video.w;
bid.height = idToImpMap[id].video.h;
bid.mediaType = 'video';
} else if (idToImpMap[id]['banner']) {
bid.ad = idToBidMap[id].adm;
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_IMP_ID(%7D|\})/gi, idToBidMap[id].impid);
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_AD_ID(%7D|\})/gi, idToBidMap[id].adid);
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_PRICE(%7D|\})/gi, idToBidMap[id].price);
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_CURRENCY(%7D|\})/gi, bidResponse.cur);
bid.ad = bid.ad.replace(/\$(%7B|\{)AUCTION_BID_ID(%7D|\})/gi, bidResponse.bidid);
bid.width = idToImpMap[id].banner.w;
bid.height = idToImpMap[id].banner.h;
bid.mediaType = 'banner';
}
bids.push(bid);
}
});
Expand All @@ -70,20 +101,110 @@ function bidResponseAvailable(bidRequest, bidResponse) {
function impression(slot) {
return {
id: slot.bidId,
banner: banner(slot),
secure: window.location.protocol === 'https:' ? 1 : 0,
'banner': banner(slot),
'native': nativeImpression(slot),
'video': videoImpression(slot),
bidfloor: slot.params.bidFloor || '0.000001',
tagid: slot.params.placementId.toString(),
};
}
function banner(slot) {
const size = parseSizesInput(slot.sizes)[0].split('x');
const width = parseInt(size[0]);
const height = parseInt(size[1]);

function getSizes(slot) {
const size = utils.parseSizesInput(slot.sizes)[0].split('x');
return {
w: width,
h: height,
width: parseInt(size[0]),
height: parseInt(size[1]),
};
}

function banner(slot) {
if (slot.mediaType === 'banner' || utils.deepAccess(slot, 'mediaTypes.banner')) {
const sizes = getSizes(slot);
return {
w: sizes.width,
h: sizes.height,
};
}
return null;
}

function videoImpression(slot) {
if (slot.mediaType === 'video' || utils.deepAccess(slot, 'mediaTypes.video')) {
const sizes = getSizes(slot);
const video = {
w: sizes.width,
h: sizes.height,
mimes: DEFAULT_MIMES,
protocols: DEFAULT_PROTOCOLS,
api: DEFAULT_APIS,
};
if (slot.params.video) {
Object.keys(slot.params.video).filter(param => includes(VIDEO_TARGETING, param)).forEach(param => video[param] = slot.params.video[param]);
}
return video;
}
return null;
}

function nativeImpression(slot) {
if (slot.mediaType === 'native' || utils.deepAccess(slot, 'mediaTypes.native')) {
const assets = [];
addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN));
addAsset(assets, dataAsset(2, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN));
addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN));
addAsset(assets, imageAsset(4, slot.nativeParams.icon, 1, NATIVE_DEFAULTS.ICON_MIN, NATIVE_DEFAULTS.ICON_MIN));
addAsset(assets, imageAsset(5, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN));
return {
request: JSON.stringify({ assets }),
ver: '1.1',
};
}
return null;
}

function addAsset(assets, asset) {
if (asset) {
assets.push(asset);
}
}

function titleAsset(id, params, defaultLen) {
if (params) {
return {
id,
required: params.required ? 1 : 0,
title: {
len: params.len || defaultLen,
},
};
}
return null;
}

function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) {
return params ? {
id,
required: params.required ? 1 : 0,
img: {
type,
wmin: params.wmin || defaultMinWidth,
hmin: params.hmin || defaultMinHeight,
}
} : null;
}

function dataAsset(id, params, type, defaultLen) {
return params ? {
id,
required: params.required ? 1 : 0,
data: {
type,
len: params.len || defaultLen,
}
} : null;
}

function site(bidderRequest) {
const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0';
const siteId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.siteId : '0';
Expand All @@ -92,22 +213,88 @@ function site(bidderRequest) {
return {
publisher: {
id: pubId.toString(),
domain: getTopWindowLocation().hostname,
domain: utils.getTopWindowLocation().hostname,
},
id: siteId.toString(),
ref: getTopWindowReferrer(),
page: getTopWindowLocation().href,
ref: utils.getTopWindowReferrer(),
page: utils.getTopWindowLocation().href,
}
}
return null;
}
function device() {

function app(bidderRequest) {
const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.pubId : '0';
const appParams = bidderRequest[0].params.app;
if (appParams) {
return {
publisher: {
id: pubId.toString(),
},
id: appParams.id,
name: appParams.name,
bundle: appParams.bundle,
storeurl: appParams.storeUrl,
domain: appParams.domain,
}
}
return null;
}

function device(bidderRequest) {
const lat = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.latitude : '';
const lon = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.longitude : '';
const ifa = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.ifa : '';
return {
dnt: utils.getDNT() ? 1 : 0,
ua: navigator.userAgent,
language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage),
w: (window.screen.width || window.innerWidth),
h: (window.screen.height || window.innerHeigh),
geo: {
lat: lat,
lon: lon,
},
ifa: ifa,
};
}

function parse(rawResponse) {
try {
if (rawResponse) {
return JSON.parse(rawResponse);
}
} catch (ex) {
logError('kumma.parse', 'ERROR', ex);
}
return null;
}

function nativeResponse(imp, bid) {
if (imp['native']) {
const nativeAd = parse(bid.adm);
const keys = {};
keys.image = {};
keys.icon = {};
if (nativeAd && nativeAd['native'] && nativeAd['native'].assets) {
nativeAd['native'].assets.forEach(asset => {
keys.title = asset.title ? asset.title.text : keys.title;
keys.body = asset.data && asset.id === 2 ? asset.data.value : keys.body;
keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy;
keys.icon.url = asset.img && asset.id === 4 ? asset.img.url : keys.icon.url;
keys.icon.width = asset.img && asset.id === 4 ? asset.img.w : keys.icon.width;
keys.icon.height = asset.img && asset.id === 4 ? asset.img.h : keys.icon.height;
keys.image.url = asset.img && asset.id === 5 ? asset.img.url : keys.image.url;
keys.image.width = asset.img && asset.id === 5 ? asset.img.w : keys.image.width;
keys.image.height = asset.img && asset.id === 5 ? asset.img.h : keys.image.height;
});
if (nativeAd['native'].link) {
keys.clickUrl = encodeURIComponent(nativeAd['native'].link.url);
}
return keys;
}
}
return null;
}

registerBidder(spec);
Loading