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

Nativo Bid Adapter: support native and video #12134

Merged
merged 78 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
38e1ade
Initial nativoBidAdapter document creation (js, md and spec)
jsfledd Feb 22, 2021
0792373
Fulling working prebid using nativoBidAdapter. Support for GDPR and C…
jsfledd Mar 12, 2021
008e906
Added defult size settings based on the largest ad unit. Added respon…
jsfledd Apr 5, 2021
21f3e0c
Changed bidder endpoint url
jsfledd Apr 7, 2021
1a33f2c
Changed double quotes to single quotes.
jsfledd Apr 7, 2021
517cd5b
Reverted package-json.lock to remove modifications from PR
jsfledd Apr 8, 2021
44bf428
Added optional bidder param 'url' so the ad server can force- match a…
jsfledd Apr 15, 2021
bfe0e1e
Lint fix. Added space after if.
jsfledd Apr 15, 2021
e927584
Added new QS param to send various adUnit data to adapter endpopint
jsfledd May 26, 2021
8ac4419
Merged latest prebid master branch
jsfledd May 26, 2021
26d8b86
Updated unit test for new QS param
jsfledd May 26, 2021
ead77de
Added qs param to keep track of ad unit refreshes
jsfledd Jul 20, 2021
4ed371c
Merged latest prebid master
jsfledd Jul 20, 2021
e59a770
Merged latest. Added adUnitCode as alternate to placementID. Removed …
jsfledd Sep 29, 2021
c338c4d
Updated bidMap key default value
jsfledd Sep 30, 2021
bfe7b02
Updated refresh increment logic
jsfledd Oct 12, 2021
06407a1
Merged latest
jsfledd Oct 25, 2021
978ffd7
Refactored spread operator for IE11 support
jsfledd Oct 25, 2021
f74f370
Updated isBidRequestValid check
jsfledd Oct 26, 2021
e1554d0
Merge branch 'master' of https://github.com/prebid/Prebid.js
jsfledd Oct 26, 2021
7b9c9bb
Refactored Object.enties to use Object.keys to fix CircleCI testing e…
jsfledd Oct 26, 2021
ffe4dc9
Merge remote-tracking branch 'Prebid_Official/master'
jsfledd Jan 14, 2022
7274900
Updated bid mapping key creation to prioritize ad unit code over plac…
jsfledd Jan 14, 2022
95cc80e
Added filtering by ad, advertiser and campaign.
jsfledd Feb 7, 2022
6b248fc
Merge remote-tracking branch 'Prebid_Official/master'
jsfledd Feb 7, 2022
bea02d0
Merge remote-tracking branch 'Prebid_Official/master'
jsfledd Feb 17, 2022
a6fc789
Merged master
jsfledd Feb 17, 2022
657b35e
merged with master
jsfledd Mar 14, 2022
2c0c8f5
Added more robust bidDataMap with multiple key access
jsfledd Mar 14, 2022
97f020d
Deduped filer values
jsfledd Mar 16, 2022
b23518f
Rolled back package.json
jsfledd Mar 30, 2022
2eeaa47
Merged with latest upstream master branch
jsfledd Mar 30, 2022
729e608
Duped upstream/master's package.lock file ... not sure how it got cha…
jsfledd Mar 30, 2022
f26e064
Small refactor of filterData length check. Removed comparison with 0 …
jsfledd Mar 30, 2022
024d010
Merge branch 'upstream_master'
jsfledd Apr 20, 2022
060ff4c
Added bid sizes to request
jsfledd Jun 6, 2022
15d34f1
Fixed function name in spec. Added unit tests.
jsfledd Jun 6, 2022
4ff5d1b
Merge branch 'upstream_master'
jsfledd Jul 8, 2022
7874280
Added priceFloor module support
jsfledd Jul 8, 2022
7619590
Added protection agains empty url parameter
jsfledd Jul 13, 2022
0bdc853
Merge branch 'upstream_master'
jsfledd Jul 13, 2022
ee52fbb
Merged with latest
jsfledd Oct 5, 2022
c5b8fab
Changed ntv_url QS param to use referrer.location instead of referrer…
jsfledd Oct 5, 2022
51ba485
Removed testing 'only' flag
jsfledd Oct 5, 2022
b682e0b
Merge branch 'upstream_master'
jsfledd Dec 9, 2022
1c02303
Merge branch 'upstream_master'
jsfledd Dec 13, 2022
b6ba5b5
Added ntv_url QS param value validation
jsfledd Dec 13, 2022
e2bed09
Merge remote-tracking branch 'PrebidOfficial/master'
jsfledd Feb 10, 2023
b629344
Merge remote-tracking branch 'PrebidOfficial/master'
jsfledd Feb 23, 2023
e04cf3d
Added userId support
jsfledd Feb 23, 2023
e9bb4ab
Added unit tests, refactored for bugs
jsfledd Feb 23, 2023
ce1b931
Wrapped ajax in try/catch
jsfledd Feb 23, 2023
a3af4e2
Added more unit testing
jsfledd Feb 23, 2023
883ebd3
Updated eid check for duplicate values. Removed error logging as we n…
jsfledd Mar 3, 2023
be48d28
Removed spec test .only. Fixed unit tests that were breaking.
jsfledd Mar 20, 2023
79880a8
Added Prebid version to nativo exchange request
jsfledd Apr 14, 2023
dbc8618
Removed unused bidder methods
jsfledd Apr 14, 2023
76f1ce7
Merge remote-tracking branch 'PrebidOfficial/master'
jsfledd May 25, 2023
3c4e169
Merge remote-tracking branch 'PrebidOfficial/master'
jsfledd Aug 7, 2023
0961ed4
Added OpenRTB payload response. Changes requerst type to POST.
jsfledd Aug 7, 2023
d090447
Removed debug log
jsfledd Aug 7, 2023
722da51
Added/fixed tests
jsfledd Aug 7, 2023
655a6e9
Merge remote-tracking branch 'PrebidOfficial/master'
jsfledd Aug 8, 2023
16a9f80
Merge branch 'prebid:master' into master
doctafaustus Jun 18, 2024
f346598
Merge branch 'prebid:master' into master
doctafaustus Aug 1, 2024
8d0d5af
Handle video mediaType
doctafaustus Aug 1, 2024
d05ecb4
Add built renderer files
doctafaustus Aug 1, 2024
09407fa
Fix no-inner-declarations linting error
doctafaustus Aug 1, 2024
1288e4c
Handle native requests
doctafaustus Aug 5, 2024
3314390
Add examples in Nativo readme
doctafaustus Aug 15, 2024
e538231
Add 'mediaType' property to tests for compatibility with adapter code
doctafaustus Aug 15, 2024
8661827
Remove data URI from VAST XML
doctafaustus Aug 15, 2024
1ebc2ee
Fix 'no-unused-expressions' lint error
doctafaustus Aug 15, 2024
631b4ab
Merge pull request #3 from NativoPlatform/ADS-8014
doctafaustus Aug 16, 2024
0b552e8
Merge branch 'prebid:master' into master
doctafaustus Aug 16, 2024
af21a08
Fix lint error 'curcly'
doctafaustus Aug 16, 2024
d336bae
Remove bidder name validation in 'isBidRequestValid' (#4)
doctafaustus Aug 19, 2024
75eb52e
Add GPP consent string to req (#5)
doctafaustus Oct 11, 2024
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
2 changes: 1 addition & 1 deletion libraries/creative-renderer-display/renderer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion libraries/creative-renderer-native/renderer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

110 changes: 79 additions & 31 deletions modules/nativoBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { deepAccess, isEmpty } from '../src/utils.js'
import { registerBidder } from '../src/adapters/bidderFactory.js'
import { BANNER } from '../src/mediaTypes.js'
import { BANNER, VIDEO, NATIVE } from '../src/mediaTypes.js'
import { getGlobal } from '../src/prebidGlobal.js'
import { ortbConverter } from '../libraries/ortbConverter/converter.js'

const converter = ortbConverter({
context: {
// `netRevenue` and `ttl` are required properties of bid responses - provide a default for them
netRevenue: true, // or false if your adapter should set bidResponse.netRevenue = false
ttl: 30 // default bidResponse.ttl (when not specified in ORTB response.seatbid[].bid[].exp)
ttl: 30, // default bidResponse.ttl (when not specified in ORTB response.seatbid[].bid[].exp)
},
imp(buildImp, bidRequest, context) {
const imp = buildImp(bidRequest, context);
const imp = buildImp(bidRequest, context)
imp.tagid = bidRequest.adUnitCode
return imp;
}
});
if (imp.ext) imp.ext.placementId = bidRequest.params.placementId

return imp
},
})

