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

mgid bid adapters: refactoring for trimmer code #12057

Merged
merged 17 commits into from
Jul 31, 2024
73 changes: 73 additions & 0 deletions libraries/mgidUtils/mgidUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
isPlainObject,
isArray,
isStr,
isNumber,
} from '../../src/utils.js';
import { config } from '../../src/config.js';
import { USERSYNC_DEFAULT_CONFIG } from '../../src/userSync.js';

const PIXEL_SYNC_URL = 'https://cm.mgid.com/i.gif';
const IFRAME_SYNC_URL = 'https://cm.mgid.com/i.html';

export function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) {
const spb = isPlainObject(config.getConfig('userSync')) &&
isNumber(config.getConfig('userSync').syncsPerBidder)
? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder;

if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) {
let pixels = [];
if (serverResponses &&
isArray(serverResponses) &&
serverResponses.length > 0 &&
isPlainObject(serverResponses[0].body) &&
isPlainObject(serverResponses[0].body.ext) &&
isArray(serverResponses[0].body.ext.cm) &&
serverResponses[0].body.ext.cm.length > 0) {
pixels = serverResponses[0].body.ext.cm;
}

const syncs = [];
const query = [];
query.push('cbuster={cbuster}');
query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : ''));
if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) {
query.push('gdpr=1');
} else {
query.push('gdpr=0');
}
if (isPlainObject(uspConsent) && uspConsent?.consentString) {
query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`);
}
if (isPlainObject(gppConsent) && gppConsent?.gppString) {
query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`);
}
if (config.getConfig('coppa')) {
query.push('coppa=1')
}
const q = query.join('&')
if (syncOptions.iframeEnabled) {
syncs.push({
type: 'iframe',
url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime()))
});
} else if (syncOptions.pixelEnabled) {
if (pixels.length === 0) {
for (let i = 0; i < spb; i++) {
syncs.push({
type: 'image',
url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required
});
}
} else {
for (let i = 0; i < spb && i < pixels.length; i++) {
syncs.push({
type: 'image',
url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime()))
});
}
}
}
return syncs;
}
}
137 changes: 29 additions & 108 deletions modules/mgidBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ import {
parseUrl,
isEmpty,
triggerPixel,
triggerNurlWithCpm,
logWarn,
isFn,
isNumber,
isBoolean,
extractDomainFromHost,
isInteger, deepSetValue, getBidIdParameter, setOnAny
} from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {BANNER, NATIVE} from '../src/mediaTypes.js';
import {config} from '../src/config.js';
import { getStorageManager } from '../src/storageManager.js';
import { convertOrtbRequestToProprietaryNative } from '../src/native.js';
import {USERSYNC_DEFAULT_CONFIG} from '../src/userSync.js';
import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js'

