prebid.js 9.52.0 → 9.53.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.circleci/config.yml +27 -4
- package/creative/crossDomain.js +4 -2
- package/dist/33acrossAnalyticsAdapter.js +1 -1
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/BTBidAdapter.js +1 -1
- package/dist/adagioAnalyticsAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adagioUtils.js +1 -1
- package/dist/addefendBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adlooxRtdProvider.js +1 -1
- package/dist/adqueryBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adstirBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgAnalyticsAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adyoulikeBidAdapter.js +1 -1
- package/dist/agmaAnalyticsAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/aniviewBidAdapter.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/beopBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bitmediaBidAdapter.js +1 -1
- package/dist/bridBidAdapter.js +1 -1
- package/dist/bridgeuppBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/chromeAiRtdProvider.js +1 -0
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/chunk-core.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/contxtfulBidAdapter.js +1 -1
- package/dist/conversantAnalyticsAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/cwireBidAdapter.js +1 -1
- package/dist/dailymotionBidAdapter.js +1 -1
- package/dist/debugging-standalone.js +1 -1
- package/dist/dependencies.json +10 -2
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/dxkultureBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/equativBidAdapter.js +1 -1
- package/dist/eskimiBidAdapter.js +1 -1
- package/dist/euidIdSystem.js +1 -1
- package/dist/exadsBidAdapter.js +1 -1
- package/dist/excoBidAdapter.js +1 -1
- package/dist/fanAdapter.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freewheel-sspBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/greenbidsAnalyticsAdapter.js +1 -1
- package/dist/greenbidsBidAdapter.js +1 -1
- package/dist/greenbidsRtdProvider.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/hypelabBidAdapter.js +1 -1
- package/dist/id5AnalyticsAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/imdsBidAdapter.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmobiBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/intentIqAnalyticsAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/jixieBidAdapter.js +1 -1
- package/dist/jixieIdSystem.js +1 -0
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoBidAdapter.js +1 -1
- package/dist/kimberliteBidAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/lifestreetBidAdapter.js +1 -1
- package/dist/liveIntentId.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/luceadBidAdapter.js +1 -1
- package/dist/mabidderBidAdapter.js +1 -1
- package/dist/madsenseBidAdapter.js +1 -1
- package/dist/magniteAnalyticsAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/medianetBidAdapter.js +1 -1
- package/dist/medianetUtils.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/missenaBidAdapter.js +1 -1
- package/dist/mobilefuseBidAdapter.js +1 -1
- package/dist/nextMillenniumBidAdapter.js +1 -1
- package/dist/nexx360Utils.js +1 -1
- package/dist/nobidAnalyticsAdapter.js +1 -1
- package/dist/nobidBidAdapter.js +1 -1
- package/dist/nodalsAiRtdProvider.js +1 -1
- package/dist/not-for-prod/prebid.js +175 -173
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxBidAdapter.js +1 -1
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/orbidderBidAdapter.js +1 -1
- package/dist/ortb2.5Translator.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/ozoneBidAdapter.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebidServerBidAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticAnalyticsAdapter.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubmaticRtdProvider.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pubxaiAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/relevatehealthBidAdapter.js +1 -1
- package/dist/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseUtils.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/showheroes-bsBidAdapter.js +1 -1
- package/dist/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/snigelBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sparteoBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/stvBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/taboolaBidAdapter.js +1 -1
- package/dist/tappxBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/terceptAnalyticsAdapter.js +1 -1
- package/dist/themoneytizerBidAdapter.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.js +1 -1
- package/dist/uid2IdSystem.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/unrulyBidAdapter.js +1 -1
- package/dist/userId.js +1 -1
- package/dist/vidazooUtils.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahooAdsBidAdapter.js +1 -1
- package/dist/yandexBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/gulpfile.js +12 -6
- package/integrationExamples/chromeai/japanese.html +224 -0
- package/integrationExamples/gpt/x-domain/creative.html +1 -1
- package/karma.conf.maker.js +7 -7
- package/karmaRunner.js +3 -3
- package/libraries/liveIntentId/shared.js +16 -0
- package/modules/.submodules.json +1 -0
- package/modules/aniviewBidAdapter.js +32 -23
- package/modules/chromeAiRtdProvider.js +421 -0
- package/modules/chromeAiRtdProvider.md +230 -0
- package/modules/fanAdapter.js +318 -124
- package/modules/ixBidAdapter.js +5 -0
- package/modules/jixieIdSystem.js +186 -0
- package/modules/ozoneBidAdapter.js +214 -336
- package/modules/prebidServerBidAdapter/index.js +59 -35
- package/modules/pubmaticRtdProvider.js +418 -4
- package/modules/pubmaticRtdProvider.md +12 -2
- package/modules/relevatehealthBidAdapter.js +20 -130
- package/modules/relevatehealthBidAdapter.md +1 -2
- package/modules/sovrnBidAdapter.js +4 -4
- package/modules/teadsBidAdapter.js +5 -0
- package/modules/ttdBidAdapter.js +5 -4
- package/modules/userId/index.js +30 -31
- package/package.json +5 -4
- package/src/adapterManager.js +3 -0
- package/test/spec/libraries/cmUtils_spec.js +17 -12
- package/test/spec/modules/aniviewBidAdapter_spec.js +15 -2
- package/test/spec/modules/chromeAiRtdProvider_spec.js +393 -0
- package/test/spec/modules/dgkeywordRtdProvider_spec.js +5 -2
- package/test/spec/modules/euidIdSystem_spec.js +9 -3
- package/test/spec/modules/fanAdapter_spec.js +264 -268
- package/test/spec/modules/id5IdSystem_spec.js +57 -101
- package/test/spec/modules/identityLinkIdSystem_spec.js +1 -0
- package/test/spec/modules/idxIdSystem_spec.js +2 -75
- package/test/spec/modules/instreamTracking_spec.js +15 -18
- package/test/spec/modules/ixBidAdapter_spec.js +26 -0
- package/test/spec/modules/jixieIdSystem_spec.js +303 -0
- package/test/spec/modules/liveIntentExternalIdSystem_spec.js +5 -0
- package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +5 -0
- package/test/spec/modules/liveIntentIdSystem_spec.js +38 -0
- package/test/spec/modules/lmpIdSystem_spec.js +2 -81
- package/test/spec/modules/ozoneBidAdapter_spec.js +511 -658
- package/test/spec/modules/prebidServerBidAdapter_spec.js +72 -2
- package/test/spec/modules/pubmaticBidAdapter_spec.js +411 -126
- package/test/spec/modules/pubmaticRtdProvider_spec.js +946 -2
- package/test/spec/modules/raynRtdProvider_spec.js +18 -22
- package/test/spec/modules/relevatehealthBidAdapter_spec.js +9 -39
- package/test/spec/modules/sharedIdSystem_spec.js +3 -3
- package/test/spec/modules/sovrnBidAdapter_spec.js +71 -3
- package/test/spec/modules/teadsBidAdapter_spec.js +9 -4
- package/test/spec/modules/ttdBidAdapter_spec.js +24 -2
- package/test/spec/modules/uid2IdSystem_helpers.js +5 -2
- package/test/spec/modules/userId_spec.js +142 -387
- package/test/spec/modules/yieldoneAnalyticsAdapter_spec.js +13 -12
- package/test/spec/modules/zeotapIdPlusIdSystem_spec.js +3 -69
- package/wdio.shared.conf.js +2 -2
- package/CLAUDE.md +0 -1
package/modules/fanAdapter.js
CHANGED
|
@@ -1,176 +1,370 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { ajax } from '../src/ajax.js';
|
|
3
|
-
import { BANNER, NATIVE } from '../src/mediaTypes.js';
|
|
1
|
+
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
|
|
4
2
|
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* @typedef {import('../src/adapters/bidderFactory.js').ServerResponse} ServerResponse
|
|
11
|
-
*/
|
|
3
|
+
import { BANNER, VIDEO } from '../src/mediaTypes.js';
|
|
4
|
+
import { deepAccess, deepSetValue, logInfo, logWarn, logError, triggerPixel } from '../src/utils.js';
|
|
5
|
+
import { getStorageManager } from '../src/storageManager.js';
|
|
6
|
+
import { Renderer } from '../src/Renderer.js';
|
|
7
|
+
import { getGptSlotInfoForAdUnitCode } from '../libraries/gptUtils/gptUtils.js';
|
|
12
8
|
|
|
13
9
|
const BIDDER_CODE = 'freedomadnetwork';
|
|
14
|
-
const
|
|
10
|
+
const BIDDER_VERSION = '0.2.0';
|
|
11
|
+
const NETWORK_ENDPOINTS = {
|
|
12
|
+
'fan': 'https://srv.freedomadnetwork.com/ortb',
|
|
13
|
+
'armanet': 'https://srv.armanet.us/ortb',
|
|
14
|
+
'test': 'http://localhost:8001/ortb',
|
|
15
|
+
};
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* @param {BidRequest} bid
|
|
20
|
-
* @param {BidderRequest} bidderRequest
|
|
21
|
-
* @returns {Request}
|
|
22
|
-
*/
|
|
23
|
-
function buildBidRequest(bid, bidderRequest) {
|
|
24
|
-
const payload = {
|
|
25
|
-
id: bid.bidId,
|
|
26
|
-
tmax: bidderRequest.timeout,
|
|
27
|
-
placements: [bid.params.placementId],
|
|
28
|
-
at: 1,
|
|
29
|
-
user: {}
|
|
30
|
-
}
|
|
17
|
+
const DEFAULT_ENDPOINT = NETWORK_ENDPOINTS['fan'];
|
|
18
|
+
const DEFAULT_CURRENCY = 'USD';
|
|
19
|
+
const DEFAULT_TTL = 300;
|
|
31
20
|
|
|
32
|
-
|
|
33
|
-
if (!!gdprConsent && gdprConsent.gdprApplies) {
|
|
34
|
-
payload.user.gdpr = 1;
|
|
35
|
-
payload.user.consent = gdprConsent.consentString;
|
|
36
|
-
}
|
|
21
|
+
export const storage = getStorageManager({bidderCode: BIDDER_CODE});
|
|
37
22
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
23
|
+
const converter = ortbConverter({
|
|
24
|
+
context: {
|
|
25
|
+
netRevenue: true,
|
|
26
|
+
ttl: DEFAULT_TTL,
|
|
27
|
+
currency: DEFAULT_CURRENCY
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
imp(buildImp, bidRequest, context) {
|
|
31
|
+
const imp = buildImp(bidRequest, context);
|
|
32
|
+
|
|
33
|
+
// Add custom fields to impression
|
|
34
|
+
if (bidRequest.params.placementId) {
|
|
35
|
+
imp.tagid = bidRequest.params.placementId;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Add floor price
|
|
39
|
+
if (bidRequest.params.bidFloor) {
|
|
40
|
+
imp.bidfloor = parseFloat(bidRequest.params.bidFloor);
|
|
41
|
+
imp.bidfloorcur = bidRequest.params.bidFloorCur || DEFAULT_CURRENCY;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Add custom extensions
|
|
45
|
+
deepSetValue(imp, 'ext.prebid.storedrequest.id', bidRequest.params.placementId);
|
|
46
|
+
deepSetValue(imp, 'ext.bidder', {
|
|
47
|
+
network: bidRequest.params.network || 'fan',
|
|
48
|
+
placementId: bidRequest.params.placementId
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
return imp;
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
request(buildRequest, imps, bidderRequest, context) {
|
|
55
|
+
const request = buildRequest(imps, bidderRequest, context);
|
|
56
|
+
|
|
57
|
+
// First price auction
|
|
58
|
+
request.at = 1;
|
|
59
|
+
request.cur = [DEFAULT_CURRENCY];
|
|
60
|
+
|
|
61
|
+
// Add source information
|
|
62
|
+
deepSetValue(request, 'source.tid', bidderRequest.auctionId);
|
|
63
|
+
|
|
64
|
+
// Add custom extensions
|
|
65
|
+
deepSetValue(request, 'ext.prebid.channel', BIDDER_CODE);
|
|
66
|
+
deepSetValue(request, 'ext.prebid.version', BIDDER_VERSION);
|
|
67
|
+
|
|
68
|
+
// Add user extensions
|
|
69
|
+
const firstBid = imps[0];
|
|
70
|
+
const pbUser = firstBid.userId || {};
|
|
71
|
+
request.user = request.user || {};
|
|
72
|
+
request.user.ext = request.user.ext || {};
|
|
42
73
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
74
|
+
if (pbUser.tdid) {
|
|
75
|
+
request.user.ext.tdid = pbUser.tdid;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (window.geck) {
|
|
79
|
+
request.user.ext.adi = window.geck;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (pbUser.pubcid) {
|
|
83
|
+
request.user.ext.pubcid = pbUser.pubcid;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (pbUser.id5id?.uid) {
|
|
87
|
+
request.user.ext.id5id = pbUser.id5id.uid;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (pbUser.lipb?.lipbid) {
|
|
91
|
+
request.user.ext.lipbid = pbUser.lipb.lipbid;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return request;
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
bidResponse(buildBidResponse, bid, context) {
|
|
98
|
+
const { bidRequest } = context;
|
|
99
|
+
const bidResponse = buildBidResponse(bid, context);
|
|
100
|
+
|
|
101
|
+
// Add custom bid response fields
|
|
102
|
+
bidResponse.meta = bidResponse.meta || {};
|
|
103
|
+
bidResponse.meta.networkName = BIDDER_CODE;
|
|
104
|
+
bidResponse.meta.advertiserDomains = bid.adomain || [];
|
|
105
|
+
|
|
106
|
+
if (bid.ext && bid.ext.libertas) {
|
|
107
|
+
bidResponse.meta.libertas = bid.ext.libertas;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Add tracking URLs
|
|
111
|
+
if (bid.nurl) {
|
|
112
|
+
bidResponse.nurl = bid.nurl;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Handle different ad formats
|
|
116
|
+
if (bidResponse.mediaType === BANNER) {
|
|
117
|
+
bidResponse.ad = bid.adm;
|
|
118
|
+
bidResponse.width = bid.w;
|
|
119
|
+
bidResponse.height = bid.h;
|
|
120
|
+
} else if (bidResponse.mediaType === VIDEO) {
|
|
121
|
+
bidResponse.vastXml = bid.adm;
|
|
122
|
+
bidResponse.width = bid.w;
|
|
123
|
+
bidResponse.height = bid.h;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Add renderer if needed for outstream video
|
|
127
|
+
if (bidResponse.mediaType === VIDEO && bid.ext.libertas.ovp) {
|
|
128
|
+
bidResponse.width = bid.w;
|
|
129
|
+
bidResponse.height = bid.h;
|
|
130
|
+
bidResponse.renderer = createRenderer(bidRequest, bid.ext.libertas.vp);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return bidResponse;
|
|
55
134
|
}
|
|
56
|
-
}
|
|
135
|
+
});
|
|
57
136
|
|
|
58
137
|
export const spec = {
|
|
59
138
|
code: BIDDER_CODE,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
139
|
+
supportedMediaTypes: [BANNER, VIDEO],
|
|
140
|
+
|
|
141
|
+
isBidRequestValid(bid) {
|
|
142
|
+
// Validate minimum required parameters
|
|
143
|
+
if (!bid.params) {
|
|
144
|
+
logError(`${BIDDER_CODE}: bid.params is required`);
|
|
63
145
|
|
|
64
146
|
return false;
|
|
65
147
|
}
|
|
66
148
|
|
|
67
|
-
|
|
68
|
-
|
|
149
|
+
// Validate placement ID
|
|
150
|
+
if (!bid.params.placementId) {
|
|
151
|
+
logError(`${BIDDER_CODE}: placementId is required`);
|
|
69
152
|
|
|
70
153
|
return false;
|
|
71
154
|
}
|
|
72
155
|
|
|
73
|
-
|
|
74
|
-
|
|
156
|
+
// Validate network parameter
|
|
157
|
+
if (bid.params.network && !NETWORK_ENDPOINTS[bid.params.network]) {
|
|
158
|
+
logError(`${BIDDER_CODE}: Invalid network: ${bid.params.network}`);
|
|
75
159
|
|
|
76
160
|
return false;
|
|
77
161
|
}
|
|
78
162
|
|
|
79
|
-
|
|
80
|
-
if (banner
|
|
163
|
+
// Validate media types
|
|
164
|
+
if (!bid.mediaTypes || (!bid.mediaTypes.banner && !bid.mediaTypes.video)) {
|
|
165
|
+
logError(`${BIDDER_CODE}: Only banner and video mediaTypes are supported`);
|
|
166
|
+
|
|
81
167
|
return false;
|
|
82
168
|
}
|
|
83
169
|
|
|
170
|
+
// Validate video parameters if video mediaType is present
|
|
171
|
+
if (bid.mediaTypes.video) {
|
|
172
|
+
const video = bid.mediaTypes.video;
|
|
173
|
+
if (!video.mimes || !Array.isArray(video.mimes) || video.mimes.length === 0) {
|
|
174
|
+
logError(`${BIDDER_CODE}: video.mimes is required for video ads`);
|
|
175
|
+
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!video.playerSize || !Array.isArray(video.playerSize)) {
|
|
180
|
+
logError(`${BIDDER_CODE}: video.playerSize is required for video ads`);
|
|
181
|
+
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
84
186
|
return true;
|
|
85
187
|
},
|
|
86
188
|
|
|
87
|
-
|
|
88
|
-
|
|
189
|
+
/**
|
|
190
|
+
* Make server requests from the list of BidRequests
|
|
191
|
+
*/
|
|
192
|
+
buildRequests(validBidRequests, bidderRequest) {
|
|
193
|
+
const requestsByNetwork = validBidRequests.reduce((acc, bid) => {
|
|
194
|
+
const network = bid.params.network || 'fan';
|
|
195
|
+
if (!acc[network]) {
|
|
196
|
+
acc[network] = [];
|
|
197
|
+
}
|
|
198
|
+
acc[network].push(bid);
|
|
199
|
+
|
|
200
|
+
return acc;
|
|
201
|
+
}, {});
|
|
202
|
+
|
|
203
|
+
return Object.entries(requestsByNetwork).map(([network, bids]) => {
|
|
204
|
+
const data = converter.toORTB({
|
|
205
|
+
bidRequests: bids,
|
|
206
|
+
bidderRequest,
|
|
207
|
+
context: { network }
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
return {
|
|
211
|
+
method: 'POST',
|
|
212
|
+
url: NETWORK_ENDPOINTS[network] || DEFAULT_ENDPOINT,
|
|
213
|
+
data,
|
|
214
|
+
options: {
|
|
215
|
+
contentType: 'application/json',
|
|
216
|
+
withCredentials: false
|
|
217
|
+
},
|
|
218
|
+
bids
|
|
219
|
+
};
|
|
220
|
+
});
|
|
89
221
|
},
|
|
90
222
|
|
|
91
223
|
/**
|
|
92
|
-
* Unpack the response from the server into a list of bids
|
|
93
|
-
*
|
|
94
|
-
* @param {ServerResponse} serverResponse A successful response from the server.
|
|
95
|
-
* @return {Bid[]} An array of bids which were nested inside the server.
|
|
224
|
+
* Unpack the response from the server into a list of bids
|
|
96
225
|
*/
|
|
97
|
-
interpretResponse
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
if (!serverBody) {
|
|
102
|
-
return bidResponses;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
serverBody.forEach((response) => {
|
|
106
|
-
const bidResponse = {
|
|
107
|
-
requestId: response.id,
|
|
108
|
-
bidid: response.bidid,
|
|
109
|
-
impid: response.impid,
|
|
110
|
-
userId: response.userId,
|
|
111
|
-
cpm: response.cpm,
|
|
112
|
-
currency: response.currency,
|
|
113
|
-
width: response.width,
|
|
114
|
-
height: response.height,
|
|
115
|
-
ad: response.payload,
|
|
116
|
-
ttl: response.ttl,
|
|
117
|
-
creativeId: response.crid,
|
|
118
|
-
netRevenue: response.netRevenue,
|
|
119
|
-
trackers: response.trackers,
|
|
120
|
-
meta: {
|
|
121
|
-
mediaType: response.mediaType,
|
|
122
|
-
advertiserDomains: response.domains,
|
|
123
|
-
}
|
|
124
|
-
};
|
|
226
|
+
interpretResponse(serverResponse, bidRequest) {
|
|
227
|
+
if (!serverResponse.body) {
|
|
228
|
+
return [];
|
|
229
|
+
}
|
|
125
230
|
|
|
126
|
-
|
|
231
|
+
const response = converter.fromORTB({
|
|
232
|
+
response: serverResponse.body,
|
|
233
|
+
request: bidRequest.data,
|
|
127
234
|
});
|
|
128
235
|
|
|
129
|
-
return
|
|
236
|
+
return response.bids || [];
|
|
130
237
|
},
|
|
131
238
|
|
|
132
239
|
/**
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
* @param {Bid} bid The bid that won the auction
|
|
240
|
+
* Handle bidder errors
|
|
136
241
|
*/
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
242
|
+
onBidderError: function(error) {
|
|
243
|
+
logError(`${BIDDER_CODE} bidder error`, error);
|
|
244
|
+
},
|
|
141
245
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
246
|
+
/**
|
|
247
|
+
* Register user sync pixels
|
|
248
|
+
*/
|
|
249
|
+
getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) {
|
|
250
|
+
if (!syncOptions.iframeEnabled && !syncOptions.pixelEnabled) {
|
|
251
|
+
return [];
|
|
147
252
|
}
|
|
148
253
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
254
|
+
const syncs = [];
|
|
255
|
+
const seenUrls = new Set();
|
|
256
|
+
|
|
257
|
+
serverResponses.forEach(response => {
|
|
258
|
+
const userSync = deepAccess(response.body, 'ext.sync');
|
|
259
|
+
if (!userSync) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if (syncOptions.iframeEnabled && userSync.iframe) {
|
|
264
|
+
userSync.iframe.forEach(sync => {
|
|
265
|
+
const url = buildSyncUrl(sync.url, gdprConsent, uspConsent, gppConsent);
|
|
266
|
+
if (!seenUrls.has(url)) {
|
|
267
|
+
seenUrls.add(url);
|
|
268
|
+
syncs.push({
|
|
269
|
+
type: 'iframe',
|
|
270
|
+
url
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
if (syncOptions.pixelEnabled && userSync.image) {
|
|
277
|
+
userSync.image.forEach(sync => {
|
|
278
|
+
const url = buildSyncUrl(sync.url, gdprConsent, uspConsent, gppConsent);
|
|
279
|
+
if (!seenUrls.has(url)) {
|
|
280
|
+
seenUrls.add(url);
|
|
281
|
+
syncs.push({
|
|
282
|
+
type: 'image',
|
|
283
|
+
url
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
});
|
|
287
|
+
}
|
|
154
288
|
});
|
|
155
289
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
290
|
+
return syncs;
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Handle bid won event
|
|
295
|
+
*/
|
|
296
|
+
onBidWon(bid) {
|
|
297
|
+
logInfo(`${BIDDER_CODE}: Bid won`, bid);
|
|
298
|
+
|
|
299
|
+
if (bid.nurl) {
|
|
300
|
+
triggerPixel(bid.nurl);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (bid.meta.libertas.pxl && bid.meta.libertas.pxl.length > 0) {
|
|
304
|
+
for (var i = 0; i < bid.meta.libertas.pxl.length; i++) {
|
|
305
|
+
if (bid.meta.libertas.pxl[i].type == 0) {
|
|
306
|
+
triggerPixel(bid.meta.libertas.pxl[i].url);
|
|
160
307
|
}
|
|
161
308
|
}
|
|
162
309
|
}
|
|
163
310
|
},
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Build sync URL with privacy parameters
|
|
315
|
+
*/
|
|
316
|
+
function buildSyncUrl(baseUrl, gdprConsent, uspConsent, gppConsent) {
|
|
317
|
+
try {
|
|
318
|
+
const url = new URL(baseUrl);
|
|
319
|
+
|
|
320
|
+
if (gdprConsent) {
|
|
321
|
+
url.searchParams.set('gdpr', gdprConsent.gdprApplies ? '1' : '0');
|
|
322
|
+
if (gdprConsent.consentString) {
|
|
323
|
+
url.searchParams.set('gdpr_consent', gdprConsent.consentString);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (uspConsent) {
|
|
328
|
+
url.searchParams.set('us_privacy', uspConsent);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (gppConsent?.gppString) {
|
|
332
|
+
url.searchParams.set('gpp', gppConsent.gppString);
|
|
333
|
+
if (gppConsent.applicableSections?.length) {
|
|
334
|
+
url.searchParams.set('gpp_sid', gppConsent.applicableSections.join(','));
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return url.toString();
|
|
339
|
+
} catch (e) {
|
|
340
|
+
logWarn(`${BIDDER_CODE}: Invalid sync URL: ${baseUrl}`);
|
|
341
|
+
|
|
342
|
+
return baseUrl;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Create renderer for outstream video
|
|
348
|
+
*/
|
|
349
|
+
function createRenderer(bid, videoPlayerUrl) {
|
|
350
|
+
const renderer = Renderer.install({
|
|
351
|
+
url: videoPlayerUrl,
|
|
352
|
+
loaded: false,
|
|
353
|
+
adUnitCode: bid.adUnitCode,
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
try {
|
|
357
|
+
renderer.setRender(function (bidResponse) {
|
|
358
|
+
const divId = document.getElementById(bid.adUnitCode) ? bid.adUnitCode : getGptSlotInfoForAdUnitCode(bid.adUnitCode).divId;
|
|
359
|
+
const adUnit = document.getElementById(divId);
|
|
360
|
+
|
|
361
|
+
window.createOutstreamPlayer(adUnit, bidResponse.vastXml, bid.width, bid.height);
|
|
362
|
+
});
|
|
363
|
+
} catch (error) {
|
|
364
|
+
logWarn('Renderer error: setRender() failed', error);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
return renderer;
|
|
174
368
|
}
|
|
175
369
|
|
|
176
370
|
registerBidder(spec);
|
package/modules/ixBidAdapter.js
CHANGED
|
@@ -1188,6 +1188,11 @@ function addFPD(bidderRequest, r, fpd, site, user) {
|
|
|
1188
1188
|
if (ipv6) {
|
|
1189
1189
|
deepSetValue(r, 'device.ipv6', ipv6);
|
|
1190
1190
|
}
|
|
1191
|
+
|
|
1192
|
+
const geo = fpd.device.geo;
|
|
1193
|
+
if (geo) {
|
|
1194
|
+
deepSetValue(r, 'device.geo', geo);
|
|
1195
|
+
}
|
|
1191
1196
|
}
|
|
1192
1197
|
|
|
1193
1198
|
// regulations from ortb2
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This module adds the jixie to the User ID module
|
|
3
|
+
* The {@link module:modules/userId} module is required
|
|
4
|
+
* @module modules/jixieIdSystem
|
|
5
|
+
* @requires module:modules/userId
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { submodule } from '../src/hook.js';
|
|
9
|
+
import { getStorageManager } from '../src/storageManager.js';
|
|
10
|
+
import { ajax } from '../src/ajax.js';
|
|
11
|
+
import { parseUrl, buildUrl, isPlainObject, timestamp } from '../src/utils.js';
|
|
12
|
+
import { MODULE_TYPE_UID } from '../src/activities/modules.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {import('../modules/userId/index.js').Submodule} Submodule
|
|
16
|
+
* @typedef {import('../modules/userId/index.js').SubmoduleConfig} SubmoduleConfig
|
|
17
|
+
* @typedef {import('../modules/userId/index.js').ConsentData} ConsentData
|
|
18
|
+
* @typedef {import('../modules/userId/index.js').IdResponse} IdResponse
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const MODULE_NAME = 'jixieId';
|
|
22
|
+
const STD_JXID_KEY = '_jxx';
|
|
23
|
+
const PBJS_JXID_KEY = 'pbjx_jxx';
|
|
24
|
+
const PBJS_IDLOGSTR_KEY = 'pbjx_idlog';
|
|
25
|
+
const TRACKER_EP_FROM_IDMODULE = 'https://traid.jixie.io/api/usersyncpbjs'
|
|
26
|
+
const CK_LIFE_DAYS = 365;
|
|
27
|
+
const ONE_YEAR_IN_MS = 365 * 24 * 60 * 60 * 1000;
|
|
28
|
+
|
|
29
|
+
export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME });
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* remove any property in obj that is null or undefined
|
|
33
|
+
* @param {*} obj
|
|
34
|
+
*/
|
|
35
|
+
function removeNullProp(obj) {
|
|
36
|
+
for (const key in obj) {
|
|
37
|
+
if (obj[key] === null || obj[key] === undefined) {
|
|
38
|
+
delete obj[key];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* save the info returned by our endpoint into cookie
|
|
45
|
+
* @param {object} response
|
|
46
|
+
*/
|
|
47
|
+
function persistExtInfo(response) {
|
|
48
|
+
let o = response;
|
|
49
|
+
if (o) {
|
|
50
|
+
const ageMS = (CK_LIFE_DAYS) * 24 * 60 * 60 * 1000;
|
|
51
|
+
const expireDT = new Date(timestamp() + ageMS).toUTCString();
|
|
52
|
+
if (o.client_id) {
|
|
53
|
+
storage.setCookie(PBJS_JXID_KEY, o.client_id, expireDT);
|
|
54
|
+
}
|
|
55
|
+
if (o.idlog) {
|
|
56
|
+
storage.setCookie(PBJS_IDLOGSTR_KEY, o.idlog, expireDT);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* build the full url to call the jixie endpoint
|
|
63
|
+
* @param {Object} params - config params from the pbjs setup
|
|
64
|
+
* @param {Object} gdprConsent
|
|
65
|
+
* @returns {string} a full url to call by ajax
|
|
66
|
+
*/
|
|
67
|
+
function buildIdCallUrl(params, gdprConsent) {
|
|
68
|
+
let url = parseUrl(params.idendpoint || TRACKER_EP_FROM_IDMODULE);
|
|
69
|
+
|
|
70
|
+
if (gdprConsent) {
|
|
71
|
+
url.search.gdpr_consent = gdprConsent && gdprConsent.gdprApplies ? gdprConsent.consentString : '';
|
|
72
|
+
}
|
|
73
|
+
if (params) {
|
|
74
|
+
if (params.accountid) { url.search.accountid = params.accountid; }
|
|
75
|
+
url.search.client_id = storage.getCookie(PBJS_JXID_KEY);
|
|
76
|
+
url.search.idlog = storage.getCookie(PBJS_IDLOGSTR_KEY);
|
|
77
|
+
if (Array.isArray(params.pubExtIds)) {
|
|
78
|
+
params.pubExtIds.forEach((extId) => {
|
|
79
|
+
if (extId.ckname) {
|
|
80
|
+
url.search[extId.pname] = storage.getCookie(extId.ckname);
|
|
81
|
+
} else if (extId.lsname) {
|
|
82
|
+
url.search[extId.pname] = storage.getDataFromLocalStorage(extId.lsname);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
removeNullProp(url.search);
|
|
88
|
+
return buildUrl(url);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* just to check if the page has jixie publisher script planted
|
|
93
|
+
* @returns {boolean}
|
|
94
|
+
*/
|
|
95
|
+
function pgHasJxEvtScript() {
|
|
96
|
+
return ((window && window.jixie_o));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* analyze the log string from the server side to see if it is now time to
|
|
101
|
+
* call the server again
|
|
102
|
+
* @param {*} logstr a formatted string
|
|
103
|
+
* @return {boolean}
|
|
104
|
+
*/
|
|
105
|
+
function shouldCallSrv(logstr) {
|
|
106
|
+
if (!logstr) return true;
|
|
107
|
+
let now = Date.now();
|
|
108
|
+
let tsStr = logstr.split('_')[0];
|
|
109
|
+
let ts = parseInt(tsStr, 10);
|
|
110
|
+
if (!(tsStr.length == 13 && ts && ts >= (now - ONE_YEAR_IN_MS) && ts <= (now + ONE_YEAR_IN_MS))) {
|
|
111
|
+
ts = undefined;
|
|
112
|
+
}
|
|
113
|
+
return (ts === undefined || (ts && now > ts));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** @type {Submodule} */
|
|
117
|
+
export const jixieIdSubmodule = {
|
|
118
|
+
/**
|
|
119
|
+
* used to link submodule with config
|
|
120
|
+
* @type {string}
|
|
121
|
+
*/
|
|
122
|
+
name: MODULE_NAME,
|
|
123
|
+
/**
|
|
124
|
+
* decode the stored id value for passing to bid requests
|
|
125
|
+
* @function
|
|
126
|
+
* @param {string} value
|
|
127
|
+
* @returns {{jixieId: string} | undefined}
|
|
128
|
+
*/
|
|
129
|
+
decode(value) {
|
|
130
|
+
return (value != null && value.length > 0 ? { jixieId: value } : undefined);
|
|
131
|
+
},
|
|
132
|
+
/**
|
|
133
|
+
* performs action to obtain id
|
|
134
|
+
* Use a publink cookie first if it is present, otherwise use prebids copy, if neither are available callout to get a new id
|
|
135
|
+
* @function
|
|
136
|
+
* @param {SubmoduleConfig} [config] Config object with params and storage properties
|
|
137
|
+
* @param {ConsentData|undefined} gdprConsent GDPR consent
|
|
138
|
+
* @returns {IdResponse}
|
|
139
|
+
*/
|
|
140
|
+
getId(config, gdprConsent) {
|
|
141
|
+
if (!isPlainObject(config.params)) {
|
|
142
|
+
config.params = {};
|
|
143
|
+
}
|
|
144
|
+
const options = { method: 'GET', withCredentials: true };
|
|
145
|
+
const resp = function(callback) {
|
|
146
|
+
let jxId;
|
|
147
|
+
// If page has jixie script we use the standard jixie id cookie
|
|
148
|
+
if (pgHasJxEvtScript()) {
|
|
149
|
+
jxId = storage.getCookie(config.params.stdjxidckname || STD_JXID_KEY);
|
|
150
|
+
callback(jxId || null);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
// Case of no jixie script runs on this site:
|
|
154
|
+
jxId = storage.getCookie(PBJS_JXID_KEY);
|
|
155
|
+
let idLogStr = storage.getCookie(PBJS_IDLOGSTR_KEY);
|
|
156
|
+
if (jxId && !shouldCallSrv(idLogStr)) {
|
|
157
|
+
callback(jxId);
|
|
158
|
+
} else {
|
|
159
|
+
let handleResponse = function(responseText, xhr) {
|
|
160
|
+
if (xhr.status === 200) {
|
|
161
|
+
let response = JSON.parse(responseText);
|
|
162
|
+
if (response && response.data && response.data.success) {
|
|
163
|
+
response = response.data
|
|
164
|
+
persistExtInfo(response);
|
|
165
|
+
callback(response.client_id);
|
|
166
|
+
if (response.telcoep) {
|
|
167
|
+
ajax(response.telcoep, undefined, undefined, options);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
ajax(
|
|
173
|
+
buildIdCallUrl(config.params, gdprConsent && gdprConsent.gdpr ? gdprConsent.gdpr : null), handleResponse, undefined, options
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
return { callback: resp };
|
|
178
|
+
},
|
|
179
|
+
eids: {
|
|
180
|
+
'jixieId': {
|
|
181
|
+
source: 'jixie.io',
|
|
182
|
+
atype: 3
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
submodule('userId', jixieIdSubmodule);
|