Skip to content

Commit

Permalink
Merge branch 'prebid:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
krzysztofequativ authored Apr 8, 2024
2 parents 64bb962 + eac5e04 commit 4cbe6b3
Show file tree
Hide file tree
Showing 35 changed files with 1,861 additions and 641 deletions.
2 changes: 1 addition & 1 deletion RELEASE_SCHEDULE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

## Release Schedule

We aim to push a new release of Prebid.js every week on Tuesday.
We aim to push a new release of Prebid.js each week barring any unforseen circumstances or in observance of holidays.

While the releases will be available immediately for those using direct Git access,
it will be about a week before the Prebid Org [Download Page](https://docs.prebid.org/download.html) will be updated.
Expand Down
3 changes: 1 addition & 2 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,7 @@ function bundle(dev, moduleArr) {
[coreFile].concat(moduleFiles).map(name => path.basename(name)).forEach((file) => {
(depGraph[file] || []).forEach((dep) => dependencies.add(helpers.getBuiltPath(dev, dep)));
});

const entries = [coreFile].concat(Array.from(dependencies), moduleFiles);
const entries = _.uniq([coreFile].concat(Array.from(dependencies), moduleFiles));

var outputFileName = argv.bundleName ? argv.bundleName : 'prebid.js';

Expand Down
3 changes: 1 addition & 2 deletions karma.conf.maker.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ function newWebpackConfig(codeCoverage, disableFeatures) {
mode: 'development',
devtool: 'inline-source-map',
});

delete webpackConfig.entry;
['entry', 'optimization'].forEach(prop => delete webpackConfig[prop]);

webpackConfig.module.rules
.flatMap((r) => r.use)
Expand Down
3 changes: 2 additions & 1 deletion modules/adkernelBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,8 @@ export const spec = {
{code: 'qortex'},
{code: 'adpluto'},
{code: 'headbidder'},
{code: 'digiad'}
{code: 'digiad'},
{code: 'monetix'}
],
supportedMediaTypes: [BANNER, VIDEO, NATIVE],

Expand Down
213 changes: 213 additions & 0 deletions modules/anyclipBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {BANNER} from '../src/mediaTypes.js';
import {deepAccess, isArray, isFn, logError, logInfo} from '../src/utils.js';
import {config} from '../src/config.js';

/**
* @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest
* @typedef {import('../src/adapters/bidderFactory.js').Bid} Bid
* @typedef {import('../src/adapters/bidderFactory.js').ServerRequest} ServerRequest
* @typedef {import('../src/adapters/bidderFactory.js').BidderSpec} BidderSpec
*/

const BIDDER_CODE = 'anyclip';
const ENDPOINT_URL = 'https://prebid.anyclip.com';
const DEFAULT_CURRENCY = 'USD';
const NET_REVENUE = false;

/*
* Get the bid floor value from the bidRequest object, either using the getFloor function or by accessing the 'params.floor' property.
* If the bid floor cannot be determined, return 0 as a fallback value.
*/
function getBidFloor(bidRequest) {
if (!isFn(bidRequest.getFloor)) {
return deepAccess(bidRequest, 'params.floor', 0);
}

try {
const bidFloor = bidRequest.getFloor({
currency: DEFAULT_CURRENCY,
mediaType: '*',
size: '*',
});
return bidFloor.floor;
} catch (err) {
logError(err);
return 0;
}
}

/** @type {BidderSpec} */
export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER],

/**
* @param {object} bid
* @return {boolean}
*/
isBidRequestValid: (bid = {}) => {
const bidder = deepAccess(bid, 'bidder');
const params = deepAccess(bid, 'params', {});
const mediaTypes = deepAccess(bid, 'mediaTypes', {});
const banner = deepAccess(mediaTypes, BANNER, {});

const isValidBidder = (bidder === BIDDER_CODE);
const isValidSize = (Boolean(banner.sizes) && isArray(mediaTypes[BANNER].sizes) && mediaTypes[BANNER].sizes.length > 0);
const hasSizes = mediaTypes[BANNER] ? isValidSize : false;
const hasRequiredBidParams = Boolean(params.publisherId && params.supplyTagId);

const isValid = isValidBidder && hasSizes && hasRequiredBidParams;
if (!isValid) {
logError(`Invalid bid request: isValidBidder: ${isValidBidder}, hasSizes: ${hasSizes}, hasRequiredBidParams: ${hasRequiredBidParams}`);
}
return isValid;
},

