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

Adagio Bid Adapter: preparation for new Rtd module and Prebid.js 9 #11485

Merged
merged 2 commits into from
May 21, 2024
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
151 changes: 84 additions & 67 deletions modules/adagioBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {find} from '../src/polyfill.js';
import {
canAccessWindowTop,
cleanObj,
deepAccess,
deepClone,
Expand All @@ -8,17 +9,18 @@ import {
getUniqueIdentifierStr,
getWindowSelf,
getWindowTop,
inIframe,
isArray,
isArrayOfNums,
isFn,
inIframe,
isInteger,
isNumber,
isArrayOfNums,
isSafeFrameWindow,
isStr,
logError,
logInfo,
logWarn,
mergeDeep,
isStr,
} from '../src/utils.js';
import {config} from '../src/config.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
Expand Down Expand Up @@ -104,13 +106,15 @@ export const GlobalExchange = (function() {
getOrSetGlobalFeatures: function () {
if (!features) {
features = {
type: 'bidAdapter',
page_dimensions: getPageDimensions().toString(),
viewport_dimensions: getViewPortDimensions().toString(),
user_timestamp: getTimestampUTC().toString(),
dom_loading: getDomLoadingDuration().toString(),
}
}
return features;

return { ...features };
},

prepareExchangeData(storageValue) {
Expand All @@ -130,7 +134,7 @@ export const GlobalExchange = (function() {
const data = {
session: {
new: newSession,
rnd: random
rnd: random,
}
}

Expand All @@ -149,6 +153,9 @@ export const GlobalExchange = (function() {
};
})();

/**
* @deprecated will be removed in Prebid.js 9.
*/
export function adagioScriptFromLocalStorageCb(ls) {
try {
if (!ls) {
Expand Down Expand Up @@ -179,6 +186,9 @@ export function adagioScriptFromLocalStorageCb(ls) {
}
}

/**
* @deprecated will be removed in Prebid.js 9.
*/
export function getAdagioScript() {
storage.getDataFromLocalStorage(ADAGIO_LOCALSTORAGE_KEY, (ls) => {
internal.adagioScriptFromLocalStorageCb(ls);
Expand All @@ -204,31 +214,14 @@ export function getAdagioScript() {
});
}

function canAccessTopWindow() {
try {
if (getWindowTop().location.href) {
return true;
}
} catch (error) {
return false;
}
}

function getCurrentWindow() {
return currentWindow || getWindowSelf();
}

function isSafeFrameWindow() {
const ws = getWindowSelf();
return !!(ws.$sf && ws.$sf.ext);
}

function initAdagio() {
if (canAccessTopWindow()) {
currentWindow = (canAccessTopWindow()) ? getWindowTop() : getWindowSelf();
}
currentWindow = (canAccessWindowTop()) ? getWindowTop() : getWindowSelf();

const w = internal.getCurrentWindow();
const w = currentWindow;

w.ADAGIO = w.ADAGIO || {};
w.ADAGIO.adUnits = w.ADAGIO.adUnits || {};
Expand All @@ -240,13 +233,16 @@ function initAdagio() {

storage.getDataFromLocalStorage('adagio', (storageData) => {
try {
GlobalExchange.prepareExchangeData(storageData);
if (w.ADAGIO.hasRtd !== true) {
logInfo(`${LOG_PREFIX} RTD module not found. Loading external script from adagioBidAdapter is deprecated and will be removed in Prebid.js 9.`);

GlobalExchange.prepareExchangeData(storageData);
getAdagioScript();
}
} catch (e) {
logError(LOG_PREFIX, e);
}
});

getAdagioScript();
}

function enqueue(ob) {
Expand Down Expand Up @@ -359,6 +355,12 @@ function setPlayerName(bidRequest) {
return playerName;
}

function hasRtd() {
const w = internal.getCurrentWindow();

return !!(w.ADAGIO && w.ADAGIO.hasRtd);
};

export const internal = {
enqueue,
getPageviewId,
Expand All @@ -368,9 +370,10 @@ export const internal = {
getRefererInfo,
adagioScriptFromLocalStorageCb,
getCurrentWindow,
canAccessTopWindow,
canAccessWindowTop,
isRendererPreferredFromPublisher,
isNewSession
isNewSession,
hasRtd
};

function _getGdprConsent(bidderRequest) {
Expand Down Expand Up @@ -685,7 +688,7 @@ function autoFillParams(bid) {
}

function getPageDimensions() {
if (isSafeFrameWindow() || !canAccessTopWindow()) {
if (isSafeFrameWindow() || !canAccessWindowTop()) {
return '';
}

Expand All @@ -708,7 +711,7 @@ function getPageDimensions() {
* @returns
*/
function getViewPortDimensions() {
if (!isSafeFrameWindow() && !canAccessTopWindow()) {
if (!isSafeFrameWindow() && !canAccessWindowTop()) {
return '';
}

Expand Down Expand Up @@ -746,7 +749,7 @@ function getSlotPosition(adUnitElementId) {
return '';
}

if (!isSafeFrameWindow() && !canAccessTopWindow()) {
if (!isSafeFrameWindow() && !canAccessWindowTop()) {
return '';
}

Expand All @@ -769,7 +772,7 @@ function getSlotPosition(adUnitElementId) {

position.x = Math.round(sfGeom.t);
position.y = Math.round(sfGeom.l);
} else if (canAccessTopWindow()) {
} else if (canAccessWindowTop()) {
try {
// window.top based computing
const wt = getWindowTop();
Expand Down Expand Up @@ -823,22 +826,14 @@ function getTimestampUTC() {
return Math.floor(new Date().getTime() / 1000) - new Date().getTimezoneOffset() * 60;
}

function getPrintNumber(adUnitCode, bidderRequest) {
if (!bidderRequest.bids || !bidderRequest.bids.length) {
return 1;
}
const adagioBid = find(bidderRequest.bids, bid => bid.adUnitCode === adUnitCode);
return adagioBid.bidderRequestsCount || 1;
}

/**
* domLoading feature is computed on window.top if reachable.
*/
function getDomLoadingDuration() {
let domLoadingDuration = -1;
let performance;

performance = (canAccessTopWindow()) ? getWindowTop().performance : getWindowSelf().performance;
performance = (canAccessWindowTop()) ? getWindowTop().performance : getWindowSelf().performance;

if (performance && performance.timing && performance.timing.navigationStart > 0) {
const val = performance.timing.domLoading - performance.timing.navigationStart;
Expand Down Expand Up @@ -958,6 +953,31 @@ const OUTSTREAM_RENDERER = {
}
};

/**
*
* @param {*} bidRequest
* @returns
*/
const _getFeatures = (bidRequest) => {
const f = { ...deepAccess(bidRequest, 'ortb2.ext.features', GlobalExchange.getOrSetGlobalFeatures()) } || {};

f.print_number = deepAccess(bidRequest, 'bidderRequestsCount', 1).toString();

if (f.type === 'bidAdapter') {
f.adunit_position = getSlotPosition(bidRequest.params.adUnitElementId)
} else {
f.adunit_position = deepAccess(bidRequest, 'ortb2Imp.ext.data.adunit_position');
}

Object.keys(f).forEach((prop) => {
if (f[prop] === '') {
delete f[prop];
}
});

return f;
}

export const spec = {
code: BIDDER_CODE,
gvlid: GVLID,
Expand Down Expand Up @@ -986,6 +1006,7 @@ export const spec = {
const device = internal.getDevice();
const site = internal.getSite(bidderRequest);
const pageviewId = internal.getPageviewId();
const hasRtd = internal.hasRtd();
const gdprConsent = _getGdprConsent(bidderRequest) || {};
const uspConsent = _getUspConsent(bidderRequest) || {};
const coppa = _getCoppa();
Expand All @@ -998,6 +1019,9 @@ export const spec = {
// We don't validate the dsa object in adapter and let our server do it.
const dsa = deepAccess(bidderRequest, 'ortb2.regs.ext.dsa');

let rtdSamplingSession = deepAccess(bidderRequest, 'ortb2.ext.session');
const dataExchange = (rtdSamplingSession) ? { session: rtdSamplingSession } : GlobalExchange.getExchangeData();

const aucId = generateUUID()

const adUnits = validBidRequests.map(rawBidRequest => {
Expand All @@ -1006,13 +1030,6 @@ export const spec = {
// Fix https://github.com/prebid/Prebid.js/issues/9781
bidRequest.auctionId = aucId

const globalFeatures = GlobalExchange.getOrSetGlobalFeatures();
const features = {
...globalFeatures,
print_number: getPrintNumber(bidRequest.adUnitCode, bidderRequest).toString(),
adunit_position: getSlotPosition(bidRequest.params.adUnitElementId) // adUnitElementId à déplacer ???
};

// Force the Split Keyword to be a String
if (bidRequest.params.splitKeyword) {
if (isStr(bidRequest.params.splitKeyword) || isNumber(bidRequest.params.splitKeyword)) {
Expand Down Expand Up @@ -1056,23 +1073,20 @@ export const spec = {
}
}

Object.keys(features).forEach((prop) => {
if (features[prop] === '') {
delete features[prop];
}
});

const features = _getFeatures(bidRequest);
bidRequest.features = features;

internal.enqueue({
action: 'features',
ts: Date.now(),
data: {
features: bidRequest.features,
params: bidRequest.params,
adUnitCode: bidRequest.adUnitCode
}
});
if (!hasRtd) {
internal.enqueue({
action: 'features',
ts: Date.now(),
data: {
features,
params: { ...bidRequest.params },
adUnitCode: bidRequest.adUnitCode
}
});
}

// Handle priceFloors module
// We need to use `rawBidRequest` as param because:
Expand Down Expand Up @@ -1127,8 +1141,10 @@ export const spec = {
bidRequest.gpid = gpid;
}

// store the whole bidRequest (adUnit) object in the ADAGIO namespace.
storeRequestInAdagioNS(bidRequest);
if (!hasRtd) {
// store the whole bidRequest (adUnit) object in the ADAGIO namespace.
storeRequestInAdagioNS(bidRequest);
}

// Remove some params that are not needed on the server side.
delete bidRequest.params.siteId;
Expand Down Expand Up @@ -1176,12 +1192,13 @@ export const spec = {
url: ENDPOINT,
data: {
organizationId: organizationId,
hasRtd: hasRtd ? 1 : 0,
secure: secure,
device: device,
site: site,
pageviewId: pageviewId,
adUnits: groupedAdUnits[organizationId],
data: GlobalExchange.getExchangeData(),
data: dataExchange,
regs: {
gdpr: gdprConsent,
coppa: coppa,
Expand Down
23 changes: 23 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const internal = {
createTrackPixelIframeHtml,
getWindowSelf,
getWindowTop,
canAccessWindowTop,
getWindowLocation,
insertUserSyncIframe,
insertElement,
Expand Down Expand Up @@ -180,6 +181,16 @@ export function getWindowLocation() {
return window.location;
}

export function canAccessWindowTop() {
try {
if (internal.getWindowTop().location.href) {
return true;
}
} catch (e) {
return false;
}
}

/**
* Wrappers to console.(log | info | warn | error). Takes N arguments, the same as the native methods
*/
Expand Down Expand Up @@ -620,6 +631,18 @@ export function inIframe() {
}
}

/**
* https://iabtechlab.com/wp-content/uploads/2016/03/SafeFrames_v1.1_final.pdf
*/
export function isSafeFrameWindow() {
if (!inIframe()) {
return false;
}

const ws = internal.getWindowSelf();
return !!(ws.$sf && ws.$sf.ext);
}

export function isSafariBrowser() {
return /^((?!chrome|android|crios|fxios).)*safari/i.test(navigator.userAgent);
}
Expand Down
Loading