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

BeOp Bid Adapter : Fix keywords as array #8

Closed
Closed
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
228 changes: 147 additions & 81 deletions modules/beopBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,153 +1,214 @@
import { deepAccess, isArray, logWarn, triggerPixel, buildUrl, logInfo, getValue, getBidIdParameter } from '../src/utils.js';
import { getRefererInfo } from '../src/refererDetection.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { config } from '../src/config.js';
const BIDDER_CODE = 'beop';
const ENDPOINT_URL = 'https://hb.beop.io/bid';
import {
deepAccess,
isArray,
logWarn,
triggerPixel,
buildUrl,
logInfo,
getValue,
getBidIdParameter,
} from "../src/utils.js";
import { getRefererInfo } from "../src/refererDetection.js";
import { registerBidder } from "../src/adapters/bidderFactory.js";
import { config } from "../src/config.js";
const BIDDER_CODE = "beop";
const ENDPOINT_URL = "https://hb.beop.io/bid";
const TCF_VENDOR_ID = 666;

const validIdRegExp = /^[0-9a-fA-F]{24}$/
const validIdRegExp = /^[0-9a-fA-F]{24}$/;

export const spec = {
code: BIDDER_CODE,
gvlid: TCF_VENDOR_ID,
aliases: ['bp'],
aliases: ["bp"],
/**
* Test if the bid request is valid.
*
* @param {bid} : The Bid params
* @return boolean true if the bid request is valid (aka contains a valid accountId or networkId and is open for BANNER), false otherwise.
*/
isBidRequestValid: function(bid) {
* Test if the bid request is valid.
*
* @param {bid} : The Bid params
* @return boolean true if the bid request is valid (aka contains a valid accountId or networkId and is open for BANNER), false otherwise.
*/
isBidRequestValid: function (bid) {
const id = bid.params.accountId || bid.params.networkId;
if (id === null || typeof id === 'undefined') {
return false
if (id === null || typeof id === "undefined") {
return false;
}
if (!validIdRegExp.test(id)) {
return false
return false;
}
return bid.mediaTypes.banner !== null && typeof bid.mediaTypes.banner !== 'undefined';
return (
bid.mediaTypes.banner !== null &&
typeof bid.mediaTypes.banner !== "undefined"
);
},
/**
* Create a BeOp server request from a list of BidRequest
*
* @param {validBidRequests[], ...} : The array of validated bidRequests
* @param {... , bidderRequest} : Common params for each bidRequests
* @return ServerRequest Info describing the request to the BeOp's server
*/
buildRequests: function(validBidRequests, bidderRequest) {
* Create a BeOp server request from a list of BidRequest
*
* @param {validBidRequests[], ...} : The array of validated bidRequests
* @param {... , bidderRequest} : Common params for each bidRequests
* @return ServerRequest Info describing the request to the BeOp's server
*/
buildRequests: function (validBidRequests, bidderRequest) {
const slots = validBidRequests.map(beOpRequestSlotsMaker);
const pageUrl = getPageUrl(bidderRequest.refererInfo, window);
const gdpr = bidderRequest.gdprConsent;
const firstSlot = slots[0];
const kwdsFromRequest = bidderRequest.ortb2?.site?.keywords;
let keywords = [];
if (kwdsFromRequest) {
if (isArray(kwdsFromRequest)) {
keywords = kwdsFromRequest;
} else {
if (kwdsFromRequest.indexOf(",") != -1) {
keywords = kwdsFromRequest.split(",");
} else {
keywords.push(kwdsFromRequest);
}
}
}

Choose a reason for hiding this comment

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

If you want me to nitpick, you could write

else if (…) {
  …
  …
} else {
  …
}

instead of

else {
  if (…) {
    …
    …
  } else {
    …
  }
}

const payloadObject = {
at: new Date().toString(),
nid: firstSlot.nid,
nptnid: firstSlot.nptnid,
pid: firstSlot.pid,
url: pageUrl,
lang: (window.navigator.language || window.navigator.languages[0]),
kwds: bidderRequest.ortb2?.site?.keywords || [],
lang: window.navigator.language || window.navigator.languages[0],
kwds: keywords,
dbg: false,
slts: slots,
is_amp: deepAccess(bidderRequest, 'referrerInfo.isAmp'),
tc_string: (gdpr && gdpr.gdprApplies) ? gdpr.consentString : null,
is_amp: deepAccess(bidderRequest, "referrerInfo.isAmp"),
tc_string: gdpr && gdpr.gdprApplies ? gdpr.consentString : null,
};
const payloadString = JSON.stringify(payloadObject);
return {
method: 'POST',
method: "POST",
url: ENDPOINT_URL,
data: payloadString
}
data: payloadString,
};
},
interpretResponse: function(serverResponse, request) {
if (serverResponse && serverResponse.body && isArray(serverResponse.body.bids) && serverResponse.body.bids.length > 0) {
interpretResponse: function (serverResponse, request) {
if (
serverResponse &&
serverResponse.body &&
isArray(serverResponse.body.bids) &&
serverResponse.body.bids.length > 0
) {
return serverResponse.body.bids;
}
return [];
},
onTimeout: function(timeoutData) {
if (timeoutData === null || typeof timeoutData === 'undefined' || Object.keys(timeoutData).length === 0) {
onTimeout: function (timeoutData) {
if (
timeoutData === null ||
typeof timeoutData === "undefined" ||
Object.keys(timeoutData).length === 0
) {
return;
}

let trackingParams = buildTrackingParams(timeoutData, 'timeout', timeoutData.timeout);
let trackingParams = buildTrackingParams(
timeoutData,
"timeout",
timeoutData.timeout
);

logWarn(BIDDER_CODE + ': timed out request');
triggerPixel(buildUrl({
protocol: 'https',
hostname: 't.beop.io',
pathname: '/bid',
search: trackingParams
}));
logWarn(BIDDER_CODE + ": timed out request");
triggerPixel(
buildUrl({
protocol: "https",
hostname: "t.beop.io",
pathname: "/bid",
search: trackingParams,
})
);
},
onBidWon: function(bid) {
if (bid === null || typeof bid === 'undefined' || Object.keys(bid).length === 0) {
onBidWon: function (bid) {
if (
bid === null ||
typeof bid === "undefined" ||
Object.keys(bid).length === 0
) {
return;
}
let trackingParams = buildTrackingParams(bid, 'won', bid.cpm);
let trackingParams = buildTrackingParams(bid, "won", bid.cpm);

logInfo(BIDDER_CODE + ': won request');
triggerPixel(buildUrl({
protocol: 'https',
hostname: 't.beop.io',
pathname: '/bid',
search: trackingParams
}));
logInfo(BIDDER_CODE + ": won request");
triggerPixel(
buildUrl({
protocol: "https",
hostname: "t.beop.io",
pathname: "/bid",
search: trackingParams,
})
);
},
onSetTargeting: function(bid) {}
}
onSetTargeting: function (bid) {},
};

function buildTrackingParams(data, info, value) {
let params = Array.isArray(data.params) ? data.params[0] : data.params;
const pageUrl = getPageUrl(null, window);
return {
pid: params.accountId === undefined ? data.ad.match(/account: \“([a-f\d]{24})\“/)[1] : params.accountId,
pid:
params.accountId === undefined
? data.ad.match(/account: \“([a-f\d]{24})\“/)[1]
: params.accountId,
nid: params.networkId,
nptnid: params.networkPartnerId,
bid: data.bidId || data.requestId,
sl_n: data.adUnitCode,
aid: data.auctionId,
se_ca: 'bid',
se_ca: "bid",
se_ac: info,
se_va: value,
url: pageUrl
url: pageUrl,
};
}

function beOpRequestSlotsMaker(bid) {
const bannerSizes = deepAccess(bid, 'mediaTypes.banner.sizes');
const publisherCurrency = config.getConfig('currency.adServerCurrency') || getValue(bid.params, 'currency') || 'EUR';
const bannerSizes = deepAccess(bid, "mediaTypes.banner.sizes");
const publisherCurrency =
config.getConfig("currency.adServerCurrency") ||
getValue(bid.params, "currency") ||
"EUR";
let floor;
if (typeof bid.getFloor === 'function') {
const floorInfo = bid.getFloor({currency: publisherCurrency, mediaType: 'banner', size: [1, 1]});
if (typeof floorInfo === 'object' && floorInfo.currency === publisherCurrency && !isNaN(parseFloat(floorInfo.floor))) {
if (typeof bid.getFloor === "function") {
const floorInfo = bid.getFloor({
currency: publisherCurrency,
mediaType: "banner",
size: [1, 1],
});
if (
typeof floorInfo === "object" &&
floorInfo.currency === publisherCurrency &&
!isNaN(parseFloat(floorInfo.floor))
) {
floor = parseFloat(floorInfo.floor);
}
}
return {
sizes: isArray(bannerSizes) ? bannerSizes : bid.sizes,
flr: floor,
pid: getValue(bid.params, 'accountId'),
nid: getValue(bid.params, 'networkId'),
nptnid: getValue(bid.params, 'networkPartnerId'),
bid: getBidIdParameter('bidId', bid),
brid: getBidIdParameter('bidderRequestId', bid),
name: getBidIdParameter('adUnitCode', bid),
aid: getBidIdParameter('auctionId', bid),
tid: getBidIdParameter('transactionId', bid),
brc: getBidIdParameter('bidRequestsCount', bid),
bdrc: getBidIdParameter('bidderRequestCount', bid),
bwc: getBidIdParameter('bidderWinsCount', bid),
}
pid: getValue(bid.params, "accountId"),
nid: getValue(bid.params, "networkId"),
nptnid: getValue(bid.params, "networkPartnerId"),
bid: getBidIdParameter("bidId", bid),
brid: getBidIdParameter("bidderRequestId", bid),
name: getBidIdParameter("adUnitCode", bid),
aid: getBidIdParameter("auctionId", bid),
tid: getBidIdParameter("transactionId", bid),
brc: getBidIdParameter("bidRequestsCount", bid),
bdrc: getBidIdParameter("bidderRequestCount", bid),
bwc: getBidIdParameter("bidderWinsCount", bid),
};
}

const protocolRelativeRegExp = /^\/\//
const protocolRelativeRegExp = /^\/\//;
function isProtocolRelativeUrl(url) {
return url && url.match(protocolRelativeRegExp) != null;
}

const withProtocolRegExp = /[a-z]{1,}:\/\//
const withProtocolRegExp = /[a-z]{1,}:\/\//;
function isNoProtocolUrl(url) {
return url && url.match(withProtocolRegExp) == null;
}
Expand All @@ -168,18 +229,23 @@ function ensureProtocolInUrl(url, defaultProtocol) {
*/
function safeDeepAccess(obj, path) {
try {
return deepAccess(obj, path)
return deepAccess(obj, path);
} catch (_e) {
return null;
}
}

function getPageUrl(refererInfo, window) {
refererInfo = refererInfo || getRefererInfo();
let pageUrl = refererInfo.canonicalUrl || safeDeepAccess(window, 'top.location.href') || deepAccess(window, 'location.href');
let pageUrl =
refererInfo.canonicalUrl ||
safeDeepAccess(window, "top.location.href") ||
deepAccess(window, "location.href");
// Ensure the protocol is present (looks like sometimes the extracted pageUrl misses it)
if (pageUrl != null) {
const defaultProtocol = safeDeepAccess(window, 'top.location.protocol') || deepAccess(window, 'location.protocol');
const defaultProtocol =
safeDeepAccess(window, "top.location.protocol") ||
deepAccess(window, "location.protocol");
pageUrl = ensureProtocolInUrl(pageUrl, defaultProtocol);
}
return pageUrl;
Expand Down
Loading