Skip to content

Commit

Permalink
Smarthub bid adapter: alias vimayx (prebid#11874)
Browse files Browse the repository at this point in the history
* update adapter SmartHub: add aliases

* SmartHub: add alias VimayX

* refactor due reviews

* code have been improved

* Update smarthubBidAdapter.js

* Update smarthubBidAdapter.js

* Smarthub: reuse teqblaze utility code

---------

Co-authored-by: Victor <[email protected]>
Co-authored-by: Patrick McCann <[email protected]>
Co-authored-by: Demetrio Girardi <[email protected]>
  • Loading branch information
4 people authored and DecayConstant committed Jul 18, 2024
1 parent 8675968 commit 91f857e
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 192 deletions.
26 changes: 15 additions & 11 deletions libraries/teqblazeUtils/bidderUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,20 +188,24 @@ export const buildRequests = (adUrl) => (validBidRequests = [], bidderRequest =
return buildRequestsBase({ adUrl, validBidRequests, bidderRequest, placementProcessingFunction });
};

export const interpretResponse = (serverResponse) => {
let response = [];
for (let i = 0; i < serverResponse.body.length; i++) {
let resItem = serverResponse.body[i];
if (isBidResponseValid(resItem)) {
const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : [];
resItem.meta = { ...resItem.meta, advertiserDomains };

response.push(resItem);
export function interpretResponseBuilder({addtlBidValidation = (bid) => true} = {}) {
return function (serverResponse) {
let response = [];
for (let i = 0; i < serverResponse.body.length; i++) {
let resItem = serverResponse.body[i];
if (isBidResponseValid(resItem) && addtlBidValidation(resItem)) {
const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : [];
resItem.meta = { ...resItem.meta, advertiserDomains };

response.push(resItem);
}
}

return response;
}
}

return response;
};
export const interpretResponse = interpretResponseBuilder();

export const getUserSyncs = (syncUrl) => (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => {
const type = syncOptions.iframeEnabled ? 'iframe' : 'image';
Expand Down
222 changes: 45 additions & 177 deletions modules/smarthubBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import {deepAccess, isFn, logError, logMessage} from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js';
import {config} from '../src/config.js';
import {convertOrtbRequestToProprietaryNative} from '../src/native.js';
import {
buildPlacementProcessingFunction,
buildRequestsBase,
interpretResponseBuilder,
isBidRequestValid
} from '../libraries/teqblazeUtils/bidderUtils.js';

const BIDDER_CODE = 'smarthub';
const ALIASES = [
{code: 'markapp', skipPbsAliasing: true},
{code: 'jdpmedia', skipPbsAliasing: true},
{code: 'tredio', skipPbsAliasing: true},
{code: 'vimayx', skipPbsAliasing: true},
];
const BASE_URLS = {
smarthub: 'https://prebid.smart-hub.io/pbjs',
markapp: 'https://markapp-prebid.smart-hub.io/pbjs',
jdpmedia: 'https://jdpmedia-prebid.smart-hub.io/pbjs',
tredio: 'https://tredio-prebid.smart-hub.io/pbjs'
tredio: 'https://tredio-prebid.smart-hub.io/pbjs',
vimayx: 'https://vimayx-prebid.smart-hub.io/pbjs',
};

function getUrl(partnerName) {
const _getUrl = (partnerName) => {
const aliases = ALIASES.map(el => el.code);
if (aliases.includes(partnerName)) {
return BASE_URLS[partnerName];
Expand All @@ -26,187 +31,50 @@ function getUrl(partnerName) {
return `${BASE_URLS[BIDDER_CODE]}?partnerName=${partnerName}`;
}

function isBidResponseValid(bid) {
if (!bid.requestId || !bid.cpm || !bid.creativeId || !bid.ttl || !bid.currency || !bid.hasOwnProperty('netRevenue')) {
return false;
}
switch (bid.mediaType) {
case BANNER:
return Boolean(bid.width && bid.height && bid.ad);
case VIDEO:
return Boolean(bid.width && bid.height && (bid.vastUrl || bid.vastXml));
case NATIVE:
return Boolean(bid.native && bid.native.impressionTrackers && bid.native.impressionTrackers.length);
default:
return false;
}
}

function getPlacementReqData(bid) {
const { params, bidId, mediaTypes, bidder } = bid;
const schain = bid.schain || {};
const { partnerName, seat, token, iabCat, minBidfloor, pos } = params;
const bidfloor = getBidFloor(bid);

const plcmt = {
partnerName: String(partnerName || bidder).toLowerCase(),
seat,
token,
iabCat,
minBidfloor,
pos,
bidId,
schain,
bidfloor,
};

if (mediaTypes && mediaTypes[BANNER]) {
plcmt.adFormat = BANNER;
plcmt.sizes = mediaTypes[BANNER].sizes;
} else if (mediaTypes && mediaTypes[VIDEO]) {
plcmt.adFormat = VIDEO;
plcmt.playerSize = mediaTypes[VIDEO].playerSize;
plcmt.minduration = mediaTypes[VIDEO].minduration;
plcmt.maxduration = mediaTypes[VIDEO].maxduration;
plcmt.mimes = mediaTypes[VIDEO].mimes;
plcmt.protocols = mediaTypes[VIDEO].protocols;
plcmt.startdelay = mediaTypes[VIDEO].startdelay;
plcmt.placement = mediaTypes[VIDEO].plcmt;
plcmt.plcmt = mediaTypes[VIDEO].plcmt; // https://github.com/prebid/Prebid.js/issues/10452
plcmt.skip = mediaTypes[VIDEO].skip;
plcmt.skipafter = mediaTypes[VIDEO].skipafter;
plcmt.minbitrate = mediaTypes[VIDEO].minbitrate;
plcmt.maxbitrate = mediaTypes[VIDEO].maxbitrate;
plcmt.delivery = mediaTypes[VIDEO].delivery;
plcmt.playbackmethod = mediaTypes[VIDEO].playbackmethod;
plcmt.api = mediaTypes[VIDEO].api;
plcmt.linearity = mediaTypes[VIDEO].linearity;
} else if (mediaTypes && mediaTypes[NATIVE]) {
plcmt.native = mediaTypes[NATIVE];
plcmt.adFormat = NATIVE;
}

return plcmt;
}

function getBidFloor(bid) {
if (!isFn(bid.getFloor)) {
return deepAccess(bid, 'params.bidfloor', 0);
}

try {
const bidFloor = bid.getFloor({
currency: 'USD',
mediaType: '*',
size: '*',
const getPartnerName = (bid) => String(bid.params?.partnerName || bid.bidder).toLowerCase();

const getPlacementReqData = buildPlacementProcessingFunction({
addPlacementType() {},
addCustomFieldsToPlacement(bid, bidderRequest, placement) {
const { seat, token, iabCat, minBidfloor, pos } = bid.params;
Object.assign(placement, {
partnerName: getPartnerName(bid),
seat,
token,
iabCat,
minBidfloor,
pos,
});
return bidFloor.floor;
} catch (e) {
logError(e);
return 0;
}
}

function buildRequestParams(bidderRequest = {}, placements = []) {
let deviceWidth = 0;
let deviceHeight = 0;

let winLocation;
try {
const winTop = window.top;
deviceWidth = winTop.screen.width;
deviceHeight = winTop.screen.height;
winLocation = winTop.location;
} catch (e) {
logMessage(e);
winLocation = window.location;
}

const refferUrl = bidderRequest.refererInfo && bidderRequest.refererInfo.page;
let refferLocation;
try {
refferLocation = refferUrl && new URL(refferUrl);
} catch (e) {
logMessage(e);
}

let location = refferLocation || winLocation;
const language = (navigator && navigator.language) ? navigator.language.split('-')[0] : '';
const host = location.host;
const page = location.pathname;
const secure = location.protocol === 'https:' ? 1 : 0;
return {
deviceWidth,
deviceHeight,
language,
secure,
host,
page,
placements,
coppa: config.getConfig('coppa') === true ? 1 : 0,
ccpa: bidderRequest.uspConsent || undefined,
gdpr: bidderRequest.gdprConsent || undefined,
tmax: bidderRequest.timeout
};
})

const buildRequests = (validBidRequests = [], bidderRequest = {}) => {
const bidsByPartner = validBidRequests.reduce((bidsByPartner, bid) => {
const partner = getPartnerName(bid);
(bidsByPartner[partner] = bidsByPartner[partner] || []).push(bid);
return bidsByPartner;
}, {});
return Object.entries(bidsByPartner).map(([partner, validBidRequests]) => {
return buildRequestsBase({
adUrl: _getUrl(partner),
bidderRequest,
validBidRequests,
placementProcessingFunction: getPlacementReqData
})
})
}

export const spec = {
code: BIDDER_CODE,
aliases: ALIASES,
supportedMediaTypes: [BANNER, VIDEO, NATIVE],

isBidRequestValid: (bid = {}) => {
const { params, bidId, mediaTypes } = bid;
let valid = Boolean(bidId && params && params.seat && params.token);

if (mediaTypes && mediaTypes[BANNER]) {
valid = valid && Boolean(mediaTypes[BANNER] && mediaTypes[BANNER].sizes);
} else if (mediaTypes && mediaTypes[VIDEO]) {
valid = valid && Boolean(mediaTypes[VIDEO] && mediaTypes[VIDEO].playerSize);
} else if (mediaTypes && mediaTypes[NATIVE]) {
valid = valid && Boolean(mediaTypes[NATIVE]);
} else {
valid = false;
isBidRequestValid: isBidRequestValid(['seat', 'token'], 'every'),
buildRequests,
interpretResponse: interpretResponseBuilder({
addtlBidValidation(bid) {
return bid.hasOwnProperty('netRevenue')
}
return valid;
},

buildRequests: (validBidRequests = [], bidderRequest = {}) => {
// convert Native ORTB definition to old-style prebid native definition
validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests);
const tempObj = {};

const len = validBidRequests.length;
for (let i = 0; i < len; i++) {
const bid = validBidRequests[i];
const data = getPlacementReqData(bid);
tempObj[data.partnerName] = tempObj[data.partnerName] || [];
tempObj[data.partnerName].push(data);
}

return Object.keys(tempObj).map(key => {
const request = buildRequestParams(bidderRequest, tempObj[key]);
return {
method: 'POST',
url: getUrl(key),
data: request,
}
});
},

interpretResponse: (serverResponse) => {
let response = [];
for (let i = 0; i < serverResponse.body.length; i++) {
let resItem = serverResponse.body[i];
if (isBidResponseValid(resItem)) {
const advertiserDomains = resItem.adomain && resItem.adomain.length ? resItem.adomain : [];
resItem.meta = { ...resItem.meta, advertiserDomains };

response.push(resItem);
}
}
return response;
}
})
};

registerBidder(spec);
10 changes: 6 additions & 4 deletions test/spec/modules/smarthubBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,9 @@ describe('SmartHubBidAdapter', function () {

const bidderRequest = {
uspConsent: '1---',
gdprConsent: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw',
gdprConsent: {
consentString: 'COvFyGBOvFyGBAbAAAENAPCAAOAAAAAAAAAAAEEUACCKAAA.IFoEUQQgAIQwgIwQABAEAAAAOIAACAIAAAAQAIAgEAACEAAAAAgAQBAAAAAAAGBAAgAAAAAAAFAAECAAAgAAQARAEQAAAAAJAAIAAgAAAYQEAAAQmAgBC3ZAYzUw'
},
refererInfo: {
page: 'https://test.com'
},
Expand Down Expand Up @@ -166,7 +168,7 @@ describe('SmartHubBidAdapter', function () {
expect(data.host).to.be.a('string');
expect(data.page).to.be.a('string');
expect(data.coppa).to.be.a('number');
expect(data.gdpr).to.be.a('string');
expect(data.gdpr.consentString).to.be.a('string');
expect(data.ccpa).to.be.a('string');
expect(data.tmax).to.be.a('number');
expect(data.placements).to.have.lengthOf(3);
Expand Down Expand Up @@ -212,8 +214,8 @@ describe('SmartHubBidAdapter', function () {
serverRequest = spec.buildRequests(bids, bidderRequest);
let data = serverRequest[0].data;
expect(data.gdpr).to.exist;
expect(data.gdpr).to.be.a('string');
expect(data.gdpr).to.equal(bidderRequest.gdprConsent);
expect(data.gdpr.consentString).to.be.a('string');
expect(data.gdpr.consentString).to.equal(bidderRequest.gdprConsent.consentString);
expect(data.ccpa).to.not.exist;
delete bidderRequest.gdprConsent;
});
Expand Down

0 comments on commit 91f857e

Please sign in to comment.