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

BMS Bid Adapter : initial release #12621

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
185 changes: 185 additions & 0 deletions integrationExamples/gpt/bms_sample.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
<html>
<head>
<script async src="../../build/dev/prebid.js"></script>
<script
async
src="https://www.googletagservices.com/tag/js/gpt.js"
></script>
<script>
var FAILSAFE_TIMEOUT = 3300;
var PREBID_TIMEOUT = 1000;

var adUnits = (adUnits = [
{
code: "test-div",
mediaTypes: {
banner: {
sizes: [[300, 250]],
},
},
bids: [
{
bidder: "blue",
params: {
bidFloor: 0.05,
currency: "USD",
placementId: 13144370,
publisherId: 13144370,
},
},
],
},
{
code: "test-div2",
mediaTypes: {
banner: {
sizes: [
[300, 250],
[300, 600],
],
},
},
floors: {
currency: "USD",
schema: {
delimiter: "|",
fields: ["mediaType", "size"],
},
values: {
"banner|300x250": 1.1,
"banner|300x600": 1.35,
"banner|*": 2,
},
},
bids: [
{
bidder: "bms",
params: {
bidFloor: 0.05,
currency: "USD",
placementId: 13144370,
publisherId: 13144370,
},
},
],
},
]);

var ortb2 = {
device: {
geo: {
lat: -23.5505,
lon: -46.6333,
type: 1,
accuracy: 100,
},
},
};

const pbjs = window.pbjs || {};
pbjs.que = pbjs.que || [];
</script>

<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
googletag.cmd.push(function () {
googletag.pubads().disableInitialLoad();
});

pbjs.que.push(() => {
pbjs.setConfig({
realTimeData: {
dataProviders: [
{
name: "geolocation",
waitForIt: true,
params: {
requestPermission: true,
},
},
],
},
floors: {},
ortb2: ortb2,
});
pbjs.bidderSettings = {
standard: {
storageAllowed: true,
},
};

pbjs.addAdUnits(adUnits);
});
function renderAllAdUnits() {
const winners = pbjs.getHighestCpmBids();
winners.forEach((winningBid) => renderOne(winningBid));
}

function renderOne(winningBid) {
if (winningBid && winningBid.adId) {
const div = document.getElementById(winningBid.adUnitCode);
if (div) {
const iframe = document.createElement("iframe");
iframe.scrolling = "no";
iframe.frameBorder = "0";
iframe.marginWidth = "0";
iframe.marginHeight = "0";
iframe.name = `prebid_ads_iframe_${winningBid.adUnitCode}`;
iframe.title = "3rd party ad content";
iframe.setAttribute(
"sandbox",
"allow-forms allow-popups allow-same-origin allow-scripts"
);
iframe.setAttribute("aria-label", "Advertisement");
iframe.style.border = "0";
iframe.style.margin = "0";
iframe.style.overflow = "hidden";

div.appendChild(iframe);
const iframeDoc = iframe.contentWindow.document;
pbjs.renderAd(iframeDoc, winningBid.adId);

const normalizeCss = `body { margin: 0; } /* Add other normalize.css styles if needed */`;
const iframeStyle = iframeDoc.createElement("style");
iframeStyle.appendChild(iframeDoc.createTextNode(normalizeCss));
iframeDoc.head.appendChild(iframeStyle);
}
}
}

pbjs.que.push(() => {
pbjs.requestBids({
timeout: 2000,
bidsBackHandler: renderAllAdUnits,
});
});
</script>

