Skip to content

Commit

Permalink
AdHash Bid Adapter: changes to support preroll videos (#9870)
Browse files Browse the repository at this point in the history
* AdHash Bidder Adapter: minor changes

We're operating on a com TLD now.
Added publisher in URL for easier routing.

* Implemented brand safety

Implemented brand safety checks

* Fix for GDPR consent

Removing the extra information as request data becomes too big and is sometimes truncated

* Ad fraud prevention formula changed

Ad fraud prevention formula changed to support negative values as well as linear distribution of article length

* AdHash brand safety additions

Adding starts-with and ends-with rules that will help us with languages such as German where a single word can be written in multiple ways depending on the gender and grammatical case.

* AdHash brand safety updates

Added support for Cyrillic characters.
Added support for bidderURL parameter.
Fixed score multiplier from 500 to 1000.

* AdHash Analytics adapter

* Support for recent ads

Support for recent ads which gives us the option to do frequency and recency capping.

* Fix for timestamp

* PUB-222

Added logic for measuring the fill rate (fallbacks) for Prebid impressions

* Unit tests for the analytics adapter

Added unit tests for the analytics adapter

* Removed export causing errors

Removed an unneeded export of a const that was causing errors with the analytics adapter

* Added globalScript parameter

* PUB-227

Support for non-latin and non-cyrillic symbols

* GEN-964

- Brand safety now checks the page URL for bad words. No ad is shown if there is at least one match.
- Repeating code is optimized and moved to helper function
- Multi-language support for brand safety

* GEN-1025

Sending the needed ad density data to the bidder

* Removing the analytics adaptor

* Fix for regexp match

* Version change

* MINOR

Code review changes

* GEN-1153

Adding support for preroll ads

* MINOR

Video unit test added

* Removing globalScript flag

---------

Co-authored-by: NikolayMGeorgiev <nikolay@adhash.org>
Co-authored-by: Ventsislav Saraminev <v.saraminev@abv.bg>
Co-authored-by: Dimitar Kalenderov <mitko.kalenderov@gmail.com>
  • Loading branch information
4 people committed May 23, 2023
1 parent bfe4538 commit 8e3c263
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 18 deletions.
45 changes: 28 additions & 17 deletions modules/adhashBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {registerBidder} from '../src/adapters/bidderFactory.js';
import { getStorageManager } from '../src/storageManager.js';
import { includes } from '../src/polyfill.js';
import { BANNER } from '../src/mediaTypes.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';

const VERSION = '3.2';
const BAD_WORD_STEP = 0.1;
Expand Down Expand Up @@ -130,13 +130,13 @@ function brandSafety(badWords, maxScore) {

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

isBidRequestValid: (bid) => {
try {
const { publisherId, platformURL, bidderURL } = bid.params;
return (
includes(Object.keys(bid.mediaTypes), BANNER) &&
(includes(Object.keys(bid.mediaTypes), BANNER) || includes(Object.keys(bid.mediaTypes), VIDEO)) &&
typeof publisherId === 'string' &&
publisherId.length === 42 &&
typeof platformURL === 'string' &&
Expand Down Expand Up @@ -168,7 +168,14 @@ export const spec = {
const url = `${bidderURL}/rtb?version=${VERSION}&prebid=true`;
const index = Math.floor(Math.random() * validBidRequests[i].sizes.length);
const size = validBidRequests[i].sizes[index].join('x');

const creativeData = includes(Object.keys(validBidRequests[i].mediaTypes), VIDEO) ? {
size: 'preroll',
position: validBidRequests[i].adUnitCode,
playerSize: size
} : {
size: size,
position: validBidRequests[i].adUnitCode
};
let recentAds = [];
if (storage.localStorageIsEnabled()) {
const prefix = validBidRequests[i].params.prefix || 'adHash';
Expand Down Expand Up @@ -204,10 +211,7 @@ export const spec = {
language: window.navigator.language,
userAgent: window.navigator.userAgent
},
creatives: [{
size: size,
position: validBidRequests[i].adUnitCode
}],
creatives: [creativeData],
blockedCreatives: [],
currentTimestamp: (new Date().getTime() / 1000) | 0,
recentAds: recentAds,
Expand All @@ -229,7 +233,6 @@ export const spec = {

interpretResponse: (serverResponse, request) => {
const responseBody = serverResponse ? serverResponse.body : {};

if (
!responseBody.creatives ||
responseBody.creatives.length === 0 ||
Expand All @@ -241,18 +244,12 @@ export const spec = {
const publisherURL = JSON.stringify(request.bidRequest.params.platformURL);
const bidderURL = request.bidRequest.params.bidderURL || 'https://bidder.adhash.com';
const oneTimeId = request.bidRequest.adUnitCode + Math.random().toFixed(16).replace('0.', '.');
const globalScript = !request.bidRequest.params.globalScript
? `<script src="${bidderURL}/static/scripts/creative.min.js"></script>`
: '';
const bidderResponse = JSON.stringify({ responseText: JSON.stringify(responseBody) });
const requestData = JSON.stringify(request.data);

return [{
var response = {
requestId: request.bidRequest.bidId,
cpm: responseBody.creatives[0].costEUR,
ad:
`<div id="${oneTimeId}"></div>${globalScript}
<script>callAdvertiser(${bidderResponse},['${oneTimeId}'],${requestData},${publisherURL})</script>`,
width: request.bidRequest.sizes[0][0],
height: request.bidRequest.sizes[0][1],
creativeId: request.bidRequest.adUnitCode,
Expand All @@ -262,7 +259,21 @@ export const spec = {
meta: {
advertiserDomains: responseBody.advertiserDomains ? [responseBody.advertiserDomains] : []
}
}];
};
if (typeof request == 'object' && typeof request.bidRequest == 'object' && typeof request.bidRequest.mediaTypes == 'object' && includes(Object.keys(request.bidRequest.mediaTypes), BANNER)) {
response = Object.assign({
ad:
`<div id="${oneTimeId}"></div>
<script src="${bidderURL}/static/scripts/creative.min.js"></script>
<script>callAdvertiser(${bidderResponse},['${oneTimeId}'],${requestData},${publisherURL})</script>`
}, response);
} else if (includes(Object.keys(request.bidRequest.mediaTypes), VIDEO)) {
response = Object.assign({
vastUrl: responseBody.creatives[0].vastURL,
mediaType: VIDEO
}, response);
}
return [response];
}
};

Expand Down
52 changes: 51 additions & 1 deletion test/spec/modules/adhashBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ describe('adhashBidAdapter', function () {
publisherId: '0xc3b09b27e9c6ef73957901aa729b9e69e5bbfbfb'
},
sizes: [[300, 250]],
adUnitCode: 'adUnitCode'
adUnitCode: 'adUnitCode',
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
}
};
it('should build the request correctly', function () {
const result = spec.buildRequests(
Expand Down Expand Up @@ -122,6 +127,11 @@ describe('adhashBidAdapter', function () {
sizes: [[300, 250]],
params: {
platformURL: 'https://adhash.com/p/struma/'
},
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
}
}
};
Expand Down Expand Up @@ -267,5 +277,45 @@ describe('adhashBidAdapter', function () {
it('should return empty array when something is not right', function () {
expect(spec.interpretResponse(null, request).length).to.equal(0);
});

it('should interpret the video response correctly', function () {
const result = spec.interpretResponse({
body: {
creatives: [{ costEUR: 1.234, vastURL: 'https://example.com/vast' }],
advertiserDomains: 'adhash.com'
}
}, {
data: { some: 'data' },
bidRequest: {
bidId: '12345678901234',
adUnitCode: 'adunit-code',
sizes: [[300, 250]],
params: {
platformURL: 'https://adhash.com/p/struma/'
},
mediaTypes: {
video: {
context: 'instream',
playerSize: [300, 250],
mimes: ['video/mp4'],
protocols: [1, 2, 3, 4, 5, 6, 7, 8],
playbackmethod: [2],
skip: 1
}
}
}
});
expect(result.length).to.equal(1);
expect(result[0].requestId).to.equal('12345678901234');
expect(result[0].cpm).to.equal(1.234);
expect(result[0].width).to.equal(300);
expect(result[0].height).to.equal(250);
expect(result[0].creativeId).to.equal('adunit-code');
expect(result[0].netRevenue).to.equal(true);
expect(result[0].currency).to.equal('EUR');
expect(result[0].ttl).to.equal(60);
expect(result[0].meta.advertiserDomains).to.eql(['adhash.com']);
expect(result[0].vastUrl).to.equal('https://example.com/vast');
});
});
});

0 comments on commit 8e3c263

Please sign in to comment.