-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Asterio Bid Adapter: Add native support #14929
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,7 @@ | ||
| 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 { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; | ||
| import type { BidRequest } from '../src/adapterManager.js'; | ||
| import type { Size } from '../src/types/common.d.ts'; | ||
|
|
||
|
|
@@ -41,9 +41,54 @@ type AsterioServerBid = { | |
| adomain?: string[]; | ||
| }; | ||
|
|
||
| type AsterioNativeImage = { | ||
| url: string; | ||
| width?: number; | ||
| height?: number; | ||
| }; | ||
|
|
||
| type AsterioNativeResponse = { | ||
| link?: { | ||
| url?: string; | ||
| clicktrackers?: string[]; | ||
| }; | ||
| imptrackers?: string[]; | ||
| eventtrackers?: Array<{ | ||
| event?: number; | ||
| method?: number; | ||
| url?: string; | ||
| }>; | ||
| assets?: Array<{ | ||
| title?: { | ||
| text?: string; | ||
| }; | ||
| img?: { | ||
| url?: string; | ||
| w?: number; | ||
| h?: number; | ||
| type?: number; | ||
| }; | ||
| data?: { | ||
| value?: string; | ||
| type?: number; | ||
| }; | ||
| }>; | ||
| }; | ||
|
|
||
| type AsterioNativeBid = { | ||
| clickUrl?: string; | ||
| clickTrackers: string[]; | ||
| impressionTrackers: string[]; | ||
| ortb: AsterioNativeResponse; | ||
| title?: string; | ||
| image?: AsterioNativeImage; | ||
| icon?: AsterioNativeImage; | ||
| body?: string; | ||
| }; | ||
|
|
||
| export const spec: BidderSpec<typeof BIDDER_CODE> = { | ||
| code: BIDDER_CODE, | ||
| supportedMediaTypes: [BANNER, VIDEO], | ||
| supportedMediaTypes: [BANNER, VIDEO, NATIVE], | ||
|
|
||
| isBidRequestValid: function (bid) { | ||
| return !!(bid.params && bid.params.adUnitToken); | ||
|
|
@@ -54,7 +99,7 @@ export const spec: BidderSpec<typeof BIDDER_CODE> = { | |
| bidId: bidRequest.bidId, | ||
| adUnitToken: bidRequest.params.adUnitToken, | ||
| pos: getPosition(bidRequest), | ||
| sizes: prepareSizes(bidRequest.sizes) | ||
| sizes: prepareSizes(getSizes(bidRequest)) | ||
| })); | ||
|
|
||
| const payload: { | ||
|
|
@@ -117,6 +162,14 @@ export const spec: BidderSpec<typeof BIDDER_CODE> = { | |
| bid.vastXml = bidResponse.ad; | ||
| } | ||
|
|
||
| if (NATIVE === bid.mediaType && bidResponse.ad) { | ||
| const native = parseNativeAd(bidResponse.ad); | ||
| if (native) { | ||
| bid.native = native; | ||
| delete bid.ad; | ||
| } | ||
| } | ||
|
|
||
| bid.meta = {}; | ||
| bid.meta.advertiserDomains = bid.adomain || []; | ||
|
|
||
|
|
@@ -134,16 +187,68 @@ export const spec: BidderSpec<typeof BIDDER_CODE> = { | |
| } | ||
| }; | ||
|
|
||
| function prepareSizes(sizes: Size | Size[]) { | ||
| function prepareSizes(sizes: Size | Size[] | undefined): AsterioBidPayload['sizes'] { | ||
| if (!Array.isArray(sizes) || sizes.length === 0) { | ||
| return []; | ||
| } | ||
| const normalizedSizes = typeof sizes[0] === 'number' ? [sizes] : sizes; | ||
| const normalizedSizes: Size[] = typeof sizes[0] === 'number' ? [sizes as Size] : sizes as Size[]; | ||
| return normalizedSizes.map(size => ({ width: size[0], height: size[1] })); | ||
| } | ||
|
|
||
| function getSizes(bidRequest: BidRequest<typeof BIDDER_CODE>): Size | Size[] | undefined { | ||
| return bidRequest.mediaTypes?.banner?.sizes ?? deepAccess(bidRequest, 'sizes'); | ||
| } | ||
|
|
||
| function getPosition(bidRequest: BidRequest<typeof BIDDER_CODE>): number | undefined { | ||
| return bidRequest.params.pos ?? deepAccess(bidRequest, 'mediaTypes.banner.pos') ?? deepAccess(bidRequest, 'mediaTypes.video.pos'); | ||
| } | ||
|
|
||
| function parseNativeAd(ad: string): AsterioNativeBid | undefined { | ||
| let parsedResponse: { native?: AsterioNativeResponse }; | ||
| try { | ||
| parsedResponse = JSON.parse(ad); | ||
| } catch (e) { | ||
| return; | ||
| } | ||
|
|
||
| const nativeResponse = parsedResponse.native; | ||
| if (!nativeResponse) { | ||
| return; | ||
| } | ||
|
|
||
| const native: AsterioNativeBid = { | ||
| clickUrl: nativeResponse.link?.url, | ||
| clickTrackers: [...(nativeResponse.link?.clicktrackers || [])], | ||
| impressionTrackers: [...(nativeResponse.imptrackers || [])], | ||
| ortb: nativeResponse | ||
| }; | ||
|
|
||
| nativeResponse.eventtrackers?.forEach(tracker => { | ||
| if (tracker.event === 1 && tracker.method === 1 && tracker.url) { | ||
| native.impressionTrackers.push(tracker.url); | ||
| } | ||
| }); | ||
|
|
||
| nativeResponse.assets?.forEach(asset => { | ||
| if (asset.title?.text) { | ||
| native.title = asset.title.text; | ||
| } else if (asset.img?.url) { | ||
| const image: AsterioNativeImage = { | ||
| url: asset.img.url, | ||
| width: asset.img.w, | ||
| height: asset.img.h | ||
| }; | ||
| if (asset.img.type === 1) { | ||
| native.icon = image; | ||
| } else if (asset.img.type === 3 || !native.image) { | ||
| native.image = image; | ||
| } | ||
| } else if (asset.data?.value && (asset.data.type === 2 || !native.body)) { | ||
| native.body = asset.data.value; | ||
|
Comment on lines
+246
to
+247
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The Useful? React with 👍 / 👎. |
||
| } | ||
| }); | ||
|
|
||
| return native; | ||
| } | ||
|
|
||
| registerBidder(spec); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Native support is declared, but the outbound bid payload only includes
bidId,adUnitToken,pos, andsizes; it never forwards the ad unit’s native asset request (mediaTypes.native/ ORTB native assets). In ORTB-native setups with custom asset IDs or required assets, the bidder cannot reliably match requested assets, which can cause returned native bids to fail core native validation and be dropped before auction completion.Useful? React with 👍 / 👎.