const BIDDER_CODE = 'nativo'
const BIDDER_ENDPOINT = 'https://exchange.postrelease.com/prebid'
Expand All @@ -24,12 +26,22 @@ const GVLID = 263

const TIME_TO_LIVE = 360

const SUPPORTED_AD_TYPES = [BANNER]
const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]
const FLOOR_PRICE_CURRENCY = 'USD'
const PRICE_FLOOR_WILDCARD = '*'

const localPbjsRef = getGlobal()

function getMediaType(accessObj) {
if (deepAccess(accessObj, 'mediaTypes.video')) {
return VIDEO
} else if (deepAccess(accessObj, 'mediaTypes.native')) {
return NATIVE
} else {
return BANNER
}
}

/**
* Keep track of bid data by keys
* @returns {Object} - Map of bid data that can be referenced by multiple keys
Expand Down Expand Up @@ -122,8 +134,7 @@ export const spec = {
*/
isBidRequestValid: function (bid) {
// We don't need any specific parameters to make a bid request
// If not parameters are supplied just verify it's the correct bidder code
if (!bid.params) return bid.bidder === BIDDER_CODE
if (!bid.params) return true

// Check if any supplied parameters are invalid
const hasInvalidParameters = Object.keys(bid.params).some((key) => {
Expand All @@ -150,7 +161,10 @@ export const spec = {
*/
buildRequests: function (validBidRequests, bidderRequest) {
// Get OpenRTB Data
const openRTBData = converter.toORTB({bidRequests: validBidRequests, bidderRequest})
const openRTBData = converter.toORTB({
bidRequests: validBidRequests,
bidderRequest,
})
const openRTBDataString = JSON.stringify(openRTBData)

const requestData = new RequestData()
Expand Down Expand Up @@ -201,7 +215,8 @@ export const spec = {
let params = [
// Prebid version
{
key: 'ntv_pbv', value: localPbjsRef.version
key: 'ntv_pbv',
value: localPbjsRef.version,
},
// Prebid request id
{ key: 'ntv_pb_rid', value: bidderRequest.bidderRequestId },
Expand Down Expand Up @@ -278,19 +293,31 @@ export const spec = {
})
}

// Add GPP params
if (bidderRequest.gppConsent) {
params.unshift({
key: 'ntv_gpp_consent',
value: bidderRequest.gppConsent.gppString,
})
}

// Add USP params
if (bidderRequest.uspConsent) {
// Put on the beginning of the qs param array
params.unshift({ key: 'us_privacy', value: bidderRequest.uspConsent })
}

const qsParamStrings = [requestData.getRequestDataQueryString(), arrayToQS(params)]
const qsParamStrings = [
requestData.getRequestDataQueryString(),
arrayToQS(params),
]
const requestUrl = buildRequestUrl(BIDDER_ENDPOINT, qsParamStrings)

let serverRequest = {
method: 'POST',
url: requestUrl,
data: openRTBDataString,
bidderRequest: bidderRequest,
}

return serverRequest
Expand Down Expand Up @@ -320,9 +347,10 @@ export const spec = {

// Step through and grab pertinent data
let bidResponse, adUnit
seatbids.forEach((seatbid) => {
seatbids.forEach((seatbid, i) => {
seatbid.bid.forEach((bid) => {
adUnit = this.getAdUnitData(body.id, bid)

bidResponse = {
requestId: adUnit.bidId,
cpm: bid.price,
Expand All @@ -337,10 +365,18 @@ export const spec = {
meta: {
advertiserDomains: bid.adomain,
},
mediaType: getMediaType(request.bidderRequest.bids[i]),
}

if (bid.ext) extData[bid.id] = bid.ext

if (bidResponse.mediaType === VIDEO) {
bidResponse.vastUrl = bid.adm
}
if (bidResponse.mediaType === NATIVE) {
bidResponse.native = {
ortb: JSON.parse(bidResponse.ad),
}
}
bidResponses.push(bidResponse)
})
})
Expand Down Expand Up @@ -414,23 +450,27 @@ export const spec = {
typeof response.body === 'string'
? JSON.parse(response.body)
: response.body
} catch (err) { return }
} catch (err) {
return
}

// Make sure we have valid content
if (!body || !body.seatbid || body.seatbid.length === 0) return

body.seatbid.forEach((seatbid) => {
// Grab the syncs for each seatbid
seatbid.syncUrls.forEach((sync) => {
if (types[sync.type]) {
if (sync.url.trim() !== '') {
syncs.push({
type: sync.type,
url: sync.url.replace('{GDPR_params}', params),
})
if (seatbid.syncUrls) {
seatbid.syncUrls.forEach((sync) => {
if (types[sync.type]) {
if (sync.url.trim() !== '') {
syncs.push({
type: sync.type,
url: sync.url.replace('{GDPR_params}', params),
})
}
}
}
})
})
}
})
})

Expand Down Expand Up @@ -491,7 +531,9 @@ export class RequestData {
getRequestDataQueryString() {
if (this.bidRequestDataSources.length == 0) return

const queryParams = this.bidRequestDataSources.map(dataSource => dataSource.getRequestQueryString()).filter(queryString => queryString !== '')
const queryParams = this.bidRequestDataSources
.map((dataSource) => dataSource.getRequestQueryString())
.filter((queryString) => queryString !== '')
return queryParams.join('&')
}
}
Expand All @@ -500,8 +542,10 @@ export class BidRequestDataSource {
constructor() {
this.type = 'BidRequestDataSource'
}
processBidRequestData(bidRequest, bidderRequest) { }
getRequestQueryString() { return '' }
processBidRequestData(bidRequest, bidderRequest) {}
getRequestQueryString() {
return ''
}
}

export class UserEIDs extends BidRequestDataSource {
Expand Down Expand Up @@ -540,7 +584,7 @@ QueryStringParam.prototype.toString = function () {
export function encodeToBase64(value) {
try {
return btoa(JSON.stringify(value))
} catch (err) { }
} catch (err) {}
}

export function parseFloorPriceData(bidRequest) {
Expand Down Expand Up @@ -708,9 +752,13 @@ function getLargestSize(sizes, method = area) {
* Build the final request url
*/
export function buildRequestUrl(baseUrl, qsParamStringArray = []) {
if (qsParamStringArray.length === 0 || !Array.isArray(qsParamStringArray)) return baseUrl
if (qsParamStringArray.length === 0 || !Array.isArray(qsParamStringArray)) {
return baseUrl
}

const nonEmptyQSParamStrings = qsParamStringArray.filter(qsParamString => qsParamString.trim() !== '')
const nonEmptyQSParamStrings = qsParamStringArray.filter(
(qsParamString) => qsParamString.trim() !== ''
)

if (nonEmptyQSParamStrings.length === 0) return baseUrl

Expand Down Expand Up @@ -752,7 +800,7 @@ export function getPageUrlFromBidRequest(bidRequest) {
try {
const url = new URL(paramPageUrl)
return url.href
} catch (err) { }
} catch (err) {}
}

export function hasProtocol(url) {
Expand Down
101 changes: 84 additions & 17 deletions modules/nativoBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,91 @@ gulp serve --modules=nativoBidAdapter

# Test Parameters

## Banner

```js
var adUnits = [
{
code: 'div-gpt-ad-1460505748561-0',
mediaTypes: {
banner: {
sizes: [
[300, 250],
[300, 600],
],
},
},
// Replace this object to test a new Adapter!
bids: [
{
bidder: 'nativo',
params: {
url: 'https://test-sites.internal.nativo.net/testing/prebid_adpater.html',
},
},
],
},
]
```

## Video

```js
var adUnits = [
{
code: 'div-gpt-ad-1460505748561-0',
mediaTypes: {
banner: {
sizes: [[300, 250], [300,600]],
}
},
// Replace this object to test a new Adapter!
bids: [{
bidder: 'nativo',
params: {
url: 'https://test-sites.internal.nativo.net/testing/prebid_adpater.html'
}
}]

}
];
{
code: 'ntvPlaceholder-1',
mediaTypes: {
video: {
mimes: ['video/mp4'],
protocols: [2, 3, 5, 6],
playbackmethod: [1, 2],
skip: 1,
skipafter: 5,
},
},
video: {
divId: 'player',
},
bids: [
{
bidder: 'nativo',
params: {
url: 'https://test-sites.internal.nativo.net/testing/prebid_adpater.html',
},
},
],
},
]
```

## Native

```js
var adUnits = [
{
code: '/416881364/prebid-native-test-unit',
sizes: [[300, 250]],
mediaTypes: {
native: {
title: {
required: true,
},
image: {
required: true,
},
sponsoredBy: {
required: true,
},
},
},
bids: [
{
bidder: 'nativo',
params: {
url: 'https://test-sites.internal.nativo.net/testing/prebid_adpater.html',
},
},
],
},
]
```
Loading