Skip to content

Commit c64d0ba

Browse files
ChrisHuievadim-mazzherinveraneverah2p4x8
authored
ShowHeroes Bid Adapter: add new endpoint (#8816)
* add ShowHeroes Adapter * ShowHeroes adapter - expanded outstream support * Revert "ShowHeroes adapter - expanded outstream support" This reverts commit bfcdb91. * ShowHeroes adapter - expanded outstream support * ShowHeroes adapter - fixes (#4222) * ShowHeroes adapter - banner and outstream fixes (#4222) * ShowHeroes adapter - description and outstream changes (#4222) * ShowHeroes adapter - increase test coverage and small fix * ShowHeroes Adapter - naming convention issue * Mixed AdUnits declaration support * ITDEV-4723 PrebidJS adapter support with SupplyChain module object * ITDEV-4723 Fix tests * ITDEV-4723 New entry point * showheroes-bsBidAdapter: Add support for advertiserDomains * showheroes-bsBidAdapter: hotfix for outstream render * showheroes-bsBidAdapter: update renderer url * showheroes-bsBidAdapter: use only the necessary fields from the gdprConsent * ShowHeroes adapter - added a new endpoint * ShowHeroes adapter - unit tests * Update showheroes-bsBidAdapter.md * kick off tests Co-authored-by: Eldengrof <[email protected]> Co-authored-by: veranevera <[email protected]> Co-authored-by: Elizaveta Voziyanova <[email protected]>
1 parent b273c57 commit c64d0ba

File tree

3 files changed

+352
-50
lines changed

3 files changed

+352
-50
lines changed

modules/showheroes-bsBidAdapter.js

Lines changed: 130 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
1-
import { deepAccess, getBidIdParameter, getWindowTop, logError } from '../src/utils.js';
1+
import {
2+
deepAccess,
3+
getBidIdParameter,
4+
getWindowTop,
5+
triggerPixel,
6+
logInfo,
7+
logError
8+
} from '../src/utils.js';
29
import { config } from '../src/config.js';
310
import { Renderer } from '../src/Renderer.js';
411
import { registerBidder } from '../src/adapters/bidderFactory.js';
@@ -7,6 +14,7 @@ import { loadExternalScript } from '../src/adloader.js';
714

815
const PROD_ENDPOINT = 'https://bs.showheroes.com/api/v1/bid';
916
const STAGE_ENDPOINT = 'https://bid-service.stage.showheroes.com/api/v1/bid';
17+
const VIRALIZE_ENDPOINT = 'https://ads.viralize.tv/prebid-sh/';
1018
const PROD_PUBLISHER_TAG = 'https://static.showheroes.com/publishertag.js';
1119
const STAGE_PUBLISHER_TAG = 'https://pubtag.stage.showheroes.com/publishertag.js';
1220
const PROD_VL = 'https://video-library.showheroes.com';
@@ -26,12 +34,13 @@ export const spec = {
2634
aliases: ['showheroesBs'],
2735
supportedMediaTypes: [VIDEO, BANNER],
2836
isBidRequestValid: function(bid) {
29-
return !!bid.params.playerId;
37+
return !!bid.params.playerId || !!bid.params.unitId;
3038
},
3139
buildRequests: function(validBidRequests, bidderRequest) {
3240
let adUnits = [];
33-
const pageURL = validBidRequests[0].params.contentPageUrl || bidderRequest.refererInfo.page;
41+
const pageURL = validBidRequests[0].params.contentPageUrl || bidderRequest.refererInfo.referer;
3442
const isStage = !!validBidRequests[0].params.stage;
43+
const isViralize = !!validBidRequests[0].params.unitId;
3544
const isOutstream = deepAccess(validBidRequests[0], 'mediaTypes.video.context') === 'outstream';
3645
const isCustomRender = deepAccess(validBidRequests[0], 'params.outstreamOptions.customRender');
3746
const isNodeRender = deepAccess(validBidRequests[0], 'params.outstreamOptions.slot') || deepAccess(validBidRequests[0], 'params.outstreamOptions.iframe');
@@ -40,12 +49,19 @@ export const spec = {
4049
const isBanner = !!validBidRequests[0].mediaTypes.banner || (isOutstream && !(isCustomRender || isNativeRender || isNodeRender));
4150
const defaultSchain = validBidRequests[0].schain || {};
4251

52+
const consentData = bidderRequest.gdprConsent || {};
53+
const gdprConsent = {
54+
apiVersion: consentData.apiVersion || 2,
55+
gdprApplies: consentData.gdprApplies || 0,
56+
consentString: consentData.consentString || '',
57+
}
58+
4359
validBidRequests.forEach((bid) => {
4460
const videoSizes = getVideoSizes(bid);
4561
const bannerSizes = getBannerSizes(bid);
4662
const vpaidMode = getBidIdParameter('vpaidMode', bid.params);
4763

48-
const makeBids = (type, size) => {
64+
const makeBids = (type, size, isViralize) => {
4965
let context = '';
5066
let streamType = 2;
5167

@@ -61,53 +77,79 @@ export const spec = {
6177
}
6278
}
6379

64-
const consentData = bidderRequest.gdprConsent || {};
65-
66-
const gdprConsent = {
67-
apiVersion: consentData.apiVersion || 2,
68-
gdprApplies: consentData.gdprApplies || 0,
69-
consentString: consentData.consentString || '',
70-
}
71-
72-
return {
80+
let rBid = {
7381
type: streamType,
7482
adUnitCode: bid.adUnitCode,
7583
bidId: bid.bidId,
76-
mediaType: type,
7784
context: context,
78-
playerId: getBidIdParameter('playerId', bid.params),
7985
auctionId: bidderRequest.auctionId,
8086
bidderCode: BIDDER_CODE,
81-
gdprConsent: gdprConsent,
8287
start: +new Date(),
8388
timeout: 3000,
84-
size: {
85-
width: size[0],
86-
height: size[1]
87-
},
8889
params: bid.params,
89-
schain: bid.schain || defaultSchain,
90+
schain: bid.schain || defaultSchain
9091
};
92+
93+
if (isViralize) {
94+
rBid.unitId = getBidIdParameter('unitId', bid.params);
95+
rBid.sizes = size;
96+
rBid.mediaTypes = {
97+
[type]: {'context': context}
98+
};
99+
} else {
100+
rBid.playerId = getBidIdParameter('playerId', bid.params);
101+
rBid.mediaType = type;
102+
rBid.size = {
103+
width: size[0],
104+
height: size[1]
105+
};
106+
rBid.gdprConsent = gdprConsent;
107+
}
108+
109+
return rBid;
91110
};
92111

93-
videoSizes.forEach((size) => {
94-
adUnits.push(makeBids(VIDEO, size));
95-
});
112+
if (isViralize) {
113+
if (videoSizes && videoSizes[0]) {
114+
adUnits.push(makeBids(VIDEO, videoSizes, isViralize));
115+
}
116+
if (bannerSizes && bannerSizes[0]) {
117+
adUnits.push(makeBids(BANNER, bannerSizes, isViralize));
118+
}
119+
} else {
120+
videoSizes.forEach((size) => {
121+
adUnits.push(makeBids(VIDEO, size));
122+
});
96123

97-
bannerSizes.forEach((size) => {
98-
adUnits.push(makeBids(BANNER, size));
99-
});
124+
bannerSizes.forEach((size) => {
125+
adUnits.push(makeBids(BANNER, size));
126+
});
127+
}
100128
});
101129

102-
return {
103-
url: isStage ? STAGE_ENDPOINT : PROD_ENDPOINT,
104-
method: 'POST',
105-
options: {contentType: 'application/json', accept: 'application/json'},
106-
data: {
130+
let endpointUrl;
131+
let data;
132+
133+
const QA = validBidRequests[0].params.qa || {};
134+
135+
if (isViralize) {
136+
endpointUrl = VIRALIZE_ENDPOINT;
137+
data = {
138+
'bidRequests': adUnits,
139+
'context': {
140+
'gdprConsent': gdprConsent,
141+
'schain': defaultSchain,
142+
'pageURL': QA.pageURL || encodeURIComponent(pageURL)
143+
}
144+
}
145+
} else {
146+
endpointUrl = isStage ? STAGE_ENDPOINT : PROD_ENDPOINT;
147+
148+
data = {
107149
'user': [],
108150
'meta': {
109151
'adapterVersion': 2,
110-
'pageURL': encodeURIComponent(pageURL),
152+
'pageURL': QA.pageURL || encodeURIComponent(pageURL),
111153
'vastCacheEnabled': (!!config.getConfig('cache') && !isBanner && !outstreamOptions) || false,
112154
'isDesktop': getWindowTop().document.documentElement.clientWidth > 700,
113155
'xmlAndTag': !!(isOutstream && isCustomRender) || false,
@@ -116,6 +158,13 @@ export const spec = {
116158
'requests': adUnits,
117159
'debug': validBidRequests[0].params.debug || false,
118160
}
161+
}
162+
163+
return {
164+
url: QA.endpoint || endpointUrl,
165+
method: 'POST',
166+
options: {contentType: 'application/json', accept: 'application/json'},
167+
data: data
119168
};
120169
},
121170
interpretResponse: function(response, request) {
@@ -149,33 +198,53 @@ export const spec = {
149198
}
150199
return syncs;
151200
},
201+
202+
onBidWon(bid) {
203+
if (bid.callbacks) {
204+
triggerPixel(bid.callbacks.won);
205+
}
206+
logInfo(
207+
`Showheroes adapter won the auction. Bid id: ${bid.bidId || bid.requestId}`
208+
);
209+
},
152210
};
153211

154212
function createBids(bidRes, reqData) {
155-
if (bidRes && (!Array.isArray(bidRes.bids) || bidRes.bids.length < 1)) {
213+
if (!bidRes) {
214+
return [];
215+
}
216+
const responseBids = bidRes.bids || bidRes.bidResponses;
217+
if (!Array.isArray(responseBids) || responseBids.length < 1) {
156218
return [];
157219
}
158220

159221
const bids = [];
160222
const bidMap = {};
161-
(reqData.requests || []).forEach((bid) => {
223+
(reqData.requests || reqData.bidRequests || []).forEach((bid) => {
162224
bidMap[bid.bidId] = bid;
163225
});
164226

165-
bidRes.bids.forEach(function (bid) {
166-
const reqBid = bidMap[bid.bidId];
227+
responseBids.forEach(function (bid) {
228+
const requestId = bid.bidId || bid.requestId;
229+
const reqBid = bidMap[requestId];
167230
const currentBidParams = reqBid.params;
231+
const isViralize = !!reqBid.params.unitId;
232+
const size = {
233+
width: bid.width || bid.size.width,
234+
height: bid.height || bid.size.height
235+
};
236+
168237
let bidUnit = {};
169238
bidUnit.cpm = bid.cpm;
170-
bidUnit.requestId = bid.bidId;
239+
bidUnit.requestId = requestId;
171240
bidUnit.adUnitCode = reqBid.adUnitCode;
172241
bidUnit.currency = bid.currency;
173242
bidUnit.mediaType = bid.mediaType || VIDEO;
174243
bidUnit.ttl = TTL;
175-
bidUnit.creativeId = 'c_' + bid.bidId;
244+
bidUnit.creativeId = 'c_' + requestId;
176245
bidUnit.netRevenue = true;
177-
bidUnit.width = bid.size.width;
178-
bidUnit.height = bid.size.height;
246+
bidUnit.width = size.width;
247+
bidUnit.height = size.height;
179248
bidUnit.meta = {
180249
advertiserDomains: bid.adomain || []
181250
};
@@ -185,24 +254,26 @@ function createBids(bidRes, reqData) {
185254
content: bid.vastXml,
186255
};
187256
}
188-
if (bid.vastTag) {
189-
bidUnit.vastUrl = bid.vastTag;
257+
if (bid.vastTag || bid.vastUrl) {
258+
bidUnit.vastUrl = bid.vastTag || bid.vastUrl;
190259
}
191260
if (bid.mediaType === BANNER) {
192261
bidUnit.ad = getBannerHtml(bid, reqBid, reqData);
193262
} else if (bid.context === 'outstream') {
194263
const renderer = Renderer.install({
195-
id: bid.bidId,
264+
id: requestId,
196265
url: 'https://static.showheroes.com/renderer.js',
197266
adUnitCode: reqBid.adUnitCode,
198267
config: {
199268
playerId: reqBid.playerId,
200-
width: bid.size.width,
201-
height: bid.size.height,
269+
width: size.width,
270+
height: size.height,
202271
vastUrl: bid.vastTag,
203272
vastXml: bid.vastXml,
273+
ad: bid.ad,
204274
debug: reqData.debug,
205-
isStage: !!reqData.meta.stage,
275+
isStage: reqData.meta && !!reqData.meta.stage,
276+
isViralize: isViralize,
206277
customRender: getBidIdParameter('customRender', currentBidParams.outstreamOptions),
207278
slot: getBidIdParameter('slot', currentBidParams.outstreamOptions),
208279
iframe: getBidIdParameter('iframe', currentBidParams.outstreamOptions),
@@ -218,7 +289,12 @@ function createBids(bidRes, reqData) {
218289
}
219290

220291
function outstreamRender(bid) {
221-
const embedCode = createOutstreamEmbedCode(bid);
292+
let embedCode;
293+
if (bid.renderer.config.isViralize) {
294+
embedCode = createOutstreamEmbedCodeV2(bid);
295+
} else {
296+
embedCode = createOutstreamEmbedCode(bid);
297+
}
222298
if (typeof bid.renderer.config.customRender === 'function') {
223299
bid.renderer.config.customRender(bid, embedCode);
224300
} else {
@@ -266,6 +342,12 @@ function createOutstreamEmbedCode(bid) {
266342
return fragment;
267343
}
268344

345+
function createOutstreamEmbedCodeV2(bid) {
346+
const range = document.createRange();
347+
range.selectNode(document.getElementsByTagName('body')[0]);
348+
return range.createContextualFragment(getBidIdParameter('ad', bid.renderer.config));
349+
}
350+
269351
function getBannerHtml (bid, reqBid, reqData) {
270352
const isStage = !!reqData.meta.stage;
271353
const urls = getEnvURLs(isStage);

modules/showheroes-bsBidAdapter.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,52 @@ Module that connects to ShowHeroes demand source to fetch bids.
125125
}
126126
];
127127
```
128+
129+
# Test Parameters (V2)
130+
```
131+
var adUnits = [
132+
{
133+
code: 'video',
134+
mediaTypes: {
135+
video: {
136+
playerSize: [640, 480],
137+
context: 'instream',
138+
}
139+
},
140+
bids: [
141+
{
142+
bidder: "showheroes-bs",
143+
params: {
144+
unitId: 'AACBWAcof-611K4U',
145+
vpaidMode: true // by default is 'false'
146+
}
147+
}
148+
]
149+
},
150+
{
151+
code: 'video',
152+
mediaTypes: {
153+
video: {
154+
playerSize: [640, 480],
155+
context: 'outstream',
156+
}
157+
},
158+
bids: [
159+
{
160+
bidder: "showheroes-bs",
161+
params: {
162+
unitId: 'AACBTwsZVANd9NlB',
163+
164+
outstreamOptions: {
165+
// Required for the outstream renderer to exact node, one of
166+
iframe: 'iframe_id',
167+
// or
168+
slot: 'slot_id'
169+
}
170+
}
171+
}
172+
]
173+
}
174+
];
175+
```
176+

0 commit comments

Comments
 (0)