/**
* @param {BidRequest[]} validBidRequests
* @param {*} bidderRequest
* @return {ServerRequest}
*/
buildRequests: (validBidRequests, bidderRequest) => {
const bidRequest = validBidRequests[0];

let refererInfo;
if (bidderRequest && bidderRequest.refererInfo) {
refererInfo = bidderRequest.refererInfo;
}

const timeout = bidderRequest.timeout;
const timeoutAdjustment = timeout - ((20 / 100) * timeout); // timeout adjustment - 20%

if (isPubTagAvailable()) {
// Options
const options = {
publisherId: bidRequest.params.publisherId,
supplyTagId: bidRequest.params.supplyTagId,
url: refererInfo.page,
domain: refererInfo.domain,
prebidTimeout: timeoutAdjustment,
gpid: bidRequest.adUnitCode,
ext: {
transactionId: bidRequest.transactionId
},
sizes: bidRequest.sizes.map((size) => {
return {width: size[0], height: size[1]}
})
}
// Floor
const floor = parseFloat(getBidFloor(bidRequest));
if (!isNaN(floor)) {
options.ext.floor = floor;
}
// Supply Chain (Schain)
if (bidRequest?.schain) {
options.schain = bidRequest.schain
}
// GDPR & Consent (EU)
if (bidderRequest?.gdprConsent) {
options.gdpr = (bidderRequest.gdprConsent.gdprApplies ? 1 : 0);
options.consent = bidderRequest.gdprConsent.consentString;
}
// GPP
if (bidderRequest?.gppConsent?.gppString) {
options.gpp = {
gppVersion: bidderRequest.gppConsent.gppVersion,
sectionList: bidderRequest.gppConsent.sectionList,
applicableSections: bidderRequest.gppConsent.applicableSections,
gppString: bidderRequest.gppConsent.gppString
}
}
// CCPA (US Privacy)
if (bidderRequest?.uspConsent) {
options.usPrivacy = bidderRequest.uspConsent;
}
// COPPA
if (config.getConfig('coppa') === true) {
options.coppa = 1;
}
// Eids
if (bidRequest?.userIdAsEids) {
const eids = bidRequest.userIdAsEids;
if (eids && eids.length) {
options.eids = eids;
}
}

// Request bids
const requestBidsPromise = window._anyclip.pubTag.requestBids(options);
if (requestBidsPromise !== undefined) {
requestBidsPromise
.then(() => {
logInfo('PubTag requestBids done');
})
.catch((err) => {
logError('PubTag requestBids error', err);
});
}

// Request
const payload = {
tmax: timeoutAdjustment
}

return {
method: 'GET',
url: ENDPOINT_URL,
data: payload,
bidRequest
}
}
},

/**
* @param {*} serverResponse
* @param {ServerRequest} bidRequest
* @return {Bid[]}
*/
interpretResponse: (serverResponse, { bidRequest }) => {
const bids = [];

if (bidRequest && isPubTagAvailable()) {
const bidResponse = window._anyclip.pubTag.getBids(bidRequest.transactionId);
if (bidResponse) {
const { adServer } = bidResponse;
if (adServer) {
bids.push({
requestId: bidRequest.bidId,
creativeId: adServer.bid.creativeId,
cpm: bidResponse.cpm,
width: adServer.bid.width,
height: adServer.bid.height,
currency: adServer.bid.currency || DEFAULT_CURRENCY,
netRevenue: NET_REVENUE,
ttl: adServer.bid.ttl,
ad: adServer.bid.ad,
meta: adServer.bid.meta
});
}
}
}

return bids;
},

/**
* @param {Bid} bid
*/
onBidWon: (bid) => {
if (isPubTagAvailable()) {
window._anyclip.pubTag.bidWon(bid);
}
}
}

/**
* @return {boolean}
*/
const isPubTagAvailable = () => {
return !!(window._anyclip && window._anyclip.pubTag);
}

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

```
Module Name: AnyClip Bidder Adapter
Module Type: Bidder Adapter
Maintainer: support@anyclip.com
```

# Description

Connects to AnyClip Marketplace for bids.

