Skip to content

Commit 1f428f4

Browse files
wojciech-bialy-wpmWojciech BiałydecemberWP
authored
sspBC Bid Adapter : add support for PAAPI, detection of interstitials, and etc. (prebid#12242)
* Update tests for sspBC adapter Update tests for sspBC adapter: - change userSync test (due to tcf param appended in v4.6) - add tests for onBidWon and onTimeout * [sspbc-adapter] 5.3 updates: content-type for notifications * [sspbc-adapter] pass CTA to native bid * [sspbc-5.3] keep pbsize for detected adunits * [maintenance] - remove old test for sspBc bid adaptor * [sspbc-5.3] increment adaptor ver * [sspbc-adapter] maintenance update to sspBCBidAdapter * remove yarn.lock * Delete package-lock.json * remove package-lock.jsonfrom pull request * [sspbc-adapter] send pageViewId in request * [sspbc-adapter] update pageViewId test * [sspbc-adapter] add viewabiility tracker to native ads * [sspbc-adapter] add support for bid.admNative property * [sspbc-adapter] ensure that placement id length is always 3 (improves matching response to request) * [sspbc-adapter] read publisher id and custom ad label, then send them to banner creative * [sspbc-adapter] adlabel and pubid are set as empty strings, if not present in bid response * [sspbc-adapter] jstracker data fix * [sspbc-adapter] jstracker data fix * [sspbc-adapter] send tagid in notifications * [sspbc-adapter] add gvlid to spec; prepare getUserSyncs for iframe + image sync * update remote repo * cleanup of grupawp/prebid master branch * update sspBC adapter to v 5.9 * update tests for sspBC bid adapter * [sspbc-adapter] add support for topicsFPD module * [sspbc-adapter] change topic segment ids to int * sspbc-5.94: read bid platform * sspbc-5.94 wip * [sspbc-adapter] major version 6.00 (uses backend renderer) * [sspbc-adapter] 6.0 add support for PAAPI component auctions * [sspbc-adapter] default platform value for non-bid notifications * [sspbc-6.0] add default value for native title length * [sspbc-6.0] include interstitial info in request * [sspbc-adapter] update to v6, test coverage and smaller fixes * remove lint console override --------- Co-authored-by: Wojciech Biały <wb@WojciechBialy.local> Co-authored-by: decemberWP <155962474+decemberWP@users.noreply.github.com>
1 parent 1f3b684 commit 1f428f4

File tree

2 files changed

+161
-114
lines changed

2 files changed

+161
-114
lines changed

modules/sspBCBidAdapter.js

Lines changed: 62 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { deepAccess, getWindowTop, isArray, logWarn } from '../src/utils.js';
1+
import { deepAccess, getWindowTop, isArray, logInfo, logWarn } from '../src/utils.js';
22
import { ajax } from '../src/ajax.js';
33
import { config } from '../src/config.js';
44
import { registerBidder } from '../src/adapters/bidderFactory.js';
@@ -12,7 +12,7 @@ const SYNC_URL = 'https://ssp.wp.pl/bidder/usersync';
1212
const NOTIFY_URL = 'https://ssp.wp.pl/bidder/notify';
1313
const GVLID = 676;
1414
const TMAX = 450;
15-
const BIDDER_VERSION = '5.93';
15+
const BIDDER_VERSION = '6.00';
1616
const DEFAULT_CURRENCY = 'PLN';
1717
const W = window;
1818
const { navigator } = W;
@@ -21,7 +21,6 @@ const adUnitsCalled = {};
2121
const adSizesCalled = {};
2222
const bidderRequestsMap = {};
2323
const pageView = {};
24-
var consentApiVersion;
2524

2625
/**
2726
* Native asset mapping - we use constant id per type
@@ -99,14 +98,16 @@ const getNotificationPayload = bidData => {
9998
tagid: [],
10099
}
101100
bids.forEach(bid => {
102-
const { adUnitCode, cpm, creativeId, meta, mediaType, params: bidParams, bidderRequestId, requestId, timeout } = bid;
101+
const { adUnitCode, cpm, creativeId, meta = {}, mediaType, params: bidParams, bidderRequestId, requestId, timeout } = bid;
102+
const { platform = 'wpartner' } = meta;
103103
const params = unpackParams(bidParams);
104104

105105
// basic notification data
106106
const bidBasicData = {
107107
requestId: bidderRequestId || bidderRequestsMap[requestId],
108108
timeout: timeout || result.timeout,
109109
pvid: pageView.id,
110+
platform
110111
}
111112
result = { ...result, ...bidBasicData }
112113

@@ -233,10 +234,9 @@ const applyUserIds = (validBidRequest, ortbRequest) => {
233234
const applyGdpr = (bidderRequest, ortbRequest) => {
234235
const { gdprConsent } = bidderRequest;
235236
if (gdprConsent) {
236-
const { apiVersion, gdprApplies, consentString } = gdprConsent;
237-
consentApiVersion = apiVersion;
238-
ortbRequest.regs = Object.assign(ortbRequest.regs, { 'gdpr': gdprApplies ? 1 : 0 });
239-
ortbRequest.user = Object.assign(ortbRequest.user, { 'consent': consentString });
237+
const { gdprApplies, consentString } = gdprConsent;
238+
ortbRequest.regs = Object.assign(ortbRequest.regs || {}, { 'gdpr': gdprApplies ? 1 : 0 });
239+
ortbRequest.user = Object.assign(ortbRequest.user || {}, { 'consent': consentString });
240240
}
241241
}
242242

@@ -340,7 +340,7 @@ var mapAsset = function mapAsset(paramName, paramValue) {
340340
id: id,
341341
required: required,
342342
title: {
343-
len: len
343+
len: len || 140
344344
}
345345
});
346346
break;
@@ -469,7 +469,7 @@ var mapVideo = (slot, videoFromBid) => {
469469
const mapImpression = slot => {
470470
const { adUnitCode, bidderRequestId, bidId, params = {}, ortb2Imp = {} } = slot;
471471
const { id, siteId, video } = params;
472-
const { ext = {} } = ortb2Imp;
472+
const { instl, ext = {} } = ortb2Imp;
473473

474474
/*
475475
store bidId <-> bidderRequestId mapping for bidWon notification
@@ -497,6 +497,7 @@ const mapImpression = slot => {
497497
video: mapVideo(slot, video),
498498
tagid: adUnitCode,
499499
ext,
500+
instl,
500501
};
501502

502503
// Check floorprices for this imp
@@ -519,6 +520,11 @@ const isNativeAd = bid => {
519520
return bid.admNative || (bid.adm && bid.adm.match(xmlTester));
520521
}
521522

523+
const isHTML = bid => {
524+
const xmlTester = new RegExp(/^<html|<iframe/, 'i');
525+
return bid.adm && bid.adm.match(xmlTester);
526+
}
527+
522528
const parseNative = (nativeData, adUnitCode) => {
523529
const { link = {}, imptrackers: impressionTrackers, jstracker } = nativeData;
524530
const { url: clickUrl, clicktrackers: clickTrackers = [] } = link;
@@ -572,82 +578,6 @@ const parseNative = (nativeData, adUnitCode) => {
572578
return result;
573579
}
574580

575-
const renderCreative = (site, auctionId, bid, seat, request) => {
576-
const { adLabel, id, slot, sn, page, publisherId, ref } = site;
577-
let gam;
578-
579-
const mcad = {
580-
id: auctionId,
581-
seat,
582-
seatbid: [{
583-
bid: [bid],
584-
}],
585-
};
586-
587-
const mcbase = btoa(encodeURI(JSON.stringify(mcad)));
588-
589-
if (bid.adm) {
590-
// parse adm for gam config
591-
try {
592-
gam = JSON.parse(bid.adm).gam;
593-
594-
if (!gam || !Object.keys(gam).length) {
595-
gam = undefined;
596-
} else {
597-
gam.namedSizes = ['fluid'];
598-
gam.div = 'div-gpt-ad-x01';
599-
gam.targeting = Object.assign(gam.targeting || {}, {
600-
OAS_retarg: '0',
601-
PREBID_ON: '1',
602-
emptygaf: '0',
603-
});
604-
}
605-
606-
if (gam && !gam.targeting) {
607-
gam.targeting = {};
608-
}
609-
} catch (err) {
610-
logWarn('Could not parse adm data', bid.adm);
611-
}
612-
}
613-
614-
let adcode = `<head>
615-
<title></title>
616-
<meta charset="UTF-8">
617-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
618-
<style>
619-
body {
620-
background-color: transparent;
621-
margin: 0;
622-
padding: 0;
623-
}
624-
</style>
625-
<script>
626-
window.rekid = ${id};
627-
window.slot = ${parseInt(slot, 10)};
628-
window.responseTimestamp = ${Date.now()};
629-
window.wp_sn = "${sn}";
630-
window.mcad = JSON.parse(decodeURI(atob("${mcbase}")));
631-
window.tcString = "${request.gdprConsent?.consentString || ''}";
632-
window.page = "${page}";
633-
window.ref = "${ref}";
634-
window.adlabel = "${adLabel || ''}";
635-
window.pubid = "${publisherId || ''}";
636-
window.requestPVID = "${pageView.id}";
637-
`;
638-
639-
adcode += `</script>
640-
</head>
641-
<body>
642-
<div id="c"></div>
643-
<script async crossorigin nomodule src="https://std.wpcdn.pl/wpjslib/wpjslib-inline.js" id="wpjslib"></script>
644-
<script async crossorigin type="module" src="https://std.wpcdn.pl/wpjslib6/wpjslib-inline.js" id="wpjslib6"></script>
645-
</body>
646-
</html>`;
647-
648-
return adcode;
649-
}
650-
651581
const spec = {
652582
code: BIDDER_CODE,
653583
gvlid: GVLID,
@@ -714,21 +644,22 @@ const spec = {
714644

715645
interpretResponse(serverResponse, request) {
716646
const { bidderRequest } = request;
717-
const response = serverResponse.body;
647+
const { body: response = {} } = serverResponse;
648+
const { seatbid: responseSeat, ext: responseExt = {} } = response;
649+
const { paapi: fledgeAuctionConfigs = [] } = responseExt;
718650
const bids = [];
719651
let site = JSON.parse(request.data).site; // get page and referer data from request
720652
site.sn = response.sn || 'mc_adapter'; // WPM site name (wp_sn)
721653
pageView.sn = site.sn; // store site_name (for syncing and notifications)
722-
let seat;
723654

724-
if (response.seatbid !== undefined) {
655+
if (responseSeat !== undefined) {
725656
/*
726657
Match response to request, by comparing bid id's
727658
'bidid-' prefix indicates oneCode (parameterless) request and response
728659
*/
729-
response.seatbid.forEach(seatbid => {
730-
seat = seatbid.seat;
731-
seatbid.bid.forEach(serverBid => {
660+
responseSeat.forEach(seatbid => {
661+
const { seat, bid } = seatbid;
662+
bid.forEach(serverBid => {
732663
// get data from bid response
733664
const { adomain, crid = `mcad_${bidderRequest.auctionId}_${site.slot}`, impid, exp = 300, ext = {}, price, w, h } = serverBid;
734665

@@ -744,7 +675,7 @@ const spec = {
744675
const { bidId } = bidRequest || {};
745676

746677
// get ext data from bid
747-
const { siteid = site.id, slotid = site.slot, pubid, adlabel, cache: creativeCache, vurls = [], dsa } = ext;
678+
const { siteid = site.id, slotid = site.slot, pubid, adlabel, cache: creativeCache, vurls = [], dsa, platform = 'wpartner', pricepl } = ext;
748679

749680
// update site data
750681
site = {
@@ -775,8 +706,9 @@ const spec = {
775706
meta: {
776707
advertiserDomains: adomain,
777708
networkName: seat,
778-
pricepl: ext && ext.pricepl,
709+
pricepl,
779710
dsa,
711+
platform,
780712
},
781713
netRevenue: true,
782714
vurls,
@@ -790,6 +722,8 @@ const spec = {
790722
bid.vastXml = serverBid.adm;
791723
bid.vastContent = serverBid.adm;
792724
bid.vastUrl = creativeCache;
725+
726+
logInfo(`Bid ${bid.creativeId} is a video ad`);
793727
} else if (isNativeAd(serverBid)) {
794728
// native
795729
bid.mediaType = 'native';
@@ -803,10 +737,18 @@ const spec = {
803737
logWarn('Could not parse native data', serverBid.adm);
804738
bid.cpm = 0;
805739
}
806-
} else {
807-
// banner ad (default)
740+
logInfo(`Bid ${bid.creativeId} as a native ad`);
741+
} else if (isHTML(serverBid)) {
742+
// banner ad (preformatted)
808743
bid.mediaType = 'banner';
809-
bid.ad = renderCreative(site, response.id, serverBid, seat, bidderRequest);
744+
logInfo(`Bid ${bid.creativeId} as a preformatted banner`);
745+
bid.ad = serverBid.adm;
746+
} else {
747+
// unsupported bid format - send notification and set CPM to zero
748+
const payload = getNotificationPayload(bid);
749+
payload.event = 'parseError';
750+
sendNotification(payload);
751+
bid.cpm = 0;
810752
}
811753

812754
if (bid.cpm > 0) {
@@ -820,15 +762,14 @@ const spec = {
820762
});
821763
}
822764

823-
return bids;
765+
return fledgeAuctionConfigs.length ? { bids, fledgeAuctionConfigs } : bids;
824766
},
825-
getUserSyncs(syncOptions, serverResponses, gdprConsent) {
767+
getUserSyncs(syncOptions) {
826768
let mySyncs = [];
827-
// TODO: the check on CMP api version does not seem to make sense here. It means "always run the usersync unless an old (v1) CMP was detected". No attention is paid to the consent choices.
828-
if (syncOptions.iframeEnabled && consentApiVersion != 1) {
769+
if (syncOptions.iframeEnabled) {
829770
mySyncs.push({
830771
type: 'iframe',
831-
url: `${SYNC_URL}?tcf=${consentApiVersion}&pvid=${pageView.id}&sn=${pageView.sn}`,
772+
url: `${SYNC_URL}?tcf=2&pvid=${pageView.id}&sn=${pageView.sn}`,
832773
});
833774
};
834775
return mySyncs;
@@ -843,6 +784,15 @@ const spec = {
843784
}
844785
},
845786

787+
onBidderError(errorData) {
788+
const payload = getNotificationPayload(errorData);
789+
if (payload) {
790+
payload.event = 'parseError';
791+
sendNotification(payload);
792+
return payload;
793+
}
794+
},
795+
846796
onBidViewable(bid) {
847797
const payload = getNotificationPayload(bid);
848798
if (payload) {
@@ -852,6 +802,15 @@ const spec = {
852802
}
853803
},
854804

805+
onBidBillable(bid) {
806+
const payload = getNotificationPayload(bid);
807+
if (payload) {
808+
payload.event = 'bidBillable';
809+
sendNotification(payload);
810+
return payload;
811+
}
812+
},
813+
855814
onBidWon(bid) {
856815
const payload = getNotificationPayload(bid);
857816
if (payload) {
@@ -860,6 +819,7 @@ const spec = {
860819
return payload;
861820
}
862821
},
822+
863823
};
864824

865825
registerBidder(spec);

0 commit comments

Comments
 (0)