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

Digital Matter Bid Adapter: Refactor Adapter #12203

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
213 changes: 199 additions & 14 deletions modules/digitalMatterBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,208 @@
import {BANNER, VIDEO} from '../src/mediaTypes.js';
import {deepAccess, deepSetValue, getDNT, inIframe, logWarn, parseSizesInput} from '../src/utils.js';
import {config} from '../src/config.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {
buildRequests,
getUserSyncs,
interpretResponse,
isBidRequestValid
} from '../libraries/xeUtils/bidderUtils.js';
import {BANNER} from '../src/mediaTypes.js';
import {hasPurpose1Consent} from '../src/utils/gdpr.js';

const BIDDER_CODE = 'digitalmatter';
const ENDPOINT = 'https://prebid.di-change.live';
const BIDDER_CODE = 'digitalMatter';
const ENDPOINT_URL = 'https://adx.digitalmatter.services/'

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER],
aliases: ['dichange', 'digitalmatter'],
supportedMediaTypes: [BANNER, VIDEO],
isBidRequestValid,
buildRequests: (validBidRequests, bidderRequest) => buildRequests(validBidRequests, bidderRequest, ENDPOINT),
interpretResponse,
getUserSyncs
bidParameters: ['accountId', 'siteId'],
isBidRequestValid: function (bid) {
if (typeof bid.params !== 'object') {
return false;
}
if (!hasBannerMediaType(bid)) {
logWarn('Invalid bid request: missing required mediaType - banner');
return false;
}

return !!(bid.params.accountId && bid.params.siteId)
},
buildRequests: function (validBidRequests, bidderRequest) {
const common = bidderRequest.ortb2 || {};
const site = common.site;
const tid = common?.source?.tid;
const {user} = common || {};

if (!site.page) {
site.page = bidderRequest.refererInfo.page;
}

const device = getDevice(common.device);
const schain = getByKey(validBidRequests, 'schain');
const eids = getByKey(validBidRequests, 'userIdAsEids');
const currency = config.getConfig('currency')
const cur = currency && [currency];

const imp = validBidRequests.map((bid, id) => {
const {accountId, siteId} = bid.params;
const bannerParams = deepAccess(bid, 'mediaTypes.banner');
const position = deepAccess(bid, 'mediaTypes.banner.pos') ?? 0;

return {
id: bid.adUnitCode,
bidId: bid.bidId,
accountId: accountId,
adUnitCode: bid.adUnitCode,
siteId: siteId,
banner: {
pos: position,
topframe: inIframe() ? 0 : 1,
format: bannerParams.sizes.map(sizeArr => ({
w: sizeArr[0],
h: sizeArr[1]
}))
},
sizes: parseSizesInput(bannerParams.sizes),
};
});

const ext = {
prebid: {
targeting: {
includewinners: true,
includebidderkeys: false
}
}
};

const payload = {
id: bidderRequest.bidderRequestId,
tid,
site,
device,
user,
cur,
imp,
test: config.getConfig('debug') ? 1 : 0,
tmax: bidderRequest.timeout,
start: bidderRequest.auctionStart,
ext
};

if (schain) {
deepSetValue(payload, 'source.ext.schain', schain);
}

if (eids) {
deepSetValue(payload, 'user.ext.eids', eids);
}

if (deepAccess(bidderRequest, 'gdprConsent.gdprApplies') !== undefined) {
deepSetValue(payload, 'user.ext.consent', bidderRequest.gdprConsent.consentString);
deepSetValue(payload, 'regs.ext.gdpr', bidderRequest.gdprConsent.gdprApplies & 1);
}

const payloadString = JSON.stringify(payload);
return {
method: 'POST',
url: ENDPOINT_URL + 'openrtb2/auction',
data: payloadString,
};
},
interpretResponse: function (serverResponse) {
const body = serverResponse.body || serverResponse;
const {cur} = body;
const bids = [];

if (body && body.bids && Array.isArray(body.bids)) {
body.bids.forEach(bidItem => {
const bid = {
requestId: bidItem.bidid,
adomain: bidItem.adomain,
cpm: bidItem.cpm,
currency: cur,
netRevenue: true,
ttl: bidItem.ttl || 300,
creativeId: bidItem.creativeid,
width: bidItem.width,
height: bidItem.height,
dealId: bidItem.dealid,
ad: bidItem.ad,
meta: bidItem.meta,
};

bids.push(bid);
});
}

return bids
},
getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent, gppConsent) {
if (usersSynced) {
return [];
}

const userSyncs = [];

function checkGppStatus(gppConsent) {
if (gppConsent && Array.isArray(gppConsent.applicableSections)) {
return gppConsent.applicableSections.every(sec => typeof sec === 'number' && sec <= 5);
}
return true;
}

if (hasPurpose1Consent(gdprConsent) && checkGppStatus(gppConsent)) {
responses.forEach(response => {
if (response.body.ext && response.body.ext.usersync) {
try {
const userSync = response.body.ext.usersync;

userSync.forEach((element) => {
let url = element.url;
let type = element.type;

if (url) {
if ((type === 'image' || type === 'redirect') && syncOptions.pixelEnabled) {
userSyncs.push({type: 'image', url: url});
} else if (type === 'iframe' && syncOptions.iframeEnabled) {
userSyncs.push({type: 'iframe', url: url});
}
}
})
} catch (e) {
//
}
}
});
}

return userSyncs;
}
}

let usersSynced = false;

function hasBannerMediaType(bidRequest) {
return !!deepAccess(bidRequest, 'mediaTypes.banner');
}

function getDevice(data) {
let dnt = data.dnt;
if (!dnt) {
dnt = getDNT() ? 1 : 0;
}
return {
w: data.w || window.innerWidth,
h: data.h || window.innerHeight,
ua: data.ua || navigator.userAgent,
dnt: dnt,
language: data.language || navigator.language,
}
}

function getByKey(collection, key) {
for (let i = 0, result; i < collection.length; i++) {
result = deepAccess(collection[i], key);
if (result) {
return result;
}
}
}

registerBidder(spec);
68 changes: 28 additions & 40 deletions modules/digitalMatterBidAdapter.md
Original file line number Diff line number Diff line change
@@ -1,50 +1,38 @@
# Overview

```
Module Name: Digital Matter Bidder Adapter
Module Type: Digital Matter Bidder Adapter
Maintainer: di-change@digitalmatter.ai
Module Name: Digital Matter Bid Adapter
Module Type: Digital Matter Bid Adapter
Maintainer: prebid@digitalmatter.ai
```

# Test Parameters
```
# Description

Module that connects to Digital Matter demand sources

# Banner Test Parameters

```js
var adUnits = [
{
code: 'test-banner',
mediaTypes: {
banner: {
sizes: [[300, 250]],
}
},
bids: [
{
bidder: 'digitalmatter',
params: {
env: 'digitalmatter',
pid: '40',
ext: {}
}
}
{
code: "test-banner",
mediaTypes: {
banner: {
sizes: [
[300, 250],
[300, 600]
]
}
},
{
code: 'test-video',
sizes: [ [ 640, 480 ] ],
mediaTypes: {
video: {
playerSize: [640, 480],
context: 'instream',
skipppable: true
}
},
bids: [{
bidder: 'digitalmatter',
params: {
env: 'digitalmatter',
pid: '40',
ext: {}
}
}]
}
bids: [
{
bidder: "digitalMatter",
params: {
accountId: "1_demo_1", // string, required
siteId: "1-demo-1" // string, required
}
}
]
}
];
```
Loading