For more information about [AnyClip](https://anyclip.com), please contact [support@anyclip.com](support@anyclip.com).

AnyClip bid adapter supports Banner currently*.

Use `anyclip` as bidder.

# Bid Parameters

| Key | Required | Example | Description |
|---------------|----------|--------------------------|---------------------------------------|
| `publisherId` | Yes | `'12345'` | The publisher ID provided by AnyClip |
| `supplyTagId` | Yes | `'-mptNo0BycUG4oCDgGrU'` | The supply tag ID provided by AnyClip |
| `floor` | No | `0.5` | Floor price |


# Sample Ad Unit: For Publishers
## Sample Banner only Ad Unit
```js
var adUnits = [{
code: 'adunit1', // ad slot HTML element ID
mediaTypes: {
banner: {
sizes: [
[300, 250],
[728, 90]
]
}
},
bids: [{
bidder: 'anyclip',
params: {
publisherId: '12345', // required, string
supplyTagId: '-mptNo0BycUG4oCDgGrU', // required, string
floor: 0.5 // optional, floor
}
}]
}]
```


48 changes: 40 additions & 8 deletions modules/appnexusBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const URL = 'https://ib.adnxs.com/ut/v3/prebid';
const URL_SIMPLE = 'https://ib.adnxs-simple.com/ut/v3/prebid';
const VIDEO_TARGETING = ['id', 'minduration', 'maxduration',
'skippable', 'playback_method', 'frameworks', 'context', 'skipoffset'];
const VIDEO_RTB_TARGETING = ['minduration', 'maxduration', 'skip', 'skipafter', 'playbackmethod', 'api', 'startdelay'];
const VIDEO_RTB_TARGETING = ['minduration', 'maxduration', 'skip', 'skipafter', 'playbackmethod', 'api', 'startdelay', 'placement', 'plcmt'];
const USER_PARAMS = ['age', 'externalUid', 'external_uid', 'segments', 'gender', 'dnt', 'language'];
const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately
const DEBUG_PARAMS = ['enabled', 'dongle', 'member_id', 'debug_timeout'];
Expand All @@ -72,7 +72,12 @@ const VIDEO_MAPPING = {
'mid_roll': 2,
'post_roll': 3,
'outstream': 4,
'in-banner': 5
'in-banner': 5,
'in-feed': 6,
'interstitial': 7,
'accompanying_content_pre_roll': 8,
'accompanying_content_mid_roll': 9,
'accompanying_content_post_roll': 10
}
};
const NATIVE_MAPPING = {
Expand Down Expand Up @@ -916,15 +921,15 @@ function bidToTag(bid) {
tag['video_frameworks'] = apiTmp;
}
break;

case 'startdelay':
case 'plcmt':
case 'placement':
const contextKey = 'context';
if (typeof tag.video[contextKey] !== 'number') {
if (typeof tag.video.context !== 'number') {
const plcmt = videoMediaType['plcmt'];
const placement = videoMediaType['placement'];
const startdelay = videoMediaType['startdelay'];
const context = getContextFromPlacement(placement) || getContextFromStartDelay(startdelay);
tag.video[contextKey] = VIDEO_MAPPING[contextKey][context];
const contextVal = getContextFromPlcmt(plcmt, startdelay) || getContextFromPlacement(placement) || getContextFromStartDelay(startdelay);
tag.video.context = VIDEO_MAPPING.context[contextVal];
}
break;
}
Expand Down Expand Up @@ -983,8 +988,12 @@ function getContextFromPlacement(ortbPlacement) {

if (ortbPlacement === 2) {
return 'in-banner';
} else if (ortbPlacement > 2) {
} else if (ortbPlacement === 3) {
return 'outstream';
} else if (ortbPlacement === 4) {
return 'in-feed';
} else if (ortbPlacement === 5) {
return 'intersitial';
}
}

Expand All @@ -1002,6 +1011,29 @@ function getContextFromStartDelay(ortbStartDelay) {
}
}

function getContextFromPlcmt(ortbPlcmt, ortbStartDelay) {
if (!ortbPlcmt) {
return;
}

if (ortbPlcmt === 2) {
if (!ortbStartDelay) {
return;
}
if (ortbStartDelay === 0) {
return 'accompanying_content_pre_roll';
} else if (ortbStartDelay === -1) {
return 'accompanying_content_mid_roll';
} else if (ortbStartDelay === -2) {
return 'accompanying_content_post_roll';
}
} else if (ortbPlcmt === 3) {
return 'interstitial';
} else if (ortbPlcmt === 4) {
return 'outstream';
}
}

function hasUserInfo(bid) {
return !!bid.params.user;
}
Expand Down
Loading

0 comments on commit 4cbe6b3

Please sign in to comment.