Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .github/workflows/issue_tracker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
steps:
- name: Generate token
id: generate_token
uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
uses: tibdex/github-app-token@f717b5ecd4534d3c4df4ce9b5c1c2214f0f7cd06
with:
app_id: ${{ secrets.ISSUE_APP_ID }}
private_key: ${{ secrets.ISSUE_APP_PEM }}
Expand Down
51 changes: 44 additions & 7 deletions modules/onetagBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
'use strict';

import {BANNER, VIDEO} from '../src/mediaTypes.js';
import {INSTREAM, OUTSTREAM} from '../src/video.js';
import {Renderer} from '../src/Renderer.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { INSTREAM, OUTSTREAM } from '../src/video.js';
import { Renderer } from '../src/Renderer.js';
import {find} from '../src/polyfill.js';
import {getStorageManager} from '../src/storageManager.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {createEidsArray} from './userId/eids.js';
import {deepClone} from '../src/utils.js';
import { getStorageManager } from '../src/storageManager.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { createEidsArray } from './userId/eids.js';
import { deepClone, logError, deepAccess } from '../src/utils.js';

const ENDPOINT = 'https://onetag-sys.com/prebid-request';
const USER_SYNC_ENDPOINT = 'https://onetag-sys.com/usync/';
Expand Down Expand Up @@ -68,6 +68,9 @@ function buildRequests(validBidRequests, bidderRequest) {
if (validBidRequests && validBidRequests.length !== 0 && validBidRequests[0].userId) {
payload.userId = createEidsArray(validBidRequests[0].userId);
}
if (validBidRequests && validBidRequests.length !== 0 && validBidRequests[0].schain && isSchainValid(validBidRequests[0].schain)) {
payload.schain = validBidRequests[0].schain;
}
try {
if (storage.hasLocalStorage()) {
payload.onetagSid = storage.getDataFromLocalStorage('onetag_sid');
Expand Down Expand Up @@ -245,6 +248,7 @@ function requestsToBids(bidRequests) {
// Other params
videoObj['mediaTypeInfo'] = deepClone(bidRequest.mediaTypes.video);
videoObj['type'] = VIDEO;
videoObj['priceFloors'] = getBidFloor(bidRequest, VIDEO, videoObj['playerSize']);
return videoObj;
});
const bannerBidRequests = bidRequests.filter(bidRequest => isValid(BANNER, bidRequest)).map(bidRequest => {
Expand All @@ -253,6 +257,7 @@ function requestsToBids(bidRequests) {
bannerObj['sizes'] = parseSizes(bidRequest);
bannerObj['type'] = BANNER;
bannerObj['mediaTypeInfo'] = deepClone(bidRequest.mediaTypes.banner);
bannerObj['priceFloors'] = getBidFloor(bidRequest, BANNER, bannerObj['sizes']);
return bannerObj;
});
return videoBidRequests.concat(bannerBidRequests);
Expand All @@ -265,6 +270,7 @@ function setGeneralInfo(bidRequest) {
this['bidderRequestId'] = bidRequest.bidderRequestId;
this['auctionId'] = bidRequest.auctionId;
this['transactionId'] = bidRequest.transactionId;
this['gpid'] = deepAccess(bidRequest, 'ortb2Imp.ext.gpid') || deepAccess(bidRequest, 'ortb2Imp.ext.data.pbadslot');
this['pubId'] = params.pubId;
this['ext'] = params.ext;
if (params.pubClick) {
Expand Down Expand Up @@ -373,6 +379,37 @@ function getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent) {
return syncs;
}

function getBidFloor(bidRequest, mediaType, sizes) {
const priceFloors = [];
if (typeof bidRequest.getFloor === 'function') {
sizes.forEach(size => {
const floor = bidRequest.getFloor({
currency: 'EUR',
mediaType: mediaType || '*',
size: [size.width, size.height]
});
floor.size = deepClone(size);
if (!floor.floor) { floor.floor = null; }
priceFloors.push(floor);
});
}
return priceFloors;
}

export function isSchainValid(schain) {
let isValid = false;
const requiredFields = ['asi', 'sid', 'hp'];
if (!schain || !schain.nodes) return isValid;
isValid = schain.nodes.reduce((status, node) => {
if (!status) return status;
return requiredFields.every(field => node.hasOwnProperty(field));
}, true);
if (!isValid) {
logError('OneTag: required schain params missing');
}
return isValid;
}

export const spec = {
code: BIDDER_CODE,
gvlid: GVLID,
Expand Down
57 changes: 53 additions & 4 deletions test/spec/modules/onetagBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { spec, isValid, hasTypeVideo } from 'modules/onetagBidAdapter.js';
import { spec, isValid, hasTypeVideo, isSchainValid } from 'modules/onetagBidAdapter.js';
import { expect } from 'chai';
import {find} from 'src/polyfill.js';
import { BANNER, VIDEO } from 'src/mediaTypes.js';
Expand All @@ -15,7 +15,21 @@ describe('onetag', function () {
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475',
'transactionId': 'qwerty123'
'transactionId': 'qwerty123',
'schain': {
'validation': 'off',
'config': {
'ver': '1.0',
'complete': 1,
'nodes': [
{
'asi': 'indirectseller.com',
'sid': '00001',
'hp': 1
}
]
}
},
};
}

Expand Down Expand Up @@ -193,7 +207,8 @@ describe('onetag', function () {
'context',
'playerSize',
'mediaTypeInfo',
'type'
'type',
'priceFloors'
);
} else if (isValid(BANNER, bid)) {
expect(bid).to.have.all.keys(
Expand All @@ -205,9 +220,13 @@ describe('onetag', function () {
'transactionId',
'mediaTypeInfo',
'sizes',
'type'
'type',
'priceFloors'
);
}
if (bid.schain && isSchainValid(bid.schain)) {
expect(data).to.have.all.keys('schain');
}
expect(bid.bidId).to.be.a('string');
expect(bid.pubId).to.be.a('string');
}
Expand Down Expand Up @@ -358,6 +377,36 @@ describe('onetag', function () {
expect(syncs[0].url).to.match(/(?:[?&](?:us_privacy=us_foo(?:[&][^&]*)*))+$/);
});
});
describe('isSchainValid', function () {
it('Should return false when schain is null or undefined', function () {
expect(isSchainValid(null)).to.be.false;
expect(isSchainValid(undefined)).to.be.false;
});
it('Should return false when schain is missing nodes key', function () {
const schain = {'otherKey': 'otherValue'};
expect(isSchainValid(schain)).to.be.false;
});
it('Should return false when schain is missing one of the required SupplyChainNode attribute', function () {
const missingAsiNode = {'sid': '00001', 'hp': 1};
const missingSidNode = {'asi': 'indirectseller.com', 'hp': 1};
const missingHpNode = {'asi': 'indirectseller.com', 'sid': '00001'};
expect(isSchainValid({'config': {'nodes': [missingAsiNode]}})).to.be.false;
expect(isSchainValid({'config': {'nodes': [missingSidNode]}})).to.be.false;
expect(isSchainValid({'config': {'nodes': [missingHpNode]}})).to.be.false;
});
it('Should return true when schain contains all required attributes', function () {
const validSchain = {
'nodes': [
{
'asi': 'indirectseller.com',
'sid': '00001',
'hp': 1
}
]
};
expect(isSchainValid(validSchain)).to.be.true;
})
});
});

function getBannerVideoResponse() {
Expand Down