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

Michao Bid Adapter: Initial release #12507

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ee93a3f
Michao Bid Adapter: Initial release
hogekai Nov 26, 2024
2b0d4fd
Michao Bid Adapter: Fix incomprehensible integration tests
hogekai Nov 27, 2024
ae817a3
Michao Bid Adapter: Explicitly specify VAST XML
hogekai Nov 27, 2024
27d6259
Michao Bid Adapter: Support for rewarded advertising
hogekai Nov 27, 2024
522b79d
Michao Bid Adapter: Re-run E2e test
hogekai Nov 27, 2024
d8313fc
Michao Bid Adapter: Support for native format
hogekai Dec 2, 2024
2228613
Michao Bid Adapter: Change renderer URL
hogekai Dec 2, 2024
08d9ce2
Michao Bid Adapter: Support for blocked categories and blocked advert…
hogekai Dec 3, 2024
dfd29c9
Michao Bid Adapter: Change placement to string type
hogekai Dec 4, 2024
1fb9d7e
Michao Bid Adapter: Add minimum bid price
hogekai Dec 4, 2024
0c0d5e4
Michao Bid Adapter: Added log system validation to integration testin…
hogekai Dec 4, 2024
b869d1c
Michao Bid Adapter: Add partner ID parameter
hogekai Dec 12, 2024
3292094
Michao Bid Adapter: Refactoring
hogekai Dec 13, 2024
a35a9a6
Michao Bid Adapter: Change the method used by the property validation…
hogekai Dec 13, 2024
7457a83
Michao Bid Adapter: Remove video property assertion
hogekai Dec 13, 2024
71b0f01
Michao Bid Adapter: Remove assertions on video properties that you fo…
hogekai Dec 13, 2024
2049dd8
Michao Bid Adapter: Explicitly delete native objects
hogekai Dec 13, 2024
3358914
Michao Bid Adapter: Rename Renderer URL to outstream renderer URL
hogekai Dec 13, 2024
f8ee3aa
Michao Bid Adapter: Swap the order in which bid requests are pushed
hogekai Dec 23, 2024
ac07297
Michao Bid Adapter: Explicitly specify version of outstream renderer URL
hogekai Dec 28, 2024
2d6f8b5
Michao Bid Adapter: Tests are supported for out-stream renderer URL v…
hogekai Dec 29, 2024
b1f16db
Michao Bid Adapter: Add test parameter, Remove OpenRTB parameters
hogekai Jan 6, 2025
a73317f
Michao Bid Adapter: Re run test
hogekai Jan 6, 2025
4b37c27
Michao Bid Adapter: Re run test 2
hogekai Jan 7, 2025
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
260 changes: 260 additions & 0 deletions modules/michaoBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
import { Renderer } from '../src/Renderer.js';
import {
deepSetValue,
isBoolean,
isNumber,
isStr,
logError,
replaceAuctionPrice,
triggerPixel,
} from '../src/utils.js';

const ENV = {
BIDDER_CODE: 'michao',
SUPPORTED_MEDIA_TYPES: [BANNER, VIDEO, NATIVE],
ENDPOINT: 'https://rtb.michao-ssp.com/openrtb/prebid',
NET_REVENUE: true,
DEFAULT_CURRENCY: 'USD',
OUTSTREAM_RENDERER_URL:
hogekai marked this conversation as resolved.
Show resolved Hide resolved
'https://cdn.jsdelivr.net/npm/[email protected]/dist/in-video-renderer.umd.min.js',
};

export const spec = {
code: ENV.BIDDER_CODE,
supportedMediaTypes: ENV.SUPPORTED_MEDIA_TYPES,

isBidRequestValid: function (bid) {
const params = bid.params;

if (!isNumber(params?.site)) {
domainLogger.invalidSiteError(params?.site);
return false;
}

if (!isStr(params?.placement)) {
domainLogger.invalidPlacementError(params?.placement);
return false;
}

if (params?.partner) {
if (!isNumber(params?.partner)) {
domainLogger.invalidPartnerError(params?.partner);
return false;
}
}

if (params?.test) {
if (!isBoolean(params?.test)) {
domainLogger.invalidTestParamError(params?.test);
return false;
}
}

return true;
},

buildRequests: function (validBidRequests, bidderRequest) {
const bidRequests = [];

validBidRequests.forEach((validBidRequest) => {
let bidRequestEachFormat = [];

if (validBidRequest.mediaTypes?.banner) {
bidRequestEachFormat.push({
...validBidRequest,
mediaTypes: {
banner: validBidRequest.mediaTypes.banner,
},
});
}

if (validBidRequest.mediaTypes?.native) {
bidRequestEachFormat.push({
...validBidRequest,
mediaTypes: {
native: validBidRequest.mediaTypes.native,
},
});
}

if (validBidRequest.mediaTypes?.video) {
bidRequestEachFormat.push({
...validBidRequest,
mediaTypes: {
video: validBidRequest.mediaTypes.video,
},
});
}

bidRequests.push(buildRequest(bidRequestEachFormat, bidderRequest));
});

return bidRequests;
},

interpretResponse: function (serverResponse, request) {
return converter.fromORTB({
response: serverResponse.body,
request: request.data,
}).bids;
},

getUserSyncs: function (
syncOptions,
serverResponses,
gdprConsent,
uspConsent
) {
if (syncOptions.iframeEnabled) {
return [
{
type: 'iframe',
url:
'https://sync.michao-ssp.com/cookie-syncs?' +
generateGdprParams(gdprConsent),
},
];
}

return [];
},

onBidBillable: function (bid) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Exciting to see this getting defined

if (bid.burl && isStr(bid.burl)) {
triggerPixel(generateBillableUrl(bid));
}
},
};

