Skip to content

Commit

Permalink
33Across ID System: Fix merge conflicts between master & 9.0 (#11715)
Browse files Browse the repository at this point in the history
* Vis X Bid Adapter : retrieve and send seller defined audiences (#11638)

* AF-3647 added device object to request in visxBidAdapter

* AF-3647 added user, regs, site and user agent data to request

* AF-3647 removed userAgentClientHints because of it is gotten from device object

* AF-3647 updated test scenarios with sda signals

* AF-3647 fixed to getting ortb2 and spec file

* AF-3647 reverted to get user data from cookie/local storage

* 33Across User ID Module : support for the recently introduced "multiple storage types" feature (#11563)

* Refactoring - break functions that are handling multiple storage types.

* user id: introduce the concept of enabled storage types

* Apply domain override to 33across ID

* First party ID - Support for multiple storage types

* 33Across User ID: Recommend both storage types

* refactor the way enabled storage types are populated

* Default to fetch keepalive (#11682)

Co-authored-by: Marcin Komorski <[email protected]>

* Dailymotion Bid Adapter: add support for user syncs & new fields (#11603)

* Dailymotion Bid Adapter: add support for playbackmethod & plcmt

* Dailymotion Bid Adapter: add support for user syncs

* Dailymotion Bid Adapter: Add support for ortb2 device, and contextual informations

* Dailymotion Bid Adapter: Fix tests

* Dailymotion Bid Adapter: add support for content.url & device.ext.atts

* Dailymotion Bid Adapter: change markdown header levels

* Dailymotion Bid Adapter: collect prebid.version

---------

Co-authored-by: Kevin Siow <[email protected]>

* ZetaGlobalSsp Analytics Adapter : provide device object (#11607)

* ZetaGlobalSpp Analytics adapter: provide device object

* ZetaGlobalSpp Analytics adapter: provide ua in adRenderSucceeded event

* provide domain and page in timeout event

---------

Co-authored-by: Surovenko Alexey <[email protected]>
Co-authored-by: Alexey Surovenko <[email protected]>

* Core Utils: fix jsdoc warnings (#11694)

* Update utils.js

* Update perfMetrics.js

* Update ttlCollection.js

* Update adpod.js

* Update consentManagementGpp.js

* Update consentManagementGpp.js

* Update consentManagement.js

* Update consentManagementUsp.js

* Update currency.js

* Update dfpAdServerVideo.js

* Update instreamTracking.js

* Update s2sTesting.js

* Update sizeMapping.js

* Update topicsFpdModule.js

* Update uid2IdSystem.js

* Update consentManagementUsp.js

* Update sizeMapping.js

* datablocksBidAdapter.js: fix syncs issue (#11684)

fixes #11319

* ColossusSSP Bid Adapter : replace gpid for pbadslot (#11701)

* add video&native traffic colossus ssp

* Native obj validation

* Native obj validation #2

* Added size field in requests

* fixed test

* fix merge conflicts

* move to 3.0

* move to 3.0

* fix IE11 new URL issue

* fix IE11 new URL issue

* fix IE11 new URL issue

* https for 3.0

* add https test

* add ccp and schain features

* fix test

* sync with upstream, fix conflicts

* Update colossussspBidAdapter.js

remove commented code

* Update colossussspBidAdapter.js

lint fix

* identity extensions

* identity extensions

* fix

* fix

* fix

* fix

* fix

* add tests for user ids

* fix

* fix

* fix

* fix

* fix

* fix

* fix

* add gdpr support

* add gdpr support

* id5id support

* Update colossussspBidAdapter.js

add bidfloor parameter

* Update colossussspBidAdapter.js

check bidfloor

* Update colossussspBidAdapter.js

* Update colossussspBidAdapter.js

* Update colossussspBidAdapter.js

* Update colossussspBidAdapter_spec.js

* use floor module

* Revert "use floor module"

This reverts commit f0c5c24.

* use floor module

* update to 5v

* fix

* add uid2 and bidFloor support

* fix

* add pbadslot support

* fix conflicts

* add onBidWon

* refactor

* add test for onBidWon()

* fix

* add group_id

* Trigger circleci

* fix

* update user sync

* fix window.location

* fix test

* updates

* fix conflict

* fix

* updates

* remove traffic param

* add transactionId to request data for colossusssp adapter

* Send tid in placements array

* update user sync

* updated tests

* remove changes package-lock file

* fix

* add First Party Data

* gpp support

* accepting eids from request

* fixing lint errors

* resolving a conflict

* fixing a failed test case related to tid

* fixing karma version for conflict resolution

* reverting package json files to original version

* switching placement to plcmt

* replacing gpid for pbadslot

---------

Co-authored-by: Vladislav Isaiko <[email protected]>
Co-authored-by: Aiholkin <[email protected]>
Co-authored-by: Bill Newman <[email protected]>
Co-authored-by: Mykhailo Yaremchuk <[email protected]>
Co-authored-by: kottapally <[email protected]>

* Bidmatic Bid Adapter: Initial Release (#11690)

* Bidmatic Initial commit

* Use getFloor from price module

---------

Co-authored-by: Gonca Karadeniz <[email protected]>
Co-authored-by: mkomorski <[email protected]>
Co-authored-by: Marcin Komorski <[email protected]>
Co-authored-by: Kevin Siow <[email protected]>
Co-authored-by: Kevin Siow <[email protected]>
Co-authored-by: asurovenko-zeta <[email protected]>
Co-authored-by: Surovenko Alexey <[email protected]>
Co-authored-by: Alexey Surovenko <[email protected]>
Co-authored-by: Patrick McCann <[email protected]>
Co-authored-by: bhasker-ddh <[email protected]>
Co-authored-by: Vladislav Isaiko <[email protected]>
Co-authored-by: Aiholkin <[email protected]>
Co-authored-by: Bill Newman <[email protected]>
Co-authored-by: Mykhailo Yaremchuk <[email protected]>
Co-authored-by: kottapally <[email protected]>
Co-authored-by: Gena <[email protected]>
  • Loading branch information
17 people committed Jun 5, 2024
1 parent b932759 commit fd8f2e1
Show file tree
Hide file tree
Showing 32 changed files with 1,739 additions and 271 deletions.
71 changes: 48 additions & 23 deletions modules/33acrossIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { submodule } from '../src/hook.js';
import { uspDataHandler, coppaDataHandler, gppDataHandler } from '../src/adapterManager.js';
import { getStorageManager, STORAGE_TYPE_COOKIES, STORAGE_TYPE_LOCALSTORAGE } from '../src/storageManager.js';
import { MODULE_TYPE_UID } from '../src/activities/modules.js';
import { domainOverrideToRootDomain } from '../libraries/domainOverrideToRootDomain/index.js';

/**
* @typedef {import('../modules/userId/index.js').Submodule} Submodule
Expand All @@ -31,6 +32,10 @@ const DEFAULT_TPID_SUPPORT = true;

export const storage = getStorageManager({ moduleType: MODULE_TYPE_UID, moduleName: MODULE_NAME });

export const domainUtils = {
domainOverride: domainOverrideToRootDomain(storage, MODULE_NAME)
};

function calculateResponseObj(response) {
if (!response.succeeded) {
if (response.error == 'Cookied User') {
Expand All @@ -54,7 +59,7 @@ function calculateResponseObj(response) {
};
}

function calculateQueryStringParams(pid, gdprConsentData, storageConfig) {
function calculateQueryStringParams(pid, gdprConsentData, enabledStorageTypes) {
const uspString = uspDataHandler.getConsentData();
const coppaValue = coppaDataHandler.getCoppa();
const gppConsent = gppDataHandler.getConsentData();
Expand Down Expand Up @@ -82,12 +87,12 @@ function calculateQueryStringParams(pid, gdprConsentData, storageConfig) {
params.gdpr_consent = gdprConsentData.consentString;
}

const fp = getStoredValue(STORAGE_FPID_KEY, storageConfig);
const fp = getStoredValue(STORAGE_FPID_KEY, enabledStorageTypes);
if (fp) {
params.fp = encodeURIComponent(fp);
}

const tp = getStoredValue(STORAGE_TPID_KEY, storageConfig);
const tp = getStoredValue(STORAGE_TPID_KEY, enabledStorageTypes);
if (tp) {
params.tp = encodeURIComponent(tp);
}
Expand All @@ -99,32 +104,42 @@ function deleteFromStorage(key) {
if (storage.cookiesAreEnabled()) {
const expiredDate = new Date(0).toUTCString();

storage.setCookie(key, '', expiredDate, 'Lax');
storage.setCookie(key, '', expiredDate, 'Lax', domainUtils.domainOverride());
}

storage.removeDataFromLocalStorage(key);
}

function storeValue(key, value, storageConfig = {}) {
if (storageConfig.type === STORAGE_TYPE_COOKIES && storage.cookiesAreEnabled()) {
const expirationInMs = 60 * 60 * 24 * 1000 * storageConfig.expires;
const expirationTime = new Date(Date.now() + expirationInMs);
function storeValue(key, value, { enabledStorageTypes, expires }) {
enabledStorageTypes.forEach(storageType => {
if (storageType === STORAGE_TYPE_COOKIES) {
const expirationInMs = 60 * 60 * 24 * 1000 * expires;
const expirationTime = new Date(Date.now() + expirationInMs);

storage.setCookie(key, value, expirationTime.toUTCString(), 'Lax');
} else if (storageConfig.type === STORAGE_TYPE_LOCALSTORAGE) {
storage.setDataInLocalStorage(key, value);
}
storage.setCookie(key, value, expirationTime.toUTCString(), 'Lax', domainUtils.domainOverride());
} else if (storageType === STORAGE_TYPE_LOCALSTORAGE) {
storage.setDataInLocalStorage(key, value);
}
});
}

function getStoredValue(key, storageConfig = {}) {
if (storageConfig.type === STORAGE_TYPE_COOKIES && storage.cookiesAreEnabled()) {
return storage.getCookie(key);
} else if (storageConfig.type === STORAGE_TYPE_LOCALSTORAGE) {
return storage.getDataFromLocalStorage(key);
}
function getStoredValue(key, enabledStorageTypes) {
let storedValue;

enabledStorageTypes.find(storageType => {
if (storageType === STORAGE_TYPE_COOKIES) {
storedValue = storage.getCookie(key);
} else if (storageType === STORAGE_TYPE_LOCALSTORAGE) {
storedValue = storage.getDataFromLocalStorage(key);
}

return !!storedValue;
});

return storedValue;
}

function handleSupplementalId(key, id, storageConfig = {}) {
function handleSupplementalId(key, id, storageConfig) {
id
? storeValue(key, id, storageConfig)
: deleteFromStorage(key);
Expand Down Expand Up @@ -160,7 +175,7 @@ export const thirthyThreeAcrossIdSubmodule = {
* @param {SubmoduleConfig} [config]
* @returns {IdResponse|undefined}
*/
getId({ params = { }, storage: storageConfig }, gdprConsentData) {
getId({ params = { }, enabledStorageTypes = [], storage: storageConfig = {} }, gdprConsentData) {
if (typeof params.pid !== 'string') {
logError(`${MODULE_NAME}: Submodule requires a partner ID to be defined`);

Expand Down Expand Up @@ -192,11 +207,17 @@ export const thirthyThreeAcrossIdSubmodule = {
}

if (storeFpid) {
handleSupplementalId(STORAGE_FPID_KEY, responseObj.fp, storageConfig);
handleSupplementalId(STORAGE_FPID_KEY, responseObj.fp, {
enabledStorageTypes,
expires: storageConfig.expires
});
}

if (storeTpid) {
handleSupplementalId(STORAGE_TPID_KEY, responseObj.tp, storageConfig);
handleSupplementalId(STORAGE_TPID_KEY, responseObj.tp, {
enabledStorageTypes,
expires: storageConfig.expires
});
}

cb(responseObj.envelope);
Expand All @@ -206,10 +227,14 @@ export const thirthyThreeAcrossIdSubmodule = {

cb();
}
}, calculateQueryStringParams(pid, gdprConsentData, storageConfig), { method: 'GET', withCredentials: true });
}, calculateQueryStringParams(pid, gdprConsentData, enabledStorageTypes), {
method: 'GET',
withCredentials: true
});
}
};
},
domainOverride: domainUtils.domainOverride,
eids: {
'33acrossId': {
source: '33across.com',
Expand Down
4 changes: 2 additions & 2 deletions modules/33acrossIdSystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pbjs.setConfig({
name: "33acrossId",
storage: {
name: "33acrossId",
type: "html5",
type: "cookie&html5",
expires: 30,
refreshInSeconds: 8*3600
},
Expand All @@ -40,7 +40,7 @@ The following settings are available for the `storage` property in the `userSync
| Param name | Scope | Type | Description | Example |
| --- | --- | --- | --- | --- |
| name | Required | String| Name of the cookie or HTML5 local storage where the user ID will be stored | `"33acrossId"` |
| type | Required | String | `"html5"` (preferred) or `"cookie"` | `"html5"` |
| type | Required | String | `"cookie&html5"` (preferred) or `"cookie"` or `"html5"` | `"cookie&html5"` |
| expires | Strongly Recommended | Number | How long (in days) the user ID information will be stored. 33Across recommends `30`. | `30` |
| refreshInSeconds | Strongly Recommended | Number | The interval (in seconds) for refreshing the user ID. 33Across recommends no more than 8 hours between refreshes. | `8*3600` |

Expand Down
9 changes: 4 additions & 5 deletions modules/adpod.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,6 @@ export function callPrebidCacheAfterAuction(bids, callback) {
/**
* Compare function to be used in sorting long-form bids. This will compare bids on price per second.
* @param {Object} bid
* @param {Object} bid
*/
export function sortByPricePerSecond(a, b) {
if (a.adserverTargeting[TARGETING_KEYS.PRICE_BUCKET] / a.video.durationBucket < b.adserverTargeting[TARGETING_KEYS.PRICE_BUCKET] / b.video.durationBucket) {
Expand All @@ -465,10 +464,10 @@ export function sortByPricePerSecond(a, b) {

/**
* This function returns targeting keyvalue pairs for long-form adserver modules. Freewheel and GAM are currently supporting Prebid long-form
* @param {Object} options
* @param {Array[string]} codes
* @param {function} callback
* @returns targeting kvs for adUnitCodes
* @param {Object} options - Options for targeting.
* @param {Array<string>} options.codes - Array of ad unit codes.
* @param {function} options.callback - Callback function to handle the targeting key-value pairs.
* @returns {Object} Targeting key-value pairs for ad unit codes.
*/
export function getTargeting({ codes, callback } = {}) {
if (!callback) {
Expand Down
110 changes: 110 additions & 0 deletions modules/bidmaticBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { replaceAuctionPrice, isNumber, deepAccess, isFn } from '../src/utils.js';

export const END_POINT = 'https://adapter.bidmatic.io/ortb-client';
const BIDDER_CODE = 'bidmatic';
const DEFAULT_CURRENCY = 'USD';

export const converter = ortbConverter({
context: {
netRevenue: true,
ttl: 290,
},
imp(buildImp, bidRequest, context) {
const imp = buildImp(bidRequest, context);
const floorInfo = isFn(bidRequest.getFloor) ? bidRequest.getFloor({
currency: context.currency || 'USD',
size: '*',
mediaType: '*'
}) : {
floor: imp.bidfloor || deepAccess(bidRequest, 'params.bidfloor') || 0,
currency: DEFAULT_CURRENCY
};

if (floorInfo) {
imp.bidfloor = floorInfo.floor;
imp.bidfloorcur = floorInfo.currency;
}
imp.tagid = deepAccess(bidRequest, 'ortb2Imp.ext.gpid') || bidRequest.adUnitCode;

return imp;
},
request(buildRequest, imps, bidderRequest, context) {
const request = buildRequest(imps, bidderRequest, context);
if (!request.cur) {
request.cur = [DEFAULT_CURRENCY];
}
return request;
},
bidResponse(buildBidResponse, bid, context) {
const { bidRequest } = context;

let resMediaType;
const reqMediaTypes = Object.keys(bidRequest.mediaTypes);
if (reqMediaTypes.length === 1) {
resMediaType = reqMediaTypes[0];
} else {
if (bid.adm.search(/^(<\?xml|<vast)/i) !== -1) {
resMediaType = VIDEO;
} else {
resMediaType = BANNER;
}
}

context.mediaType = resMediaType;

return buildBidResponse(bid, context);
}
});

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER, VIDEO],
gvlid: 1134,
isBidRequestValid: function (bid) {
return isNumber(deepAccess(bid, 'params.source'))
},

buildRequests: function (validBidRequests, bidderRequest) {
const requestsBySource = validBidRequests.reduce((acc, bidRequest) => {
acc[bidRequest.params.source] = acc[bidRequest.params.source] || [];
acc[bidRequest.params.source].push(bidRequest);
return acc;
}, {});

return Object.entries(requestsBySource).map(([source, bidRequests]) => {
const data = converter.toORTB({ bidRequests, bidderRequest });
const url = new URL(END_POINT);
url.searchParams.append('source', source);
return {
method: 'POST',
url: url.toString(),
data: data,
options: {
withCredentials: true,
}
};
});
},

interpretResponse: function (serverResponse, bidRequest) {
if (!serverResponse || !serverResponse.body) return [];
const parsedSeatbid = serverResponse.body.seatbid.map(seatbidItem => {
const parsedBid = seatbidItem.bid.map((bidItem) => ({
...bidItem,
adm: replaceAuctionPrice(bidItem.adm, bidItem.price),
nurl: replaceAuctionPrice(bidItem.nurl, bidItem.price)
}));
return { ...seatbidItem, bid: parsedBid };
});
const responseBody = { ...serverResponse.body, seatbid: parsedSeatbid };
return converter.fromORTB({
response: responseBody,
request: bidRequest.data,
}).bids;
},

};
registerBidder(spec);
26 changes: 26 additions & 0 deletions modules/bidmaticBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Overview

```
Module Name: Bidmatic Bid Adapter
Module Type: Bidder Adapter
Maintainer: [email protected]
```

# Description

Adds access to Bidmatic SSP oRTB service.

# Sample Ad Unit: For Publishers
```
var adUnits = [{
code: 'bg-test-rectangle',
sizes: [[300, 250]],
bids: [{
bidder: 'bidmatic',
params: {
source: 886409,
bidfloor: 0.1
}
}]
}]
```
7 changes: 4 additions & 3 deletions modules/consentManagementGpp.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,10 @@ export class GPPClient {
* This function handles interacting with an IAB compliant CMP to obtain the consent information of the user.
* Given the async nature of the CMP's API, we pass in acting success/error callback functions to exit this function
* based on the appropriate result.
* @param {function({})} onSuccess acts as a success callback when CMP returns a value; pass along consentObjectfrom CMP
* @param {function(string, ...{}?)} cmpError acts as an error callback while interacting with CMP; pass along an error message (string) and any extra error arguments (purely for logging)
* @param {Object} options - An object containing the callbacks.
* @param {function(Object): void} options.onSuccess - Acts as a success callback when CMP returns a value; pass along consentObject from CMP.
* @param {function(string, ...Object?): void} options.onError - Acts as an error callback while interacting with CMP; pass along an error message (string) and any extra error arguments (purely for logging).
* @param {function(): Object} [mkCmp=cmpClient] - A function to create the CMP client. Defaults to `cmpClient`.
*/
export function lookupIabConsent({onSuccess, onError}, mkCmp = cmpClient) {
pipeCallbacks(() => GPPClient.get(mkCmp).refresh(), {onSuccess, onError});
Expand Down Expand Up @@ -291,7 +293,6 @@ function processCmpData(consentData) {
/**
* Stores CMP data locally in module to make information available in adaptermanager.js for later in the auction
* @param {{}} gppData the result of calling a CMP's `getGPPData` (or equivalent)
* @param {{}} sectionData map from GPP section name to the result of calling a CMP's `getSection` (or equivalent)
*/
export function storeConsentData(gppData = {}) {
consentData = {
Expand Down
10 changes: 7 additions & 3 deletions modules/consentManagementTcf.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ const cmpCallMap = {

/**
* This function reads the consent string from the config to obtain the consent information of the user.
* @param {function({})} onSuccess acts as a success callback when the value is read from config; pass along consentObject from CMP
* @param {Object} options - An object containing the callbacks.
* @param {function(Object): void} options.onSuccess - Acts as a success callback when the value is read from config; pass along consentObject from CMP.
* @param {function(string, ...Object?): void} [options.onError] - Acts as an error callback while interacting with CMP; pass along an error message (string) and any extra error arguments (purely for logging). Optional.
*/
function lookupStaticConsentData({onSuccess, onError}) {
processCmpData(staticConsentData, {onSuccess, onError})
Expand All @@ -45,8 +47,10 @@ function lookupStaticConsentData({onSuccess, onError}) {
* This function handles interacting with an IAB compliant CMP to obtain the consent information of the user.
* Given the async nature of the CMP's API, we pass in acting success/error callback functions to exit this function
* based on the appropriate result.
* @param {function({})} onSuccess acts as a success callback when CMP returns a value; pass along consentObjectfrom CMP
* @param {function(string, ...{}?)} cmpError acts as an error callback while interacting with CMP; pass along an error message (string) and any extra error arguments (purely for logging)
* @param {Object} options - An object containing the callbacks.
* @param {function(Object): void} options.onSuccess - Acts as a success callback when CMP returns a value; pass along consentObject from CMP.
* @param {function(string, ...Object?): void} options.onError - Acts as an error callback while interacting with CMP; pass along an error message (string) and any extra error arguments (purely for logging).
* @param {function(Object): void} options.onEvent - Acts as an event callback for processing TCF data events from CMP.
*/
function lookupIabConsent({onSuccess, onError, onEvent}) {
function cmpResponseCallback(tcfData, success) {
Expand Down
10 changes: 6 additions & 4 deletions modules/consentManagementUsp.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,12 @@ export const requestBidsHook = timedAuctionHook('usp', function requestBidsHook(
/**
* This function checks the consent data provided by USPAPI to ensure it's in an expected state.
* If it's bad, we exit the module depending on config settings.
* If it's good, then we store the value and exits the module.
* @param {object} consentObject required; object returned by USPAPI that contains user's consent choices
* @param {function(string)} onSuccess callback accepting the resolved consent USP consent string
* @param {function(string, ...{}?)} onError callback accepting error message and any extra error arguments (used purely for logging)
* If it's good, then we store the value and exit the module.
*
* @param {Object} consentObject - The object returned by USPAPI that contains the user's consent choices.
* @param {Object} callbacks - An object containing the callback functions.
* @param {function(string): void} callbacks.onSuccess - Callback accepting the resolved USP consent string.
* @param {function(string, ...Object?): void} callbacks.onError - Callback accepting an error message and any extra error arguments (used purely for logging).
*/
function processUspData(consentObject, {onSuccess, onError}) {
const valid = !!(consentObject && consentObject.usPrivacy);
Expand Down
1 change: 1 addition & 0 deletions modules/currency.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export let responseReady = defer();

/**
* Configuration function for currency
* @param {object} config
* @param {string} [config.adServerCurrency = 'USD']
* ISO 4217 3-letter currency code that represents the target currency. (e.g. 'EUR'). If this value is present,
* the currency conversion feature is activated.
Expand Down
Loading

0 comments on commit fd8f2e1

Please sign in to comment.