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

33Across Bid Adapter: Obtain display-related attributes #8730

Merged
merged 11 commits into from
Jul 28, 2022
74 changes: 73 additions & 1 deletion modules/33acrossBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageU
});

ttxRequest.site = { id: siteId };
ttxRequest.device = _buildDeviceORTB();

if (pageUrl) {
ttxRequest.site.page = pageUrl;
Expand Down Expand Up @@ -333,12 +334,15 @@ function setExtensions(obj = {}, extFields) {

// BUILD REQUESTS: IMP
function _buildImpORTB(bidRequest) {
const gpid = deepAccess(bidRequest, 'ortb2Imp.ext.gpid');

const imp = {
id: bidRequest.bidId,
ext: {
ttx: {
prod: deepAccess(bidRequest, 'params.productId')
}
},
...(gpid ? { gpid } : {})
}
};

Expand Down Expand Up @@ -734,6 +738,74 @@ function _createSync({ siteId = 'zzz000000000003zzz', gdprConsent = {}, uspConse
return sync;
}

// BUILD REQUESTS: DEVICE
function _buildDeviceORTB() {
const win = getWindowSelf();

return {
ext: {
ttx: {
...getScreenDimensions(),
pxr: win.devicePixelRatio,
vp: getViewportDimensions(),
ah: win.screen.availHeight,
mtp: win.navigator.maxTouchPoints
}
}
};
}

function getTopMostAccessibleWindow() {
let mostAccessibleWindow = getWindowSelf();

try {
while (mostAccessibleWindow.parent !== mostAccessibleWindow &&
mostAccessibleWindow.parent.document) {
mostAccessibleWindow = mostAccessibleWindow.parent;
}
} catch (err) {
// Do not throw an exception if we can't access the topmost frame.
}

return mostAccessibleWindow;
}

function getViewportDimensions() {
const topWin = getTopMostAccessibleWindow();
const documentElement = topWin.document.documentElement;

return {
w: documentElement.clientWidth,
h: documentElement.clientHeight,
};
}

function getScreenDimensions() {
const {
innerWidth: windowWidth,
innerHeight: windowHeight,
screen
} = getWindowSelf();

const [biggerDimension, smallerDimension] = [
Math.max(screen.width, screen.height),
Math.min(screen.width, screen.height),
];

if (windowHeight > windowWidth) { // Portrait mode
return {
w: smallerDimension,
h: biggerDimension,
};
}

// Landscape mode
return {
w: biggerDimension,
h: smallerDimension,
};
}

export const spec = {
NON_MEASURABLE,

Expand Down
231 changes: 228 additions & 3 deletions test/spec/modules/33acrossBidAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@ describe('33acrossBidAdapter:', function () {
site: {
id: siteId
},
device: {
ext: {
ttx: {
w: 1024,
h: 728,
pxr: 2,
vp: {
w: 800,
h: 600
},
ah: 500,
mtp: 0
}
}
},
id: 'r1',
regs: {
ext: {
Expand Down Expand Up @@ -117,7 +132,7 @@ describe('33acrossBidAdapter:', function () {

this.withProduct = (prod = 'siab') => {
ttxRequest.imp.forEach((imp) => {
Object.assign(imp, {
utils.mergeDeep(imp, {
ext: {
ttx: {
prod
Expand All @@ -129,6 +144,18 @@ describe('33acrossBidAdapter:', function () {
return this;
};

this.withGpid = (gpid) => {
ttxRequest.imp.forEach((imp) => {
utils.mergeDeep(imp, {
ext: {
gpid
}
});
});

return this;
};

this.withGdprConsent = (consent, gdpr) => {
Object.assign(ttxRequest, {
user: {
Expand Down Expand Up @@ -166,6 +193,12 @@ describe('33acrossBidAdapter:', function () {
return this;
};

this.withDevice = (device) => {
utils.mergeDeep(ttxRequest, { device });

return this;
};

this.withPageUrl = pageUrl => {
Object.assign(ttxRequest.site, {
page: pageUrl
Expand Down Expand Up @@ -360,8 +393,21 @@ describe('33acrossBidAdapter:', function () {
};
win = {
parent: null,
devicePixelRatio: 2,
screen: {
width: 1024,
height: 728,
availHeight: 500
},
navigator: {
maxTouchPoints: 0
},
document: {
visibilityState: 'visible'
visibilityState: 'visible',
documentElement: {
clientWidth: 800,
clientHeight: 600
}
},

innerWidth: 800,
Expand All @@ -373,7 +419,6 @@ describe('33acrossBidAdapter:', function () {
.withBanner()
.build()
);

sandbox = sinon.sandbox.create();
sandbox.stub(Date, 'now').returns(1);
sandbox.stub(document, 'getElementById').returns(element);
Expand Down Expand Up @@ -755,6 +800,151 @@ describe('33acrossBidAdapter:', function () {
const [ buildRequest ] = spec.buildRequests(bidRequests);
validateBuiltServerRequest(buildRequest, serverRequest);
});

context('when all the wrapping windows are accessible', function() {
it('returns the viewport dimensions of the top most accessible window', function() {
const ttxRequest = new TtxRequestBuilder()
.withBanner()
.withDevice({
ext: {
ttx: {
vp: {
w: 6789,
h: 2345
}
}
}
})
.withProduct()
.build();
const serverRequest = new ServerRequestBuilder()
.withData(ttxRequest)
.build();

sandbox.stub(win, 'parent').value({
document: {
documentElement: {
clientWidth: 1234,
clientHeight: 4567
}
},
parent: {
document: {
documentElement: {
clientWidth: 6789,
clientHeight: 2345
}
},
}
});

const [ buildRequest ] = spec.buildRequests(bidRequests);
validateBuiltServerRequest(buildRequest, serverRequest);
});
});

context('when one of the wrapping windows cannot be accessed', function() {
it('returns the viewport dimensions of the top most accessible window', function() {
const ttxRequest = new TtxRequestBuilder()
.withBanner()
.withDevice({
ext: {
ttx: {
vp: {
w: 9876,
h: 5432
}
}
}
})
.withProduct()
.build();
const serverRequest = new ServerRequestBuilder()
.withData(ttxRequest)
.build();
const notAccessibleParentWindow = {};

Object.defineProperty(notAccessibleParentWindow, 'document', {
get() { throw new Error('fakeError'); }
});

sandbox.stub(win, 'parent').value({
document: {
documentElement: {
clientWidth: 1234,
clientHeight: 4567
}
},
parent: {
parent: notAccessibleParentWindow,
document: {
documentElement: {
clientWidth: 9876,
clientHeight: 5432
}
},
}
});

const [ buildRequest ] = spec.buildRequests(bidRequests);
validateBuiltServerRequest(buildRequest, serverRequest);
});
});
});

it('returns the screen dimensions', function() {
const ttxRequest = new TtxRequestBuilder()
.withBanner()
.withDevice({
ext: {
ttx: {
w: 1024,
h: 728
}
}
})
.withProduct()
.build();
const serverRequest = new ServerRequestBuilder()
.withData(ttxRequest)
.build();

win.screen.width = 1024;
win.screen.height = 728;

const [ buildRequest ] = spec.buildRequests(bidRequests);

validateBuiltServerRequest(buildRequest, serverRequest);
});

context('when the window height is greater than the width', function() {
it('returns the smaller screen dimension as the width', function() {
const ttxRequest = new TtxRequestBuilder()
.withBanner()
.withDevice({
ext: {
ttx: {
w: 728,
h: 1024
}
}
})
.withProduct()
.build();
const serverRequest = new ServerRequestBuilder()
.withData(ttxRequest)
.build();

win.screen.width = 1024;
win.screen.height = 728;

win.innerHeight = 728;
win.innerWidth = 727;

const [ buildRequest ] = spec.buildRequests(bidRequests);

validateBuiltServerRequest(buildRequest, serverRequest);
});
});

context('when tab is inactive', function() {
Expand Down Expand Up @@ -977,6 +1167,41 @@ describe('33acrossBidAdapter:', function () {
});
});

context('when Global Placement ID (gpid) is defined', function() {
let bidderRequest;

beforeEach(function() {
bidderRequest = {};
});

it('passes the Global Placement ID (gpid) in the request', function() {
const ttxRequest = new TtxRequestBuilder()
.withBanner()
.withProduct()
.withGpid('fakeGPID0')
.build();
const serverRequest = new ServerRequestBuilder()
.withData(ttxRequest)
.build();

let copyBidRequest = utils.deepClone(bidRequests);
const bidRequestsWithGpid = copyBidRequest.map(function(bidRequest, index) {
return {
...bidRequest,
ortb2Imp: {
ext: {
gpid: 'fakeGPID' + index
}
}
};
});

const [ builtServerRequest ] = spec.buildRequests(bidRequestsWithGpid, bidderRequest);

validateBuiltServerRequest(builtServerRequest, serverRequest);
});
});

context('when referer value is not available', function() {
it('returns corresponding server requests without site.page set', function() {
const bidderRequest = {
Expand Down