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

KueezRtb Bid Adapter : pass gpp and bid data to server. #9491

Merged
merged 2 commits into from
Feb 12, 2023
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
74 changes: 54 additions & 20 deletions modules/kueezRtbBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { _each, deepAccess, parseSizesInput, parseUrl, uniques, isFn } from '../src/utils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { getStorageManager } from '../src/storageManager.js';
import {_each, deepAccess, parseSizesInput, parseUrl, uniques, isFn} from '../src/utils.js';
import {registerBidder} from '../src/adapters/bidderFactory.js';
import {BANNER, VIDEO} from '../src/mediaTypes.js';
import {getStorageManager} from '../src/storageManager.js';
import { config } from '../src/config.js';

const GVLID = 1165;
const DEFAULT_SUB_DOMAIN = 'exchange';
Expand All @@ -22,11 +23,11 @@ export const SUPPORTED_ID_SYSTEMS = {
'tdid': 1,
'pubProvidedId': 1
};
const storage = getStorageManager({ gvlid: GVLID, bidderCode: BIDDER_CODE });
const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE});

function getTopWindowQueryParams() {
try {
const parsedUrl = parseUrl(window.top.document.URL, { decodeSearchAsString: true });
const parsedUrl = parseUrl(window.top.document.URL, {decodeSearchAsString: true});
return parsedUrl.search;
} catch (e) {
return '';
Expand Down Expand Up @@ -54,9 +55,22 @@ function isBidRequestValid(bid) {
return !!(extractCID(params) && extractPID(params));
}

function buildRequest(bid, topWindowUrl, sizes, bidderRequest) {
const { params, bidId, userId, adUnitCode, schain, mediaTypes } = bid;
let { bidFloor, ext } = params;
function buildRequest(bid, topWindowUrl, sizes, bidderRequest, bidderTimeout) {
const {
params,
bidId,
userId,
adUnitCode,
schain,
mediaTypes,
auctionId,
transactionId,
bidderRequestId,
bidRequestsCount,
bidderRequestsCount,
bidderWinsCount
} = bid;
let {bidFloor, ext} = params;
const hashUrl = hashCode(topWindowUrl);
const uniqueDealId = getUniqueDealId(hashUrl);
const cId = extractCID(params);
Expand Down Expand Up @@ -90,7 +104,14 @@ function buildRequest(bid, topWindowUrl, sizes, bidderRequest) {
prebidVersion: '$prebid.version$',
res: `${screen.width}x${screen.height}`,
schain: schain,
mediaTypes: mediaTypes
mediaTypes: mediaTypes,
auctionId: auctionId,
transactionId: transactionId,
bidderRequestId: bidderRequestId,
bidRequestsCount: bidRequestsCount,
bidderRequestsCount: bidderRequestsCount,
bidderWinsCount: bidderWinsCount,
bidderTimeout: bidderTimeout
};

appendUserIdsToRequestPayload(data, userId);
Expand All @@ -107,6 +128,14 @@ function buildRequest(bid, topWindowUrl, sizes, bidderRequest) {
data.usPrivacy = bidderRequest.uspConsent;
}

if (bidderRequest.gppConsent) {
data.gppString = bidderRequest.gppConsent.gppString;
data.gppSid = bidderRequest.gppConsent.applicableSections;
} else if (bidderRequest.ortb2?.regs?.gpp) {
data.gppString = bidderRequest.ortb2.regs.gpp;
data.gppSid = bidderRequest.ortb2.regs.gpp_sid;
}

const dto = {
method: 'POST',
url: `${createDomain(subDomain)}/prebid/multi/${cId}`,
Expand Down Expand Up @@ -148,10 +177,11 @@ function appendUserIdsToRequestPayload(payloadRef, userIds) {

function buildRequests(validBidRequests, bidderRequest) {
const topWindowUrl = bidderRequest.refererInfo.page || bidderRequest.refererInfo.topmostLocation;
const bidderTimeout = config.getConfig('bidderTimeout');
const requests = [];
validBidRequests.forEach(validBidRequest => {
const sizes = parseSizesInput(validBidRequest.sizes);
const request = buildRequest(validBidRequest, topWindowUrl, sizes, bidderRequest);
const request = buildRequest(validBidRequest, topWindowUrl, sizes, bidderRequest, bidderTimeout);
requests.push(request);
});
return requests;
Expand All @@ -161,14 +191,14 @@ function interpretResponse(serverResponse, request) {
if (!serverResponse || !serverResponse.body) {
return [];
}
const { bidId } = request.data;
const { results } = serverResponse.body;
const {bidId} = request.data;
const {results} = serverResponse.body;

let output = [];

try {
results.forEach(result => {
const { creativeId, ad, price, exp, width, height, currency, advertiserDomains, mediaType = BANNER } = result;
const {creativeId, ad, price, exp, width, height, currency, advertiserDomains, mediaType = BANNER} = result;
if (!ad || !price) {
return;
}
Expand Down Expand Up @@ -207,8 +237,8 @@ function interpretResponse(serverResponse, request) {

function getUserSyncs(syncOptions, responses, gdprConsent = {}, uspConsent = '') {
let syncs = [];
const { iframeEnabled, pixelEnabled } = syncOptions;
const { gdprApplies, consentString = '' } = gdprConsent;
const {iframeEnabled, pixelEnabled} = syncOptions;
const {gdprApplies, consentString = ''} = gdprConsent;

const cidArr = responses.filter(resp => deepAccess(resp, 'body.cid')).map(resp => resp.body.cid).filter(uniques);
const params = `?cid=${encodeURIComponent(cidArr.join(','))}&gdpr=${gdprApplies ? 1 : 0}&gdpr_consent=${encodeURIComponent(consentString || '')}&us_privacy=${encodeURIComponent(uspConsent || '')}`
Expand All @@ -232,7 +262,9 @@ export function hashCode(s, prefix = '_') {
let h = 0
let i = 0;
if (l > 0) {
while (i < l) { h = (h << 5) - h + s.charCodeAt(i++) | 0; }
while (i < l) {
h = (h << 5) - h + s.charCodeAt(i++) | 0;
}
}
return prefix + h;
}
Expand All @@ -256,17 +288,19 @@ export function getUniqueDealId(key, expiry = UNIQUE_DEAL_ID_EXPIRY) {
export function getStorageItem(key) {
try {
return tryParseJSON(storage.getDataFromLocalStorage(key));
} catch (e) { }
} catch (e) {
}

return null;
}

export function setStorageItem(key, value, timestamp) {
try {
const created = timestamp || Date.now();
const data = JSON.stringify({ value, created });
const data = JSON.stringify({value, created});
storage.setDataInLocalStorage(key, data);
} catch (e) { }
} catch (e) {
}
}

export function tryParseJSON(value) {
Expand Down
85 changes: 63 additions & 22 deletions test/spec/modules/kueezRtbBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect } from 'chai';
import {expect} from 'chai';
import {
spec as adapter,
SUPPORTED_ID_SYSTEMS,
Expand All @@ -13,9 +13,10 @@ import {
getUniqueDealId,
} from 'modules/kueezRtbBidAdapter.js';
import * as utils from 'src/utils.js';
import { version } from 'package.json';
import { useFakeTimers } from 'sinon';
import { BANNER, VIDEO } from '../../../src/mediaTypes';
import {version} from 'package.json';
import {useFakeTimers} from 'sinon';
import {BANNER, VIDEO} from '../../../src/mediaTypes';
import {config} from '../../../src/config';

const SUB_DOMAIN = 'exchange';

Expand All @@ -36,6 +37,10 @@ const BID = {
'transactionId': 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf',
'sizes': [[300, 250], [300, 600]],
'bidderRequestId': '1fdb5ff1b6eaa7',
'auctionId': 'auction_id',
'bidRequestsCount': 4,
'bidderRequestsCount': 3,
'bidderWinsCount': 1,
'requestId': 'b0777d85-d061-450e-9bc7-260dd54bbb7a',
'schain': 'a0819c69-005b-41ed-af06-1be1e0aefefc',
'mediaTypes': [BANNER]
Expand All @@ -46,6 +51,10 @@ const VIDEO_BID = {
'adUnitCode': '63550ad1ff6642d368cba59dh5884270560',
'bidderRequestId': '12a8ae9ada9c13',
'transactionId': '56e184c6-bde9-497b-b9b9-cf47a61381ee',
'auctionId': 'auction_id',
'bidRequestsCount': 4,
'bidderRequestsCount': 3,
'bidderWinsCount': 1,
'schain': 'a0819c69-005b-41ed-af06-1be1e0aefefc',
'params': {
'subDomain': SUB_DOMAIN,
Expand Down Expand Up @@ -78,10 +87,18 @@ const BIDDER_REQUEST = {
'consentString': 'consent_string',
'gdprApplies': true
},
'gppString': 'gpp_string',
'gppSid': [7],
'uspConsent': 'consent_string',
'refererInfo': {
'page': 'https://www.greatsite.com',
'ref': 'https://www.somereferrer.com'
},
'ortb2': {
'regs': {
'gpp': 'gpp_string',
'gpp_sid': [7]
}
}
};

Expand Down Expand Up @@ -134,7 +151,7 @@ const REQUEST = {

function getTopWindowQueryParams() {
try {
const parsedUrl = utils.parseUrl(window.top.document.URL, { decodeSearchAsString: true });
const parsedUrl = utils.parseUrl(window.top.document.URL, {decodeSearchAsString: true});
return parsedUrl.search;
} catch (e) {
return '';
Expand Down Expand Up @@ -213,6 +230,9 @@ describe('KueezRtbBidAdapter', function () {

it('should build video request', function () {
const hashUrl = hashCode(BIDDER_REQUEST.refererInfo.page);
config.setConfig({
bidderTimeout: 3000
});
const requests = adapter.buildRequests([VIDEO_BID], BIDDER_REQUEST);
expect(requests).to.have.length(1);
expect(requests[0]).to.deep.equal({
Expand All @@ -223,11 +243,20 @@ describe('KueezRtbBidAdapter', function () {
bidFloor: 0.1,
bidId: '2d52001cabd527',
bidderVersion: adapter.version,
bidderRequestId: '12a8ae9ada9c13',
cb: 1000,
gdpr: 1,
gdprConsent: 'consent_string',
usPrivacy: 'consent_string',
gppString: 'gpp_string',
gppSid: [7],
prebidVersion: version,
transactionId: '56e184c6-bde9-497b-b9b9-cf47a61381ee',
auctionId: 'auction_id',
bidRequestsCount: 4,
bidderRequestsCount: 3,
bidderWinsCount: 1,
bidderTimeout: 3000,
publisherId: '59ac17c192832d0011283fe3',
url: 'https%3A%2F%2Fwww.greatsite.com',
referrer: 'https://www.somereferrer.com',
Expand Down Expand Up @@ -259,6 +288,9 @@ describe('KueezRtbBidAdapter', function () {

it('should build banner request for each size', function () {
const hashUrl = hashCode(BIDDER_REQUEST.refererInfo.page);
config.setConfig({
bidderTimeout: 3000
});
const requests = adapter.buildRequests([BID], BIDDER_REQUEST);
expect(requests).to.have.length(1);
expect(requests[0]).to.deep.equal({
Expand All @@ -267,7 +299,16 @@ describe('KueezRtbBidAdapter', function () {
data: {
gdprConsent: 'consent_string',
gdpr: 1,
gppString: 'gpp_string',
gppSid: [7],
usPrivacy: 'consent_string',
transactionId: 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf',
auctionId: 'auction_id',
bidRequestsCount: 4,
bidderRequestsCount: 3,
bidderWinsCount: 1,
bidderTimeout: 3000,
bidderRequestId: '1fdb5ff1b6eaa7',
sizes: ['300x250', '300x600'],
url: 'https%3A%2F%2Fwww.greatsite.com',
referrer: 'https://www.somereferrer.com',
Expand Down Expand Up @@ -296,7 +337,7 @@ describe('KueezRtbBidAdapter', function () {
});
describe('getUserSyncs', function () {
it('should have valid user sync with iframeEnabled', function () {
const result = adapter.getUserSyncs({ iframeEnabled: true }, [SERVER_RESPONSE]);
const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]);

expect(result).to.deep.equal([{
type: 'iframe',
Expand All @@ -305,15 +346,15 @@ describe('KueezRtbBidAdapter', function () {
});

it('should have valid user sync with cid on response', function () {
const result = adapter.getUserSyncs({ iframeEnabled: true }, [SERVER_RESPONSE]);
const result = adapter.getUserSyncs({iframeEnabled: true}, [SERVER_RESPONSE]);
expect(result).to.deep.equal([{
type: 'iframe',
url: 'https://sync.kueezrtb.com/api/sync/iframe/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy='
}]);
});

it('should have valid user sync with pixelEnabled', function () {
const result = adapter.getUserSyncs({ pixelEnabled: true }, [SERVER_RESPONSE]);
const result = adapter.getUserSyncs({pixelEnabled: true}, [SERVER_RESPONSE]);

expect(result).to.deep.equal([{
'url': 'https://sync.kueezrtb.com/api/sync/image/?cid=testcid123&gdpr=0&gdpr_consent=&us_privacy=',
Expand All @@ -329,12 +370,12 @@ describe('KueezRtbBidAdapter', function () {
});

it('should return empty array when there is no ad', function () {
const responses = adapter.interpretResponse({ price: 1, ad: '' });
const responses = adapter.interpretResponse({price: 1, ad: ''});
expect(responses).to.be.empty;
});

it('should return empty array when there is no price', function () {
const responses = adapter.interpretResponse({ price: null, ad: 'great ad' });
const responses = adapter.interpretResponse({price: null, ad: 'great ad'});
expect(responses).to.be.empty;
});

Expand Down Expand Up @@ -394,11 +435,11 @@ describe('KueezRtbBidAdapter', function () {
const userId = (function () {
switch (idSystemProvider) {
case 'lipb':
return { lipbid: id };
return {lipbid: id};
case 'parrableId':
return { eid: id };
return {eid: id};
case 'id5id':
return { uid: id };
return {uid: id};
default:
return id;
}
Expand All @@ -417,18 +458,18 @@ describe('KueezRtbBidAdapter', function () {

describe('alternate param names extractors', function () {
it('should return undefined when param not supported', function () {
const cid = extractCID({ 'c_id': '1' });
const pid = extractPID({ 'p_id': '1' });
const subDomain = extractSubDomain({ 'sub_domain': 'prebid' });
const cid = extractCID({'c_id': '1'});
const pid = extractPID({'p_id': '1'});
const subDomain = extractSubDomain({'sub_domain': 'prebid'});
expect(cid).to.be.undefined;
expect(pid).to.be.undefined;
expect(subDomain).to.be.undefined;
});

it('should return value when param supported', function () {
const cid = extractCID({ 'cID': '1' });
const pid = extractPID({ 'Pid': '2' });
const subDomain = extractSubDomain({ 'subDOMAIN': 'prebid' });
const cid = extractCID({'cID': '1'});
const pid = extractPID({'Pid': '2'});
const subDomain = extractSubDomain({'subDOMAIN': 'prebid'});
expect(cid).to.be.equal('1');
expect(pid).to.be.equal('2');
expect(subDomain).to.be.equal('prebid');
Expand Down Expand Up @@ -488,7 +529,7 @@ describe('KueezRtbBidAdapter', function () {
now
});
setStorageItem('myKey', 2020);
const { value, created } = getStorageItem('myKey');
const {value, created} = getStorageItem('myKey');
expect(created).to.be.equal(now);
expect(value).to.be.equal(2020);
expect(typeof value).to.be.equal('number');
Expand All @@ -504,8 +545,8 @@ describe('KueezRtbBidAdapter', function () {
});

it('should parse JSON value', function () {
const data = JSON.stringify({ event: 'send' });
const { event } = tryParseJSON(data);
const data = JSON.stringify({event: 'send'});
const {event} = tryParseJSON(data);
expect(event).to.be.equal('send');
});

Expand Down