Skip to content

Commit

Permalink
Insticator bid adapter with staging endpoint (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
wgalecki authored Apr 29, 2020
1 parent b90761d commit de8c716
Show file tree
Hide file tree
Showing 4 changed files with 654 additions and 4 deletions.
265 changes: 265 additions & 0 deletions modules/insticatorBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
import {config} from '../src/config.js';
import {BANNER} from '../src/mediaTypes.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {
cookiesAreEnabled,
deepAccess,
generateUUID,
getCookie,
localStorageIsEnabled,
logError,
setCookie,
} from '../src/utils.js';

const BIDDER_CODE = 'insticator';
const ENDPOINT = 'https://ex.hunchme.com/v1/openrtb'; // staging endpoint!
const USER_ID_KEY = 'hb_insticator_uid';
const USER_ID_COOKIE_EXP = 2592000000; // 30 days

config.setDefaults({
insticator: {
endpointUrl: ENDPOINT,
},
});

function getUserId() {
let uid;

if (localStorageIsEnabled()) {
uid = localStorage.getItem(USER_ID_KEY);
} else {
uid = getCookie(USER_ID_KEY);
}

if (uid && uid.length !== 36) {
uid = undefined;
}

return uid;
}

function setUserId(userId) {
if (localStorageIsEnabled()) {
localStorage.setItem(USER_ID_KEY, userId);
}

if (cookiesAreEnabled()) {
const expires = new Date(Date.now() + USER_ID_COOKIE_EXP).toISOString();
setCookie(USER_ID_KEY, userId, expires);
}
}

function buildImpression(bidRequest) {
const format = [];
const sizes = deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes;

for (const size of sizes) {
format.push({
w: size[0],
h: size[1],
})
}

return {
id: bidRequest.bidId,
tagid: bidRequest.adUnitCode,
banner: {
format,
},
ext: {
insticator: {
adUnitId: bidRequest.params.adUnitId,
},
},
};
}

function buildDevice() {
const device = {
w: window.innerWidth,
h: window.innerHeight,
js: true,
ext: {
localStorage: localStorageIsEnabled(),
cookies: cookiesAreEnabled(),
},
};

const deviceConfig = config.getConfig('device');

if (typeof deviceConfig === 'object') {
Object.assign(device, deviceConfig);
}

return device;
}

function buildRegs(bidderRequest) {
if (bidderRequest.gdprConsent) {
return {
ext: {
gdpr: bidderRequest.gdprConsent.gdprApplies ? 1 : 0,
gdprConsentString: bidderRequest.gdprConsent.consentString,
},
};
}

return {};
}

function buildUser() {
const userId = getUserId() || generateUUID();

setUserId(userId);

return {
id: userId,
};
}

function buildRequest(validBidRequests, bidderRequest) {
const req = {
id: bidderRequest.bidderRequestId,
tmax: bidderRequest.timeout,
source: {
fd: 1,
tid: bidderRequest.auctionId,
},
site: {
domain: location.hostname,
page: location.href,
ref: bidderRequest.refererInfo.referer,
},
device: buildDevice(),
regs: buildRegs(bidderRequest),
user: buildUser(),
imp: validBidRequests.map(bidRequest => buildImpression(bidRequest)),
};

const params = config.getConfig('insticator.params');

if (params) {
req.ext = {
insticator: params,
};
}

return req;
}

function buildBid(bid, bidderRequest) {
const originalBid = bidderRequest.bids.find(b => b.bidId === bid.impid);

return {
requestId: bid.impid,
creativeId: bid.crid,
cpm: bid.price,
currency: 'USD',
netRevenue: true,
ttl: bid.exp,
width: bid.w,
height: bid.h,
mediaType: 'banner',
ad: bid.adm,
adUnitCode: originalBid.adUnitCode,
};
}

function buildBidSet(seatbid, bidderRequest) {
return seatbid.bid.map(bid => buildBid(bid, bidderRequest));
}

function validateSize(size) {
return (size instanceof Array) &&
size.length === 2 &&
typeof size[0] === 'number' &&
typeof size[1] === 'number';
}

function validateSizes(sizes) {
return (sizes instanceof Array) &&
sizes.length > 0 &&
sizes.map(validateSize)
.reduce((a, b) => a && b, true);
}

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER],

isBidRequestValid: function (bid) {
if (!bid.params.adUnitId) {
logError('insticator: missing adUnitId bid parameter');
return false;
}

if (!(BANNER in bid.mediaTypes)) {
logError('insticator: expected banner in mediaTypes');
return false;
}

if (!validateSizes(bid.sizes) && !validateSizes(bid.mediaTypes.banner.sizes)) {
logError('insticator: banner sizes not specified or invalid');
return false;
}

return true;
},

buildRequests: function (validBidRequests, bidderRequest) {
const requests = [];

if (validBidRequests.length > 0) {
requests.push({
method: 'POST',
url: config.getConfig('insticator.endpointUrl') || ENDPOINT,
options: {
contentType: 'application/json',
withCredentials: true,
},
data: JSON.stringify(buildRequest(validBidRequests, bidderRequest)),
bidderRequest,
});
}

return requests;
},

interpretResponse: function (serverResponse, request) {
const bidderRequest = request.bidderRequest;
const body = serverResponse.body;

if (!body || body.id !== bidderRequest.bidderRequestId) {
logError('insticator: response id does not match bidderRequestId');
return [];
}

if (!body.seatbid) {
return [];
}

const bidsets = body.seatbid.map(
seatbid => buildBidSet(seatbid, bidderRequest),
);

return bidsets.reduce((a, b) => a.concat(b), []);
},

getUserSyncs: function (options, responses) {
const syncs = [];

for (const response of responses) {
if (
response.body &&
response.body.ext &&
response.body.ext.sync instanceof Array
) {
syncs.push(...response.body.ext.sync);
}
}

return syncs;
},
};

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

```
Module Name: Insticator Adapter
Module Type: Bidder Adapter
Maintainer: contact@insticator.com
```

Description
===========

This module connects publishers to Insticator exchange of demand sources through Prebid.js.

### Supported Media Types

| Type | Support
| --- | ---
| Banner | Fully supported for all approved sizes.

# Bid Parameters

Each of the Insticator-specific parameters provided under the `adUnits[].bids[].params`
object are detailed here.

### Banner

| Key | Scope | Type | Description
| --- | --- | --- | ---
| adUnitId | Required | String | The ad unit ID provided by Insticator.


# Test Parameters
```
var adUnits = [
{
code: 'test-div',
sizes: [[300, 250]],
bids: [
{
bidder: 'insticator',
params: {
adUnitId: 'test'
}
}
]
}
]
```
5 changes: 1 addition & 4 deletions modules/serverbidBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ const CONFIG = {
'onefiftytwo': {
'BASE_URI': 'https://e.serverbid.com/api/v2'
},
'insticator': {
'BASE_URI': 'https://e.serverbid.com/api/v2'
},
'automatad': {
'BASE_URI': 'https://e.serverbid.com/api/v2'
},
Expand All @@ -35,7 +32,7 @@ let bidder = 'serverbid';

export const spec = {
code: BIDDER_CODE,
aliases: ['connectad', 'onefiftytwo', 'insticator', 'automatad', 'archon', 'buysellads', 'answermedia'],
aliases: ['connectad', 'onefiftytwo', 'automatad', 'archon', 'buysellads', 'answermedia'],

/**
* Determines whether or not the given bid request is valid.
Expand Down
Loading

0 comments on commit de8c716

Please sign in to comment.