<script>
googletag.cmd.push(function () {
googletag
.defineSlot(
"/19968336/header-bid-tag-0",
[
[300, 250],
[300, 600],
],
"div-gpt-ad-1460505748561-0"
)
.addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
</head>

<body>
<div>
<h5>test-div</h5>
<div id="test-div"></div>
<h5>test-div2</h5>
<div id="test-div2"></div>
</div>
</body>
</html>
2 changes: 1 addition & 1 deletion integrationExamples/gpt/x-domain/creative.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// creative will be rendered, e.g. GAM delivering a SafeFrame

// this code is autogenerated, also available in 'build/creative/creative.js'
<script>!function(){"use strict";const e="Prebid Event",n=(()=>{const e={frameBorder:0,scrolling:"no",marginHeight:0,marginWidth:0,topMargin:0,leftMargin:0,allowTransparency:"true"};return(n,t)=>{const r=n.createElement("iframe");return Object.entries(Object.assign({},t,e)).forEach((([e,n])=>r.setAttribute(e,n))),r}})();function t(e){return!!e.frames.__pb_locator__}window.pbRender=function(r){let o=r.parent;try{for(;o!==r.top&&!t(o);)o=o.parent;t(o)||(o=r.parent)}catch(e){}return function({adId:t,pubUrl:s,clickUrl:i}){const c=new URL(s,window.location).origin;function a(e,n,r){const s=new MessageChannel;s.port1.onmessage=u(r),o.postMessage(JSON.stringify(Object.assign({message:e,adId:t},n)),c,[s.port2])}function d(n){a(e,{event:"adRenderFailed",info:{reason:n?.reason||"exception",message:n?.message}}),n?.stack&&console.error(n)}function u(e){return function(){try{return e.apply(this,arguments)}catch(e){d(e)}}}a("Prebid Request",{options:{clickUrl:i}},(function(o){let s;try{s=JSON.parse(o.data)}catch(e){return}if("Prebid Response"===s.message&&s.adId===t){const t=n(r.document,{width:0,height:0,style:"display: none",srcdoc:`<script>${s.renderer}<\/script>`});t.onload=u((function(){const o=t.contentWindow;o.Promise.resolve(o.render(s,{sendMessage:a,mkFrame:n},r)).then((()=>a(e,{event:"adRenderSucceeded"})),d)})),r.document.body.appendChild(t)}}))}}(window)}();</script>
<script>(()=>{"use strict";const e="Prebid Event",n=(()=>{const e={frameBorder:0,scrolling:"no",marginHeight:0,marginWidth:0,topMargin:0,leftMargin:0,allowTransparency:"true"};return(n,t)=>{const r=n.createElement("iframe");return Object.entries(Object.assign({},t,e)).forEach((([e,n])=>r.setAttribute(e,n))),r}})();function t(e){return!!e.frames.__pb_locator__}window.pbRender=function(r){let o=r.parent;try{for(;o!==r.top&&!t(o);)o=o.parent;t(o)||(o=r.parent)}catch(e){}return function({adId:t,pubUrl:s,clickUrl:i}){const a=new URL(s,window.location).origin;function c(e,n,r){const s=new MessageChannel;s.port1.onmessage=l(r),o.postMessage(JSON.stringify(Object.assign({message:e,adId:t},n)),a,[s.port2])}function d(n){c(e,{event:"adRenderFailed",info:{reason:n?.reason||"exception",message:n?.message}}),n?.stack&&console.error(n)}function l(e){return function(){try{return e.apply(this,arguments)}catch(e){d(e)}}}c("Prebid Request",{options:{clickUrl:i}},(function(o){let s;try{s=JSON.parse(o.data)}catch(e){return}if("Prebid Response"===s.message&&s.adId===t){const t=n(r.document,{width:0,height:0,style:"display: none",srcdoc:`<script>${s.renderer}<\/script>`});t.onload=l((function(){const o=t.contentWindow;o.Promise.resolve(o.render(s,{sendMessage:c,mkFrame:n},r)).then((()=>c(e,{event:"adRenderSucceeded"})),d)})),r.document.body.appendChild(t)}}))}}(window)})();</script>
Copy link
Collaborator

Choose a reason for hiding this comment

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

can you remove changes to this file please. its autogenerated

Copy link
Contributor

Choose a reason for hiding this comment

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

removed


<script>
pbRender({
Expand Down
162 changes: 162 additions & 0 deletions modules/bmsBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER } from '../src/mediaTypes.js';
import { getStorageManager } from '../src/storageManager.js';
import {
replaceAuctionPrice,
isFn,
isPlainObject,
deepSetValue,
isEmpty,
triggerPixel,
} from '../src/utils.js';
const BIDDER_CODE = 'bms';
const ENDPOINT_URL =
'https://api.prebid.int.us-east-1.bluems.com/v1/bid?exchangeId=prebid';
const GVLID = 1105;
const COOKIE_NAME = 'bmsCookieId';
const DEFAULT_CURRENCY = 'USD';

export const storage = getStorageManager({ bidderCode: BIDDER_CODE });

function getBidFloor(bid) {
if (isFn(bid.getFloor)) {
let floor = bid.getFloor({
currency: DEFAULT_CURRENCY,
mediaType: BANNER,
size: '*',
});
if (
isPlainObject(floor) &&
!isNaN(floor.floor) &&
floor.currency === DEFAULT_CURRENCY
) {
return floor.floor;
}
}
return null;
}

const converter = ortbConverter({
context: {
netRevenue: true, // Default net revenue configuration
ttl: 100, // Default time-to-live for bid responses
},
imp,
request,
});

function request(buildRequest, imps, bidderRequest, context) {
let request = buildRequest(imps, bidderRequest, context);

// Add publisher ID
deepSetValue(request, 'site.publisher.id', context.publisherId);
return request;
}

function imp(buildImp, bidRequest, context) {
let imp = buildImp(bidRequest, context);
const floor = getBidFloor(bidRequest);
imp.tagid = bidRequest.params.placementId;

if (floor) {
imp.bidfloor = floor;
imp.bidfloorcur = DEFAULT_CURRENCY;
}

return imp;
}

export const spec = {
code: BIDDER_CODE,
gvlid: GVLID,
supportedMediaTypes: [BANNER], // Supported media types

// Validate bid request
isBidRequestValid: function (bid) {
return !!bid.params.placementId && !!bid.params.publisherId;
},

// Build OpenRTB requests using `ortbConverter`
buildRequests: function (validBidRequests, bidderRequest) {
const context = {
publisherId: validBidRequests.find(
(bidRequest) => bidRequest.params?.publisherId
)?.params.publisherId,
};

const ortbRequest = converter.toORTB({
bidRequests: validBidRequests,
bidderRequest,
context,
});

// Add extensions to the request
ortbRequest.ext = ortbRequest.ext || {};
deepSetValue(ortbRequest, 'ext.gvlid', GVLID);

if (storage.localStorageIsEnabled()) {
// Include user cookie ID if available
const ckid = storage.getDataFromLocalStorage(COOKIE_NAME) || null;
if (ckid) {
deepSetValue(ortbRequest, 'user.ext.buyerid', ckid);
}
}

return [
{
method: 'POST',
url: ENDPOINT_URL,
data: ortbRequest,
options: {
contentType: 'application/json',
},
},
];
},

interpretResponse: (serverResponse) => {
if (!serverResponse || isEmpty(serverResponse.body)) return [];

let bids = [];
serverResponse.body.seatbid.forEach((response) => {
response.bid.forEach((bid) => {
const mediaType = bid.ext?.mediaType || 'banner';
bids.push({
ad: replaceAuctionPrice(bid.adm, bid.price),
adapterCode: BIDDER_CODE,
cpm: bid.price,
creativeId: bid.ext.bms.adId,
creative_id: bid.ext.bms.adId,
currency: serverResponse.body.cur || 'USD',
deferBilling: false,
deferRendering: false,
width: bid.w,
height: bid.h,
mediaType,
netRevenue: true,
originalCpm: bid.price,
originalCurrency: serverResponse.body.cur || 'USD',
requestId: bid.impid,
seatBidId: bid.id,
ttl: 1200,
});
});
});
return bids;
},

onBidWon: function (bid) {
const { burl, nurl } = bid || {};

if (nurl) {
triggerPixel(replaceAuctionPrice(nurl, bid.originalCpm || bid.cpm));
}

if (burl) {
triggerPixel(replaceAuctionPrice(burl, bid.originalCpm || bid.cpm));
}
},
};

registerBidder(spec);
Loading
Loading