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

Merge from original branch #2

Merged
merged 7 commits into from
Aug 23, 2022
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
2 changes: 1 addition & 1 deletion .github/workflows/issue_tracker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
steps:
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
uses: tibdex/github-app-token@f717b5ecd4534d3c4df4ce9b5c1c2214f0f7cd06
with:
app_id: ${{ secrets.ISSUE_APP_ID }}
private_key: ${{ secrets.ISSUE_APP_PEM }}
Expand Down
40 changes: 28 additions & 12 deletions modules/adkernelBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ import {
isPlainObject,
isStr,
mergeDeep,
parseGPTSingleSizeArrayToRtbSize
parseGPTSingleSizeArrayToRtbSize,
getDefinedParams
} from '../src/utils.js';
import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {find, includes} from '../src/polyfill.js';
import {find} from '../src/polyfill.js';
import {config} from '../src/config.js';
import { convertOrtbRequestToProprietaryNative } from '../src/native.js';

Expand All @@ -28,10 +29,11 @@ import { convertOrtbRequestToProprietaryNative } from '../src/native.js';
*
* Please contact [email protected] and we'll add your adapter as an alias.
*/

const VIDEO_TARGETING = Object.freeze(['mimes', 'minduration', 'maxduration', 'protocols',
'startdelay', 'linearity', 'boxingallowed', 'playbackmethod', 'delivery',
'pos', 'api', 'ext']);
const VIDEO_PARAMS = ['pos', 'context', 'placement', 'api', 'mimes', 'protocols', 'playbackmethod', 'minduration', 'maxduration',
'startdelay', 'linearity', 'skip', 'skipmin', 'skipafter', 'minbitrate', 'maxbitrate', 'delivery', 'playbackend', 'boxingallowed'];
const VIDEO_FPD = ['battr', 'pos'];
const NATIVE_FPD = ['battr', 'api'];
const BANNER_FPD = ['btype', 'battr', 'pos', 'api'];
const VERSION = '1.6';
const SYNC_IFRAME = 1;
const SYNC_IMAGE = 2;
Expand Down Expand Up @@ -275,18 +277,18 @@ function buildImp(bidRequest, secure) {
format: sizes.map(wh => parseGPTSingleSizeArrayToRtbSize(wh)),
topframe: 0
};
populateImpFpd(imp.banner, bidRequest, BANNER_FPD);
mediaType = BANNER;
} else if (deepAccess(bidRequest, 'mediaTypes.video')) {
let video = deepAccess(bidRequest, 'mediaTypes.video');
imp.video = {};
imp.video = getDefinedParams(video, VIDEO_PARAMS);
populateImpFpd(imp.video, bidRequest, VIDEO_FPD);
if (video.playerSize) {
sizes = video.playerSize[0];
imp.video = Object.assign(imp.video, parseGPTSingleSizeArrayToRtbSize(sizes) || {});
}
if (bidRequest.params.video) {
Object.keys(bidRequest.params.video)
.filter(key => includes(VIDEO_TARGETING, key))
.forEach(key => imp.video[key] = bidRequest.params.video[key]);
} else if (video.w && video.h) {
imp.video.w = video.w;
imp.video.h = video.h;
}
mediaType = VIDEO;
} else if (deepAccess(bidRequest, 'mediaTypes.native')) {
Expand All @@ -295,6 +297,7 @@ function buildImp(bidRequest, secure) {
ver: '1.1',
request: JSON.stringify(nativeRequest)
};
populateImpFpd(imp.native, bidRequest, NATIVE_FPD);
mediaType = NATIVE;
} else {
throw new Error('Unsupported bid received');
Expand Down Expand Up @@ -338,6 +341,19 @@ function buildNativeRequest(nativeReq) {
return request;
}

/**
* Populate impression-level FPD from bid request
* @param target {Object}
* @param bidRequest {BidRequest}
* @param props {String[]}
*/
function populateImpFpd(target, bidRequest, props) {
if (bidRequest.ortb2Imp === undefined) {
return;
}
Object.assign(target, getDefinedParams(bidRequest.ortb2Imp, props));
}

/**
* Builds image asset request
*/
Expand Down
2 changes: 2 additions & 0 deletions modules/adtelligentBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const HOST_GETTERS = {
janet: () => 'ghb.bidder.jmgads.com',
pgam: () => 'ghb.pgamssp.com',
ocm: () => 'ghb.cenarius.orangeclickmedia.com',
vidcrunchllc: () => 'ghb.platform.vidcrunch.com',
}
const getUri = function (bidderCode) {
let bidderWithoutSuffix = bidderCode.split('_')[0];
Expand All @@ -43,6 +44,7 @@ export const spec = {
{ code: 'navelix', gvlid: 380 },
'pgam',
'ocm',
{ code: 'vidcrunchllc', gvlid: 1145 },
],
supportedMediaTypes: [VIDEO, BANNER],
isBidRequestValid: function (bid) {
Expand Down
171 changes: 112 additions & 59 deletions modules/bidwatchAnalyticsAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
BID_WON,
BID_RESPONSE,
BID_REQUESTED,
BID_TIMEOUT,
}
} = CONSTANTS;

Expand All @@ -20,93 +21,142 @@ let allEvents = {}
let auctionEnd = {}
let initOptions = {}
let endpoint = 'https://default'
let objectToSearchForBidderCode = ['bidderRequests', 'bidsReceived', 'noBids']
let requestsAttributes = ['adUnitCode', 'auctionId', 'bidder', 'bidderCode', 'bidId', 'cpm', 'creativeId', 'currency', 'width', 'height', 'mediaType', 'netRevenue', 'originalCpm', 'originalCurrency', 'requestId', 'size', 'source', 'status', 'timeToRespond', 'transactionId', 'ttl', 'sizes', 'mediaTypes', 'src', 'params', 'userId', 'labelAny', 'bids'];

function getAdapterNameForAlias(aliasName) {
return adapterManager.aliasRegistry[aliasName] || aliasName;
}

function cleanArgObject(arg, removead) {
if (typeof arg['bidderCode'] == 'string') { arg['originalBidder'] = getAdapterNameForAlias(arg['bidderCode']); }
if (typeof arg['creativeId'] == 'number') {
arg['creativeId'] = arg['creativeId'].toString();
}
if (removead && typeof arg['ad'] != 'undefined') {
arg['ad'] = 'emptied';
}
if (typeof arg['gdprConsent'] != 'undefined' && typeof arg['gdprConsent']['vendorData'] != 'undefined') {
arg['gdprConsent']['vendorData'] = 'emptied';
function filterAttributes(arg, removead) {
let response = {};
if (typeof arg == 'object') {
if (typeof arg['bidderCode'] == 'string') {
response['originalBidder'] = getAdapterNameForAlias(arg['bidderCode']);
} else if (typeof arg['bidder'] == 'string') {
response['originalBidder'] = getAdapterNameForAlias(arg['bidder']);
}
if (!removead && typeof arg['ad'] != 'undefined') {
response['ad'] = arg['ad'];
}
if (typeof arg['gdprConsent'] != 'undefined') {
response['gdprConsent'] = {};
if (typeof arg['gdprConsent']['consentString'] != 'undefined') { response['gdprConsent']['consentString'] = arg['gdprConsent']['consentString']; }
}
requestsAttributes.forEach((attr) => {
if (typeof arg[attr] != 'undefined') { response[attr] = arg[attr]; }
});
if (typeof response['creativeId'] == 'number') { response['creativeId'] = response['creativeId'].toString(); }
}
return arg;
return response;
}

function cleanArgs(arg, removead) {
Object.keys(arg).forEach(key => {
arg[key] = cleanArgObject(arg[key], removead);
function cleanAuctionEnd(args) {
let response = {};
let filteredObj;
let objects = ['bidderRequests', 'bidsReceived', 'noBids'];
objects.forEach((attr) => {
if (Array.isArray(args[attr])) {
response[attr] = [];
args[attr].forEach((obj) => {
filteredObj = filterAttributes(obj, true);
if (typeof obj['bids'] == 'object') {
filteredObj['bids'] = [];
obj['bids'].forEach((bid) => {
filteredObj['bids'].push(filterAttributes(bid, true));
});
}
response[attr].push(filteredObj);
});
}
});
return arg
return response;
}

function cleanCreatives(args) {
return filterAttributes(args, false);
}

function checkBidderCode(args, removead) {
if (typeof args == 'object') {
for (let i = 0; i < objectToSearchForBidderCode.length; i++) {
if (typeof args[objectToSearchForBidderCode[i]] == 'object') { args[objectToSearchForBidderCode[i]] = cleanArgs(args[objectToSearchForBidderCode[i]], removead) }
function enhanceMediaType(arg) {
saveEvents['bidRequested'].forEach((bidRequested) => {
if (bidRequested['auctionId'] == arg['auctionId'] && Array.isArray(bidRequested['bids'])) {
bidRequested['bids'].forEach((bid) => {
if (bid['transactionId'] == arg['transactionId'] && bid['bidId'] == arg['requestId']) { arg['mediaTypes'] = bid['mediaTypes']; }
});
}
}
if (typeof args['bidderCode'] == 'string') { args['originalBidder'] = getAdapterNameForAlias(args['bidderCode']); } else if (typeof args['bidder'] == 'string') { args['originalBidder'] = getAdapterNameForAlias(args['bidder']); }
if (typeof args['creativeId'] == 'number') { args['creativeId'] = args['creativeId'].toString(); }
});
return arg;
}

return args
function addBidResponse(args) {
let eventType = BID_RESPONSE;
let argsCleaned = cleanCreatives(JSON.parse(JSON.stringify(args))); ;
if (allEvents[eventType] == undefined) { allEvents[eventType] = [] }
allEvents[eventType].push(argsCleaned);
}

function addEvent(eventType, args) {
let argsCleaned;
if (eventType && args) {
if (allEvents[eventType] == undefined) { allEvents[eventType] = [] }
if (saveEvents[eventType] == undefined) { saveEvents[eventType] = [] }
argsCleaned = checkBidderCode(JSON.parse(JSON.stringify(args)), false);
allEvents[eventType].push(argsCleaned);
saveEvents[eventType].push(argsCleaned);
argsCleaned = checkBidderCode(JSON.parse(JSON.stringify(args)), true);
if (['auctionend', 'bidtimeout'].includes(eventType.toLowerCase())) {
if (auctionEnd[eventType] == undefined) { auctionEnd[eventType] = [] }
auctionEnd[eventType].push(argsCleaned);
}
}
function addBidRequested(args) {
let eventType = BID_REQUESTED;
let argsCleaned = filterAttributes(args, true);
if (saveEvents[eventType] == undefined) { saveEvents[eventType] = [] }
saveEvents[eventType].push(argsCleaned);
}

function addTimeout(args) {
let eventType = BID_TIMEOUT;
if (saveEvents[eventType] == undefined) { saveEvents[eventType] = [] }
saveEvents[eventType].push(args);
let argsCleaned = [];
let argsDereferenced = JSON.parse(JSON.stringify(args));
argsDereferenced.forEach((attr) => {
argsCleaned.push(filterAttributes(JSON.parse(JSON.stringify(attr)), false));
});
if (auctionEnd[eventType] == undefined) { auctionEnd[eventType] = [] }
auctionEnd[eventType].push(argsCleaned);
}

function addAuctionEnd(args) {
let eventType = AUCTION_END;
if (saveEvents[eventType] == undefined) { saveEvents[eventType] = [] }
saveEvents[eventType].push(args);
let argsCleaned = cleanAuctionEnd(JSON.parse(JSON.stringify(args)));
if (auctionEnd[eventType] == undefined) { auctionEnd[eventType] = [] }
auctionEnd[eventType].push(argsCleaned);
}

function handleBidWon(args) {
args = cleanArgObject(JSON.parse(JSON.stringify(args)), true);
args = enhanceMediaType(filterAttributes(JSON.parse(JSON.stringify(args)), true));
let increment = args['cpm'];
if (typeof saveEvents['auctionEnd'] == 'object') {
for (let i = 0; i < saveEvents['auctionEnd'].length; i++) {
let tmpAuction = saveEvents['auctionEnd'][i];
if (tmpAuction['auctionId'] == args['auctionId'] && typeof tmpAuction['bidsReceived'] == 'object') {
for (let j = 0; j < tmpAuction['bidsReceived'].length; j++) {
let tmpBid = tmpAuction['bidsReceived'][j];
if (tmpBid['transactionId'] == args['transactionId'] && tmpBid['adId'] != args['adId']) {
if (args['cpm'] < tmpBid['cpm']) {
saveEvents['auctionEnd'].forEach((auction) => {
if (auction['auctionId'] == args['auctionId'] && typeof auction['bidsReceived'] == 'object') {
auction['bidsReceived'].forEach((bid) => {
if (bid['transactionId'] == args['transactionId'] && bid['adId'] != args['adId']) {
if (args['cpm'] < bid['cpm']) {
increment = 0;
} else if (increment > args['cpm'] - tmpBid['cpm']) {
increment = args['cpm'] - tmpBid['cpm'];
} else if (increment > args['cpm'] - bid['cpm']) {
increment = args['cpm'] - bid['cpm'];
}
}
}
});
}
}
});
}
args['cpmIncrement'] = increment;
if (typeof saveEvents.bidRequested == 'object' && saveEvents.bidRequested.length > 0 && saveEvents.bidRequested[0].gdprConsent) { args.gdpr = saveEvents.bidRequested[0].gdprConsent; }
ajax(endpoint + '.bidwatch.io/analytics/bid_won', null, JSON.stringify(args), {method: 'POST', withCredentials: true});
}

function handleAuctionEnd() {
ajax(endpoint + '.bidwatch.io/analytics/auctions', null, JSON.stringify(auctionEnd), {method: 'POST', withCredentials: true});
auctionEnd = {}
if (typeof allEvents['bidResponse'] != 'undefined') {
for (let i = 0; i < allEvents['bidResponse'].length; i++) { ajax(endpoint + '.bidwatch.io/analytics/creatives', null, JSON.stringify(allEvents['bidResponse'][i]), {method: 'POST', withCredentials: true}); }
}
allEvents = {}
ajax(endpoint + '.bidwatch.io/analytics/auctions', function (data) {
let list = JSON.parse(data);
if (Array.isArray(list) && typeof allEvents['bidResponse'] != 'undefined') {
allEvents['bidResponse'].forEach((bidResponse) => {
if (list.includes(bidResponse['originalBidder'] + '_' + bidResponse['creativeId'])) { ajax(endpoint + '.bidwatch.io/analytics/creatives', null, JSON.stringify(bidResponse), {method: 'POST', withCredentials: true}); }
});
}
allEvents = {};
}, JSON.stringify(auctionEnd), {method: 'POST', withCredentials: true});
auctionEnd = {};
}

let bidwatchAnalytics = Object.assign(adapter({url, analyticsType}), {
Expand All @@ -116,17 +166,20 @@ let bidwatchAnalytics = Object.assign(adapter({url, analyticsType}), {
}) {
switch (eventType) {
case AUCTION_END:
addEvent(eventType, args);
addAuctionEnd(args);
handleAuctionEnd();
break;
case BID_WON:
handleBidWon(args);
break;
case BID_RESPONSE:
addEvent(eventType, args);
addBidResponse(args);
break;
case BID_REQUESTED:
addEvent(eventType, args);
addBidRequested(args);
break;
case BID_TIMEOUT:
addTimeout(args);
break;
}
}});
Expand Down
4 changes: 2 additions & 2 deletions modules/consumableBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { logWarn, createTrackPixelHtml, deepAccess, isArray, deepSetValue } from '../src/utils.js';
import { logWarn, deepAccess, isArray, deepSetValue } from '../src/utils.js';
import {config} from '../src/config.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
Expand Down Expand Up @@ -255,7 +255,7 @@ function getSize(sizes) {
function retrieveAd(decision, unitId, unitName) {
let ad;
if (decision.contents && decision.contents[0]) {
ad = decision.contents[0].body + createTrackPixelHtml(decision.impressionUrl);
ad = decision.contents[0].body;
}
if (decision.vastXml) {
ad = decision.vastXml;
Expand Down
Loading