export const domainLogger = {
invalidSiteError(value) {
logError(
`Michao Bid Adapter: Invalid site ID. Expected number, got ${typeof value}. Value: ${value}`
);
},

invalidPlacementError(value) {
logError(
`Michao Bid Adapter: Invalid placement. Expected string, got ${typeof value}. Value: ${value}`
);
},

invalidPartnerError(value) {
logError(
`Michao Bid Adapter: Invalid partner ID. Expected number, got ${typeof value}. Value: ${value}`
);
},

invalidTestParamError(value) {
logError(
`Michao Bid Adapter: Invalid test parameter. Expected boolean, got ${typeof value}. Value: ${value}`
);
},
};

function buildRequest(bidRequests, bidderRequest) {
const openRTBBidRequest = converter.toORTB({
bidRequests: bidRequests,
bidderRequest,
});

return {
method: 'POST',
url: ENV.ENDPOINT,
data: openRTBBidRequest,
options: { contentType: 'application/json', withCredentials: true },
};
}

function generateGdprParams(gdprConsent) {
let gdprParams = '';

if (typeof gdprConsent === 'object') {
if (gdprConsent?.gdprApplies) {
gdprParams = `gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${
gdprConsent.consentString || ''
}`;
}
}

return gdprParams;
}

function generateBillableUrl(bid) {
return replaceAuctionPrice(bid.burl, bid.originalCpm || bid.cpm);
}

const converter = ortbConverter({
request(buildRequest, imps, bidderRequest, context) {
const bidRequest = context.bidRequests[0];
const openRTBBidRequest = buildRequest(imps, bidderRequest, context);
openRTBBidRequest.cur = [ENV.DEFAULT_CURRENCY];
openRTBBidRequest.test = bidRequest.params?.test ? 1 : 0;

deepSetValue(
openRTBBidRequest,
'site.id',
bidRequest.params.site.toString()
);
if (bidRequest?.schain) {
deepSetValue(openRTBBidRequest, 'source.schain', bidRequest.schain);
}

if (bidRequest.params?.partner) {
deepSetValue(
openRTBBidRequest,
'site.publisher.ext.partner',
bidRequest.params.partner.toString()
);
}

return openRTBBidRequest;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Your doc says you only support site and user, but you seem to support device and other parts of ortb as well?

},

imp(buildImp, bidRequest, context) {
const imp = buildImp(bidRequest, context);
deepSetValue(imp, 'ext.placement', bidRequest.params.placement.toString());

if (!bidRequest.mediaTypes?.native) {
delete imp.native;
}

return imp;
},

bidResponse(buildBidResponse, bid, context) {
const bidResponse = buildBidResponse(bid, context);
const { bidRequest } = context;
if (
bidResponse.mediaType === VIDEO &&
bidRequest.mediaTypes.video.context === 'outstream'
) {
bidResponse.vastXml = bid.adm;
const renderer = Renderer.install({
url: ENV.OUTSTREAM_RENDERER_URL,
id: bidRequest.bidId,
adUnitCode: bidRequest.adUnitCode,
});
renderer.render(() => {
bid.renderer.push(() => {
const inRenderer = new window.InVideoRenderer();
inRenderer.render(bid.adUnitCode, bid);
});
});
bidResponse.renderer = renderer;
}

return bidResponse;
},

context: {
netRevenue: ENV.NET_REVENUE,
currency: ENV.DEFAULT_CURRENCY,
ttl: 360,
},
});

registerBidder(spec);
87 changes: 87 additions & 0 deletions modules/michaoBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Overview

```markdown
Module Name: Michao Bidder Adapter
Module Type: Bidder Adapter
Maintainer: [email protected]
```

# Description

Module that connects to Michao’s demand sources

Supported Ad format:
* Banner
* Video (instream and outstream)
* Native

# Test Parameters
```
var adUnits = [
// Banner adUnit
{
code: 'banner-div',
mediaTypes: {
banner: {
sizes: [[300, 250]],
}
},
bids: [{
bidder: 'michao',
params: {
site: 1,
placement: '1',
}
}]
},
// Video adUnit
{
code: 'video-div',
mediaTypes: {
video: {
context: 'outstream',
playerSize: [640, 480],
minduration: 0,
maxduration: 120,
mimes: ['video/mp4'],
protocols: [7]
}
},
bids: [{
bidder: 'michao',
params: {
site: 1,
placement: '1',
}
}]
},
// Native AdUnit
{
code: 'native-div',
mediaTypes: {
native: {
ortb: {
assets: [
{
id: 1,
required: 1,
img: {
type: 3,
w: 989,
h: 742,
},
},
]
}
}
},
bids: [{
bidder: 'michao',
params: {
site: 1,
placement: '1',
}
}]
}
];
```
Loading
Loading