Skip to content
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
95 changes: 63 additions & 32 deletions modules/magniteBidAdapter.js → modules/magniteBidAdapter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { config } from '../src/config.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import {
type AdapterRequest,
type BidderSpec,
type ServerResponse,
registerBidder
} from '../src/adapters/bidderFactory.js';
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
import { type SyncType } from '../src/userSync.js';
import { type BidRequest, type ClientBidderRequest } from '../src/adapterManager.js';
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
import { pbsExtensions } from '../libraries/pbsExtensions/pbsExtensions.js';
import { convertTypes } from '../libraries/transformParamsUtils/convertTypes.js';
Expand All @@ -20,7 +27,16 @@ export const REQUEST_URL = 'https://fastlane.rubiconproject.com/a/api/prebid-exc
export const SYNC_URL = 'https://eus.rubiconproject.com/usync.html';
const DEFAULT_INTEGRATION = 'pbjs';

let mgniConf = {};
type MgniConfig = {
int_type?: string;
rendererUrl?: string;
rendererConfig?: Record<string, unknown>;
impLimit?: number;
bidEndpoint?: string;
syncEndpoint?: string;
};

let mgniConf: MgniConfig = {};

// For transition period we need to listen to both rubicon and magnite configs
['magnite', 'rubicon'].forEach(confName => {
Expand All @@ -36,7 +52,19 @@ export function resetMgniConf() {
mgniConf = {};
}

export const spec = {
type GetUserSyncsArgs = Parameters<NonNullable<BidderSpec<'magnite'>['getUserSyncs']>>;

type LegacyGetUserSyncs = (...args: GetUserSyncsArgs) => {
type: SyncType;
url: string;
} | void;

type MagniteSpec = Omit<BidderSpec<'magnite'>, 'getUserSyncs'> & {
getUserSyncs: LegacyGetUserSyncs;
transformBidParams: (params: Record<string, unknown>) => Record<string, unknown>;
};

export const spec: MagniteSpec = {
code: 'magnite',
gvlid: GVL_ID,
supportedMediaTypes: [BANNER, NATIVE, VIDEO],
Expand All @@ -47,13 +75,13 @@ export const spec = {
transformBidParams
};

registerBidder(spec);
registerBidder(spec as unknown as BidderSpec<'magnite'>);

/**
* Lets Prebid-Core know if the bid is valid before sending it to the adapter
* @param {object} bid
*/
function isBidRequestValid(bid) {
function isBidRequestValid(bid: any) {
return ['accountId', 'siteId', 'zoneId'].every(param => !Number.isNaN(Number.parseInt(bid?.params?.[param])));
}

Expand All @@ -62,14 +90,14 @@ const posMap = {
btf: 3
};

export function masSizeOrdering(sizes) {
export function masSizeOrdering(sizes: Array<{ w: number; h: number }>) {
const MAS_SIZE_PRIORITY = [
{ w: 300, h: 250 },
{ w: 728, h: 90 },
{ w: 160, h: 600 }
];

const compareSizes = (left, right) => left.w === right.w && left.h === right.h;
const compareSizes = (left: { w: number; h: number }, right: { w: number; h: number }) => left.w === right.w && left.h === right.h;

return sizes.sort((first, second) => {
// sort by MAS_SIZE_PRIORITY priority order
Expand All @@ -88,7 +116,7 @@ export function masSizeOrdering(sizes) {
});
}

function getPpuidFromEids(eids) {
function getPpuidFromEids(eids: any[]) {
for (const eid of eids) {
const ppId = eid.uids.find(uid => uid?.ext?.stype === 'ppuid' && uid?.id);
if (ppId) {
Expand All @@ -97,7 +125,7 @@ function getPpuidFromEids(eids) {
}
}

function getPpuid(req) {
function getPpuid(req: { user?: { id?: string; ext?: { eids?: any[] } } }) {
const user = req.user;
if (user?.id) {
return user.id;
Expand All @@ -112,7 +140,7 @@ function getPpuid(req) {
return getPpuidFromEids(eids);
}

function cleanFpd(fpdObj) {
function cleanFpd(fpdObj: Record<string, any>) {
// DV+ wants first party data as object of keys / val where val is array
Object.entries(fpdObj || {}).forEach(([key, val]) => {
// if not array, wrap in array
Expand All @@ -129,9 +157,9 @@ const converter = ortbConverter({
currency: 'USD'
},
processors: pbsExtensions,
imp(buildImp, bidRequest, context) {
imp(buildImp: any, bidRequest: any, context: any) {
// Building imps of request
const imp = buildImp(bidRequest, context);
const imp: any = buildImp(bidRequest, context);

// remove any mediaTypes on imp that are not in our context
[BANNER, NATIVE, VIDEO].forEach(mediaType => {
Expand Down Expand Up @@ -173,7 +201,7 @@ const converter = ortbConverter({
return imp;
},
request(buildRequest, imps, bidderRequest, context) {
const req = buildRequest(imps, bidderRequest, context);
const req: any = buildRequest(imps, bidderRequest, context);

// Do not send in tmax
delete req.tmax;
Expand Down Expand Up @@ -208,14 +236,14 @@ const converter = ortbConverter({

return req;
},
bidResponse(buildBidResponse, bid, context) {
bidResponse(buildBidResponse: any, bid: any, context: any) {
// Move adm_native to adm for native responses so the ortbConverter can process it
if (context.mediaType === NATIVE && bid.adm_native) {
bid.adm = bid.adm_native;
delete bid.adm_native;
}

const bidResponse = buildBidResponse(bid, context);
const bidResponse: any = buildBidResponse(bid, context);

bidResponse.bidderCode = context.bidRequest.bidder;

Expand Down Expand Up @@ -248,9 +276,9 @@ const converter = ortbConverter({
},
overrides: {
imp: {
bidfloor(setBidFloor, imp, bidRequest, context) {
bidfloor(setBidFloor: any, imp: any, bidRequest: any, context: any) {
// Floors should always be in USD
const floor = {};
const floor: any = {};
setBidFloor(floor, bidRequest, { ...context, currency: 'USD' });
if (floor.bidfloorcur === 'USD') {
Object.assign(imp, floor);
Expand All @@ -260,15 +288,15 @@ const converter = ortbConverter({
}
});

function transformBidParams(params) {
function transformBidParams(params: Record<string, unknown>) {
return convertTypes({
'accountId': 'number',
'siteId': 'number',
'zoneId': 'number'
}, params);
}

function shouldAddBid(bid, mediaType) {
function shouldAddBid(bid: any, mediaType: string) {
const enabledTypes = bid.params?.enabledMediaTypes;
return !Array.isArray(enabledTypes) || enabledTypes.includes(mediaType);
}
Expand All @@ -281,8 +309,8 @@ function shouldAddBid(bid, mediaType) {
* @param bidderRequest
* @returns Array of HTTP Request Objects
*/
function buildRequests(bids, bidderRequest) {
const bidsMap = {};
function buildRequests(bids: BidRequest<'magnite'>[], bidderRequest: ClientBidderRequest<'magnite'>): AdapterRequest[] {
const bidsMap: Record<string, any[]> = {};

// Loop through all bids and group them by accountId, siteId, and mediaType
for (const bid of bids) {
Expand Down Expand Up @@ -316,35 +344,38 @@ function buildRequests(bids, bidderRequest) {
return requests;
}

function createRequest(bidRequests, bidderRequest, acctSite, mediaType) {
function createRequest(
bidRequests: BidRequest<'magnite'>[],
bidderRequest: ClientBidderRequest<'magnite'>,
acctSite: string,
mediaType: string,
): AdapterRequest {
return {
method: 'POST',
url: `${(mgniConf.bidEndpoint || REQUEST_URL)}?as=${acctSite}&m=${mediaType}&s=${bidRequests.length}`,
data: converter.toORTB({ bidRequests, bidderRequest, context: { mediaType } })
data: converter.toORTB({ bidRequests, bidderRequest, context: { mediaType: mediaType as any } })
}
}

function interpretResponse(resp, req) {
function interpretResponse(resp: ServerResponse, req: AdapterRequest) {
if (!resp.body) {
resp.body = { nbr: 0 };
}
return converter.fromORTB({ request: req.data, response: resp.body })?.bids;
return (converter.fromORTB({ request: req.data, response: resp.body }) as any)?.bids;
}

/**
* @param syncOptions
* @param responses
* @param gdprConsent
* @param uspConsent
* @param gppConsent
* @param args
* @return {{type: (string), url: (*|string)}[]}
*/
function getUserSyncs(syncOptions, responses, gdprConsent, uspConsent, gppConsent) {
function getUserSyncs(...args: GetUserSyncsArgs): ReturnType<LegacyGetUserSyncs> {
const [syncOptions, responses, gdprConsent, uspConsent, gppConsent] = args;
void responses;
if (!syncOptions.iframeEnabled) {
return;
}

const params = {};
const params: Record<string, any> = {};

if (gdprConsent && typeof gdprConsent.gdprApplies === 'boolean') {
params['gdpr'] = Number(gdprConsent.gdprApplies);
Expand Down
2 changes: 1 addition & 1 deletion test/spec/modules/magniteBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
SYNC_URL,
masSizeOrdering,
resetMgniConf
} from 'modules/magniteBidAdapter.js';
} from 'modules/magniteBidAdapter.ts';
import {newBidder} from 'src/adapters/bidderFactory.js';
import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes.js';
import {config} from 'src/config.js';
Expand Down
Loading