Skip to content
Merged
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
35 changes: 35 additions & 0 deletions modules/asterioBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Overview

```
Module Name: Asterio Bidder Adapter
Module Type: Bidder Adapter
Maintainer: mnikulin@asteriosoft.com
```

# Description

Connects to Asterio Bidder for bids.
Asterio bid adapter supports Banner and Video ads.

# Bid Params

| Name | Scope | Type | Description |
| ---- | ----- | ---- | ----------- |
| `adUnitToken` | required | String | Asterio ad unit token provided by Asterio. |
| `pos` | optional | Number | Ad position override. When omitted, the adapter uses `mediaTypes.banner.pos` or `mediaTypes.video.pos` from the ad unit. |

# Test Parameters
```
const adUnits = [
{
bids: [
{
bidder: 'asterio',
params: {
adUnitToken: '????????-????-????-????-????????????', // adUnitToken provided by Asterio
}
}
]
}
];
Comment on lines +21 to +34
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

The adapter implementation supports additional bidder params beyond adUnitToken (e.g., pos and an endpoint override), but the module docs only mention adUnitToken. Please document the full set of supported params (required vs optional), and if endpoint override is intended only for testing, explicitly call that out to avoid production misconfiguration.

Copilot uses AI. Check for mistakes.
```
149 changes: 149 additions & 0 deletions modules/asterioBidAdapter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { type AdapterRequest, type BidderSpec, type ServerResponse, registerBidder } from '../src/adapters/bidderFactory.js';
import { deepAccess, deepClone } from '../src/utils.js';
import { ajax } from '../src/ajax.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import type { BidRequest } from '../src/adapterManager.js';
import type { Size } from '../src/types/common.d.ts';

const BIDDER_CODE = 'asterio';
export const ENDPOINT = 'https://bid.asterio.ai/prebid/bid';

export type AsterioBidParams = {
adUnitToken: string;
pos?: number;
};

declare module '../src/adUnits' {
interface BidderParams {
[BIDDER_CODE]: AsterioBidParams;
}
}

type AsterioBidPayload = {
bidId: string;
adUnitToken: string;
pos?: number;
sizes: Array<{ width: number; height: number }>;
};

type AsterioServerBid = {
ad?: string;
requestId: string;
cpm: string | number;
currency?: string;
width: number;
height: number;
ttl: number;
creativeId: string;
netRevenue?: boolean;
mediaType?: string;
format?: string;
adomain?: string[];
};

export const spec: BidderSpec<typeof BIDDER_CODE> = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER, VIDEO],

isBidRequestValid: function (bid) {
return !!(bid.params && bid.params.adUnitToken);
},

buildRequests: function (validBidRequests, bidderRequest) {
const bids: AsterioBidPayload[] = validBidRequests.map(bidRequest => ({
bidId: bidRequest.bidId,
adUnitToken: bidRequest.params.adUnitToken,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

please define or import type definitions on your bidder params, eg #14773

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adapter has been migrated to TypeScript

pos: getPosition(bidRequest),
sizes: prepareSizes(bidRequest.sizes)
}));

const payload: {
requestId: string;
bids: AsterioBidPayload[];
referer: string;
schain: unknown;
gdprConsent?: {
consentRequired: boolean;
consentString?: string;
};
} = {
requestId: bidderRequest.bidderRequestId,
bids,
referer: bidderRequest.refererInfo?.page,
schain: validBidRequests[0]?.ortb2?.source?.ext?.schain
};

if (bidderRequest?.gdprConsent) {
payload.gdprConsent = {
consentRequired: typeof bidderRequest.gdprConsent.gdprApplies === 'boolean' ? bidderRequest.gdprConsent.gdprApplies : false,
consentString: bidderRequest.gdprConsent.consentString
};
}

return {
method: 'POST',
url: ENDPOINT,
data: payload,
options: {
contentType: 'text/plain',
customHeaders: {
'Rtb-Direct': 'true'
}
}
};
},

interpretResponse: function (serverResponse: ServerResponse, _request: AdapterRequest) {
const serverBody = serverResponse.body;
if (!serverBody || typeof serverBody !== 'object' || !Array.isArray(serverBody.bids)) {
return [];
}

return serverBody.bids.map((bidResponse: AsterioServerBid) => {
const bid = deepClone(bidResponse);

bid.cpm = parseFloat(String(bidResponse.cpm));
bid.requestId = bidResponse.requestId;
bid.ad = bidResponse.ad;
bid.width = bidResponse.width;
bid.height = bidResponse.height;
bid.currency = bidResponse.currency || 'USD';
bid.netRevenue = typeof bidResponse.netRevenue === 'boolean' ? bidResponse.netRevenue : true;
bid.ttl = bidResponse.ttl;
bid.creativeId = bidResponse.creativeId;
bid.mediaType = bidResponse.mediaType || bidResponse.format || 'banner';

if (VIDEO === bid.mediaType && bidResponse.ad) {
bid.vastXml = bidResponse.ad;
}

bid.meta = {};
bid.meta.advertiserDomains = bid.adomain || [];

return bid;
});
},

onBidWon: function (bid: { winUrl?: string; cpm: number }) {
if (bid.winUrl) {
const winUrl = bid.winUrl.replace(/\$\{AUCTION_PRICE}/, String(bid.cpm));
ajax(winUrl, null, undefined, { keepalive: true });
return true;
}
return false;
}
};

function prepareSizes(sizes: Size | Size[]) {
if (!Array.isArray(sizes) || sizes.length === 0) {
return [];
}
const normalizedSizes = typeof sizes[0] === 'number' ? [sizes] : sizes;
return normalizedSizes.map(size => ({ width: size[0], height: size[1] }));
}

function getPosition(bidRequest: BidRequest<typeof BIDDER_CODE>): number | undefined {
return bidRequest.params.pos ?? deepAccess(bidRequest, 'mediaTypes.banner.pos') ?? deepAccess(bidRequest, 'mediaTypes.video.pos');
}

registerBidder(spec);
Loading
Loading