/**
* @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest
Expand Down Expand Up @@ -231,7 +233,7 @@ export const spec = {
const page = deepAccess(bidderRequest, 'refererInfo.page') || info.location
if (!isStr(deepAccess(request.site, 'domain'))) {
const hostname = parseUrl(page).hostname;
request.site.domain = extractDomainFromHost(hostname) || hostname
request.site.domain = extractDomainFromHostExceptLocalhost(hostname) || hostname
}
if (!isStr(deepAccess(request.site, 'page'))) {
request.site.page = page
Expand Down Expand Up @@ -344,13 +346,7 @@ export const spec = {
},
onBidWon: (bid) => {
const cpm = deepAccess(bid, 'adserverTargeting.hb_pb') || '';
if (isStr(bid.nurl) && bid.nurl !== '') {
bid.nurl = bid.nurl.replace(
/\${AUCTION_PRICE}/,
cpm
);
triggerPixel(bid.nurl);
}
triggerNurlWithCpm(bid, cpm)
if (bid.isBurl) {
if (bid.mediaType === BANNER) {
bid.ad = bid.ad.replace(
Expand All @@ -367,68 +363,7 @@ export const spec = {
}
logInfo(LOG_INFO_PREFIX + `onBidWon`);
},
getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => {
logInfo(LOG_INFO_PREFIX + `getUserSyncs`);
const spb = isPlainObject(config.getConfig('userSync')) &&
isNumber(config.getConfig('userSync').syncsPerBidder)
? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder;

if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) {
let pixels = [];
if (serverResponses &&
isArray(serverResponses) &&
serverResponses.length > 0 &&
isPlainObject(serverResponses[0].body) &&
isPlainObject(serverResponses[0].body.ext) &&
isArray(serverResponses[0].body.ext.cm) &&
serverResponses[0].body.ext.cm.length > 0) {
pixels = serverResponses[0].body.ext.cm;
}

const syncs = [];
const query = [];
query.push('cbuster={cbuster}');
query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : ''));
if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) {
query.push('gdpr=1');
} else {
query.push('gdpr=0');
}
if (isPlainObject(uspConsent) && uspConsent?.consentString) {
query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`);
}
if (isPlainObject(gppConsent) && gppConsent?.gppString) {
query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`);
}
if (config.getConfig('coppa')) {
query.push('coppa=1')
}
const q = query.join('&')
if (syncOptions.iframeEnabled) {
syncs.push({
type: 'iframe',
url: 'https://cm.mgid.com/i.html?' + q.replace('{cbuster}', Math.round(new Date().getTime()))
});
} else if (syncOptions.pixelEnabled) {
if (pixels.length === 0) {
for (let i = 0; i < spb; i++) {
syncs.push({
type: 'image',
url: 'https://cm.mgid.com/i.gif?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required
});
}
} else {
for (let i = 0; i < spb && i < pixels.length; i++) {
syncs.push({
type: 'image',
url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime()))
});
}
}
}
return syncs;
}
}
getUserSyncs: getUserSyncs,
};

registerBidder(spec);
Expand Down Expand Up @@ -479,25 +414,11 @@ function setMediaType(bid, newBid) {
}
}

function extractDomainFromHost(pageHost) {
function extractDomainFromHostExceptLocalhost(pageHost) {
if (pageHost === 'localhost') {
return 'localhost'
}
let domain = null;
try {
let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost);
if (domains != null && domains.length > 0) {
domain = domains[0];
for (let i = 1; i < domains.length; i++) {
if (domains[i].length > domain.length) {
domain = domains[i];
}
}
}
} catch (e) {
domain = null;
}
return domain;
return extractDomainFromHost(pageHost)
}

function getLanguage() {
Expand Down Expand Up @@ -675,33 +596,25 @@ function commonNativeRequestObject(nativeAsset, params) {
function parseNativeResponse(bid, newBid) {
newBid.native = {};
if (bid.hasOwnProperty('adm')) {
let adm = '';
let nativeAdm = '';
try {
adm = JSON.parse(bid.adm);
nativeAdm = JSON.parse(bid.adm);
} catch (ex) {
logWarn(LOG_WARN_PREFIX + 'Error: Cannot parse native response for ad response: ' + newBid.adm);
return;
}
if (adm && adm.native && adm.native.assets && adm.native.assets.length > 0) {
if (nativeAdm && nativeAdm.native && nativeAdm.native.assets && nativeAdm.native.assets.length > 0) {
newBid.mediaType = NATIVE;
for (let i = 0, len = adm.native.assets.length; i < len; i++) {
switch (adm.native.assets[i].id) {
for (let i = 0, len = nativeAdm.native.assets.length; i < len; i++) {
switch (nativeAdm.native.assets[i].id) {
case NATIVE_ASSETS.TITLE.ID:
newBid.native.title = adm.native.assets[i].title && adm.native.assets[i].title.text;
newBid.native.title = nativeAdm.native.assets[i].title && nativeAdm.native.assets[i].title.text;
break;
case NATIVE_ASSETS.IMAGE.ID:
newBid.native.image = {
url: adm.native.assets[i].img && adm.native.assets[i].img.url,
height: adm.native.assets[i].img && adm.native.assets[i].img.h,
width: adm.native.assets[i].img && adm.native.assets[i].img.w,
};
newBid.native.image = copyFromAdmAsset(nativeAdm.native.assets[i]);
break;
case NATIVE_ASSETS.ICON.ID:
newBid.native.icon = {
url: adm.native.assets[i].img && adm.native.assets[i].img.url,
height: adm.native.assets[i].img && adm.native.assets[i].img.h,
width: adm.native.assets[i].img && adm.native.assets[i].img.w,
};
newBid.native.icon = copyFromAdmAsset(nativeAdm.native.assets[i]);
break;
case NATIVE_ASSETS.SPONSOREDBY.ID:
case NATIVE_ASSETS.SPONSORED.ID:
Expand All @@ -711,14 +624,14 @@ function parseNativeResponse(bid, newBid) {
case NATIVE_ASSETS.BODY.ID:
case NATIVE_ASSETS.DISPLAYURL.ID:
case NATIVE_ASSETS.CTA.ID:
newBid.native[spec.NATIVE_ASSET_ID_TO_KEY_MAP[adm.native.assets[i].id]] = adm.native.assets[i].data && adm.native.assets[i].data.value;
newBid.native[spec.NATIVE_ASSET_ID_TO_KEY_MAP[nativeAdm.native.assets[i].id]] = nativeAdm.native.assets[i].data && nativeAdm.native.assets[i].data.value;
break;
}
}
newBid.native.clickUrl = adm.native.link && adm.native.link.url;
newBid.native.clickTrackers = (adm.native.link && adm.native.link.clicktrackers) || [];
newBid.native.impressionTrackers = adm.native.imptrackers || [];
newBid.native.jstracker = adm.native.jstracker || [];
newBid.native.clickUrl = nativeAdm.native.link && nativeAdm.native.link.url;
newBid.native.clickTrackers = (nativeAdm.native.link && nativeAdm.native.link.clicktrackers) || [];
newBid.native.impressionTrackers = nativeAdm.native.imptrackers || [];
newBid.native.jstracker = nativeAdm.native.jstracker || [];
newBid.width = 0;
newBid.height = 0;
}
Expand Down Expand Up @@ -778,3 +691,11 @@ function getBidFloor(bid, cur) {
}
return {floor: bidFloor, cur: cur}
}

function copyFromAdmAsset(asset) {
return {
url: asset.img && asset.img.url,
height: asset.img && asset.img.h,
width: asset.img && asset.img.w,
}
}
68 changes: 2 additions & 66 deletions modules/mgidXBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
import { isPlainObject, isNumber, isArray, isStr } 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 { USERSYNC_DEFAULT_CONFIG } from '../src/userSync.js';
import { isBidRequestValid, buildRequestsBase, interpretResponse } from '../libraries/teqblazeUtils/bidderUtils.js';
import { getUserSyncs } from '../libraries/mgidUtils/mgidUtils.js'

const BIDDER_CODE = 'mgidX';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally this is looking great! However, you can import from /libraries/..., not from another adapter, so please move this function to a file in that folder for both

const GVLID = 358;
const AD_URL = 'https://#{REGION}#.mgid.com/pbjs';
const PIXEL_SYNC_URL = 'https://cm.mgid.com/i.gif';
const IFRAME_SYNC_URL = 'https://cm.mgid.com/i.html';

const buildRequests = (validBidRequests = [], bidderRequest = {}) => {
const request = buildRequestsBase({ adUrl: AD_URL, validBidRequests, bidderRequest });
Expand All @@ -33,67 +29,7 @@ export const spec = {
buildRequests,
interpretResponse,

getUserSyncs: (syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) => {
const spb = isPlainObject(config.getConfig('userSync')) &&
isNumber(config.getConfig('userSync').syncsPerBidder)
? config.getConfig('userSync').syncsPerBidder : USERSYNC_DEFAULT_CONFIG.syncsPerBidder;

if (spb > 0 && isPlainObject(syncOptions) && (syncOptions.iframeEnabled || syncOptions.pixelEnabled)) {
let pixels = [];
if (serverResponses &&
isArray(serverResponses) &&
serverResponses.length > 0 &&
isPlainObject(serverResponses[0].body) &&
isPlainObject(serverResponses[0].body.ext) &&
isArray(serverResponses[0].body.ext.cm) &&
serverResponses[0].body.ext.cm.length > 0) {
pixels = serverResponses[0].body.ext.cm;
}

const syncs = [];
const query = [];
query.push('cbuster={cbuster}');
query.push('gdpr_consent=' + encodeURIComponent(isPlainObject(gdprConsent) && isStr(gdprConsent?.consentString) ? gdprConsent.consentString : ''));
if (isPlainObject(gdprConsent) && typeof gdprConsent?.gdprApplies === 'boolean' && gdprConsent.gdprApplies) {
query.push('gdpr=1');
} else {
query.push('gdpr=0');
}
if (isPlainObject(uspConsent) && uspConsent?.consentString) {
query.push(`us_privacy=${encodeURIComponent(uspConsent?.consentString)}`);
}
if (isPlainObject(gppConsent) && gppConsent?.gppString) {
query.push(`gppString=${encodeURIComponent(gppConsent?.gppString)}`);
}
if (config.getConfig('coppa')) {
query.push('coppa=1')
}
const q = query.join('&')
if (syncOptions.iframeEnabled) {
syncs.push({
type: 'iframe',
url: IFRAME_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime()))
});
} else if (syncOptions.pixelEnabled) {
if (pixels.length === 0) {
for (let i = 0; i < spb; i++) {
syncs.push({
type: 'image',
url: PIXEL_SYNC_URL + '?' + q.replace('{cbuster}', Math.round(new Date().getTime())) // randomly selects partner if sync required
});
}
} else {
for (let i = 0; i < spb && i < pixels.length; i++) {
syncs.push({
type: 'image',
url: pixels[i] + (pixels[i].indexOf('?') > 0 ? '&' : '?') + q.replace('{cbuster}', Math.round(new Date().getTime()))
});
}
}
}
return syncs;
}
}
getUserSyncs: getUserSyncs,
};

registerBidder(spec);
Loading
Loading