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

Add video support in Grid Bid Adapter #3545

Merged
merged 7 commits into from
Feb 19, 2019
Merged
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
57 changes: 54 additions & 3 deletions modules/gridBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import * as utils from '../src/utils';
import {registerBidder} from '../src/adapters/bidderFactory';
import { Renderer } from '../src/Renderer';
import { VIDEO, BANNER } from '../src/mediaTypes';

const BIDDER_CODE = 'grid';
const ENDPOINT_URL = '//grid.bidswitch.net/hb';
const TIME_TO_LIVE = 360;
const RENDERER_URL = '//cdn.adnxs.com/renderer/video/ANOutstreamVideo.js';

const LOG_ERROR_MESS = {
noAuid: 'Bid from response has no auid parameter - ',
noAdm: 'Bid from response has no adm parameter - ',
Expand All @@ -16,6 +21,7 @@ const LOG_ERROR_MESS = {
};
export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [ BANNER, VIDEO ],
/**
* Determines whether or not the given bid request is valid.
*
Expand Down Expand Up @@ -124,19 +130,39 @@ function _addBidResponse(serverBid, bidsMap, bidResponses) {
const awaitingBids = bidsMap[serverBid.auid];
if (awaitingBids) {
awaitingBids.forEach(bid => {
const size = bid.sizes[0];
if (serverBid.w && serverBid.h) {
size[0] = serverBid.w;
size[1] = serverBid.h;
}
const bidResponse = {
requestId: bid.bidId, // bid.bidderRequestId,
bidderCode: spec.code,
cpm: serverBid.price,
width: serverBid.w,
height: serverBid.h,
width: size[0],
height: size[1],
creativeId: serverBid.auid, // bid.bidId,
currency: 'USD',
netRevenue: false,
ttl: TIME_TO_LIVE,
ad: serverBid.adm,
dealId: serverBid.dealid
};
if (serverBid.content_type === 'video') {
bidResponse.vastXml = serverBid.adm;
bidResponse.mediaType = VIDEO;
bidResponse.adResponse = {
content: bidResponse.vastXml
};
if (!bid.renderer && (!bid.mediaTypes || !bid.mediaTypes.video || bid.mediaTypes.video.context === 'outstream')) {
bidResponse.renderer = createRenderer(bidResponse, {
id: bid.bidId,
url: RENDERER_URL
});
}
} else {
bidResponse.ad = serverBid.adm;
bidResponse.mediaType = BANNER;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi this all looks great,

I have a question as to why when it is video there is no bidResponse.width or bidResponse.height added?

I see it is not sent or returned by your adserver.

You can see in the below screenshot that the KVP that gets set for the size turns out to be undefinedxundefined

image

I have a feeling this may cause problems for certain publishers ad servers maybe?

Do you think it is a good idea to set the width and height based on the bidRequest object?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

width and height are required.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, thank you for the catch, we have updated code, please review again.

bidResponses.push(bidResponse);
});
} else {
Expand All @@ -148,4 +174,29 @@ function _addBidResponse(serverBid, bidsMap, bidResponses) {
}
}

function outstreamRender (bid) {
bid.renderer.push(() => {
window.ANOutstreamVideo.renderAd({
targetId: bid.adUnitCode,
adResponse: bid.adResponse
});
});
}

function createRenderer (bid, rendererParams) {
const renderer = Renderer.install({
id: rendererParams.id,
url: rendererParams.url,
loaded: false
});

try {
renderer.setRender(outstreamRender);
} catch (err) {
utils.logWarn('Prebid Error calling setRender on renderer', err);
}

return renderer;
}

registerBidder(spec);
16 changes: 15 additions & 1 deletion modules/gridBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Maintainer: grid-tech@themediagrid.com
# Description

Module that connects to Grid demand source to fetch bids.
Grid bid adapter supports Banner and Video (instream and outstream).

# Test Parameters
```
Expand Down Expand Up @@ -35,6 +36,19 @@ Module that connects to Grid demand source to fetch bids.
}
}
]
}
},
{
code: 'test-div',
sizes: [[728, 90]],
mediaTypes: { video: {} },
bids: [
{
bidder: "grid",
params: {
uid: 11
}
}
]
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for good test parameters which return valid bid responses!

This is great.

];
```
93 changes: 89 additions & 4 deletions test/spec/modules/gridBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ describe('TheMediaGrid Adapter', function () {

describe('interpretResponse', function () {
const responses = [
{'bid': [{'price': 1.15, 'adm': '<div>test content 1</div>', 'auid': 1, 'h': 250, 'w': 300}], 'seat': '1'},
{'bid': [{'price': 1.15, 'adm': '<div>test content 1</div>', 'auid': 1, 'h': 250, 'w': 300, dealid: 11}], 'seat': '1'},
{'bid': [{'price': 0.5, 'adm': '<div>test content 2</div>', 'auid': 2, 'h': 90, 'w': 728}], 'seat': '1'},
{'bid': [{'price': 0, 'auid': 3, 'h': 250, 'w': 300}], 'seat': '1'},
{'bid': [{'price': 0, 'adm': '<div>test content 4</div>', 'h': 250, 'w': 300}], 'seat': '1'},
Expand Down Expand Up @@ -157,12 +157,13 @@ describe('TheMediaGrid Adapter', function () {
'requestId': '659423fff799cb',
'cpm': 1.15,
'creativeId': 1,
'dealId': undefined,
'dealId': 11,
'width': 300,
'height': 250,
'ad': '<div>test content 1</div>',
'bidderCode': 'grid',
'currency': 'USD',
'mediaType': 'banner',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for > 80% Test Coverage! 👍

'netRevenue': false,
'ttl': 360,
}
Expand Down Expand Up @@ -214,25 +215,27 @@ describe('TheMediaGrid Adapter', function () {
'requestId': '300bfeb0d71a5b',
'cpm': 1.15,
'creativeId': 1,
'dealId': undefined,
'dealId': 11,
'width': 300,
'height': 250,
'ad': '<div>test content 1</div>',
'bidderCode': 'grid',
'currency': 'USD',
'mediaType': 'banner',
'netRevenue': false,
'ttl': 360,
},
{
'requestId': '5703af74d0472a',
'cpm': 1.15,
'creativeId': 1,
'dealId': undefined,
'dealId': 11,
'width': 300,
'height': 250,
'ad': '<div>test content 1</div>',
'bidderCode': 'grid',
'currency': 'USD',
'mediaType': 'banner',
'netRevenue': false,
'ttl': 360,
},
Expand All @@ -246,6 +249,7 @@ describe('TheMediaGrid Adapter', function () {
'ad': '<div>test content 2</div>',
'bidderCode': 'grid',
'currency': 'USD',
'mediaType': 'banner',
'netRevenue': false,
'ttl': 360,
}
Expand All @@ -255,6 +259,87 @@ describe('TheMediaGrid Adapter', function () {
expect(result).to.deep.equal(expectedResponse);
});

it('should get correct video bid response', function () {
const bidRequests = [
{
'bidder': 'grid',
'params': {
'uid': '1'
},
'adUnitCode': 'adunit-code-1',
'sizes': [[300, 250], [300, 600]],
'bidId': '659423fff799cb',
'bidderRequestId': '5f2009617a7c0a',
'auctionId': '1cbd2feafe5e8b',
'mediaTypes': {
'video': {
'context': 'instream'
}
}
},
{
'bidder': 'grid',
'params': {
'uid': '2'
},
'adUnitCode': 'adunit-code-1',
'sizes': [[300, 250], [300, 600]],
'bidId': '2bc598e42b6a',
'bidderRequestId': '5f2009617a7c0a',
'auctionId': '1cbd2feafe5e8b',
'mediaTypes': {
'video': {
'context': 'instream'
}
}
}
];
const response = [
{'bid': [{'price': 1.15, 'adm': '<VAST version=\"3.0\">\n<Ad id=\"21341234\"><\/Ad>\n<\/VAST>', 'auid': 1, content_type: 'video', w: 300, h: 600}], 'seat': '2'},
{'bid': [{'price': 1.00, 'adm': '<VAST version=\"3.0\">\n<Ad id=\"21331274\"><\/Ad>\n<\/VAST>', 'auid': 2, content_type: 'video'}], 'seat': '2'}
];
const request = spec.buildRequests(bidRequests);
const expectedResponse = [
{
'requestId': '659423fff799cb',
'cpm': 1.15,
'creativeId': 1,
'dealId': undefined,
'width': 300,
'height': 600,
'bidderCode': 'grid',
'currency': 'USD',
'mediaType': 'video',
'netRevenue': false,
'ttl': 360,
'vastXml': '<VAST version=\"3.0\">\n<Ad id=\"21341234\"><\/Ad>\n<\/VAST>',
'adResponse': {
'content': '<VAST version=\"3.0\">\n<Ad id=\"21341234\"><\/Ad>\n<\/VAST>'
}
},
{
'requestId': '2bc598e42b6a',
'cpm': 1.00,
'creativeId': 2,
'dealId': undefined,
'width': 300,
'height': 250,
'bidderCode': 'grid',
'currency': 'USD',
'mediaType': 'video',
'netRevenue': false,
'ttl': 360,
'vastXml': '<VAST version=\"3.0\">\n<Ad id=\"21331274\"><\/Ad>\n<\/VAST>',
'adResponse': {
'content': '<VAST version=\"3.0\">\n<Ad id=\"21331274\"><\/Ad>\n<\/VAST>'
}
}
];

const result = spec.interpretResponse({'body': {'seatbid': response}}, request);
expect(result).to.deep.equal(expectedResponse);
});

it('handles wrong and nobid responses', function () {
const bidRequests = [
{
Expand Down