From 4c7a83dd2ee1b756d3570baf43e1082476734c97 Mon Sep 17 00:00:00 2001 From: Mikael Lundin Date: Mon, 13 May 2024 20:32:22 +0200 Subject: [PATCH] Site Ext Data to kvs. (#11465) --- modules/adnuntiusBidAdapter.js | 17 +- test/spec/modules/adnuntiusBidAdapter_spec.js | 161 +++++++++++------- 2 files changed, 113 insertions(+), 65 deletions(-) diff --git a/modules/adnuntiusBidAdapter.js b/modules/adnuntiusBidAdapter.js index 9c8aa5dd5c4..060f87c0f9c 100644 --- a/modules/adnuntiusBidAdapter.js +++ b/modules/adnuntiusBidAdapter.js @@ -146,6 +146,15 @@ const storageTool = (function () { return segments } + const getKvsFromOrtb = function (ortb2) { + const siteData = deepAccess(ortb2, 'site.ext.data'); + if (siteData) { + return siteData + } else { + return null + } + } + return { refreshStorage: function (bidderRequest) { const ortb2 = bidderRequest.ortb2 || {}; @@ -163,18 +172,19 @@ const storageTool = (function () { }); } metaInternal.segments = getSegmentsFromOrtb(ortb2); + metaInternal.kv = getKvsFromOrtb(ortb2); }, saveToStorage: function (serverData, network) { setMetaInternal(serverData, network); }, getUrlRelatedData: function () { // getting the URL information is theoretically not network-specific - const { segments, usi, voidAuIdsArray } = metaInternal; - return { segments, usi, voidAuIdsArray }; + const { segments, kv, usi, voidAuIdsArray } = metaInternal; + return { segments, kv, usi, voidAuIdsArray }; }, getPayloadRelatedData: function (network) { // getting the payload data should be network-specific - const { segments, usi, userId, voidAuIdsArray, voidAuIds, ...payloadRelatedData } = getMetaDataFromLocalStorage(network).reduce((a, entry) => ({...a, [entry.key]: entry.value}), {}); + const { segments, kv, usi, userId, voidAuIdsArray, voidAuIds, ...payloadRelatedData } = getMetaDataFromLocalStorage(network).reduce((a, entry) => ({ ...a, [entry.key]: entry.value }), {}); return payloadRelatedData; } }; @@ -252,6 +262,7 @@ export const spec = { } const targeting = bid.params.targeting || {}; + if (urlRelatedMetaData.kv) targeting.kv = urlRelatedMetaData.kv; const adUnit = { ...targeting, auId: bid.params.auId, targetId: bid.params.targetId || bid.bidId }; const maxDeals = Math.max(0, Math.min(bid.params.maxDeals || 0, MAXIMUM_DEALS_LIMIT)); if (maxDeals > 0) { diff --git a/test/spec/modules/adnuntiusBidAdapter_spec.js b/test/spec/modules/adnuntiusBidAdapter_spec.js index cad5e9ea1cf..c288bfb4f12 100644 --- a/test/spec/modules/adnuntiusBidAdapter_spec.js +++ b/test/spec/modules/adnuntiusBidAdapter_spec.js @@ -1,18 +1,18 @@ // import or require modules necessary for the test, e.g.: -import {expect} from 'chai'; // may prefer 'assert' in place of 'expect' -import {misc, spec} from 'modules/adnuntiusBidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; -import {config} from 'src/config.js'; +import { expect } from 'chai'; // may prefer 'assert' in place of 'expect' +import { misc, spec } from 'modules/adnuntiusBidAdapter.js'; +import { newBidder } from 'src/adapters/bidderFactory.js'; +import { config } from 'src/config.js'; import * as utils from 'src/utils.js'; -import {getStorageManager} from 'src/storageManager.js'; -import {getGlobal} from '../../../src/prebidGlobal'; +import { getStorageManager } from 'src/storageManager.js'; +import { getGlobal } from '../../../src/prebidGlobal'; -describe('adnuntiusBidAdapter', function() { +describe('adnuntiusBidAdapter', function () { const URL = 'https://ads.adnuntius.delivery/i?tzo='; const EURO_URL = 'https://europe.delivery.adnuntius.com/i?tzo='; const usi = utils.generateUUID() - const meta = [{key: 'valueless'}, {value: 'keyless'}, {key: 'voidAuIds'}, {key: 'voidAuIds', value: [{auId: '11118b6bc', exp: misc.getUnixTimestamp()}, {exp: misc.getUnixTimestamp(1)}]}, {key: 'valid-withnetwork', value: 'also-valid-network', network: 'the-network', exp: misc.getUnixTimestamp(1)}, {key: 'valid', value: 'also-valid', exp: misc.getUnixTimestamp(1)}, {key: 'expired', value: 'fwefew', exp: misc.getUnixTimestamp()}, {key: 'usi', value: 'should be skipped because timestamp', exp: misc.getUnixTimestamp(), network: 'adnuntius'}, {key: 'usi', value: usi, exp: misc.getUnixTimestamp(100), network: 'adnuntius'}, {key: 'usi', value: 'should be skipped because timestamp', exp: misc.getUnixTimestamp()}] + const meta = [{ key: 'valueless' }, { value: 'keyless' }, { key: 'voidAuIds' }, { key: 'voidAuIds', value: [{ auId: '11118b6bc', exp: misc.getUnixTimestamp() }, { exp: misc.getUnixTimestamp(1) }] }, { key: 'valid-withnetwork', value: 'also-valid-network', network: 'the-network', exp: misc.getUnixTimestamp(1) }, { key: 'valid', value: 'also-valid', exp: misc.getUnixTimestamp(1) }, { key: 'expired', value: 'fwefew', exp: misc.getUnixTimestamp() }, { key: 'usi', value: 'should be skipped because timestamp', exp: misc.getUnixTimestamp(), network: 'adnuntius' }, { key: 'usi', value: usi, exp: misc.getUnixTimestamp(100), network: 'adnuntius' }, { key: 'usi', value: 'should be skipped because timestamp', exp: misc.getUnixTimestamp() }] let storage; // need this to make the restore work correctly -- something to do with stubbing static prototype methods @@ -24,7 +24,7 @@ describe('adnuntiusBidAdapter', function() { storageAllowed: true } }; - storage = getStorageManager({bidderCode: 'adnuntius'}); + storage = getStorageManager({ bidderCode: 'adnuntius' }); }); beforeEach(() => { @@ -35,7 +35,7 @@ describe('adnuntiusBidAdapter', function() { getGlobal().bidderSettings = {}; }); - afterEach(function() { + afterEach(function () { config.resetConfig(); if (stub1.restore) { @@ -453,20 +453,20 @@ describe('adnuntiusBidAdapter', function() { } } - describe('inherited functions', function() { - it('exists and is a function', function() { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', function() { - it('should return true when required params found', function() { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bidderRequests[0])).to.equal(true); }); }); - describe('buildRequests', function() { - it('Test requests', function() { + describe('buildRequests', function () { + it('Test requests', function () { stub1 = sinon.stub(URLSearchParams.prototype, 'has').callsFake(() => { return true; }); @@ -485,7 +485,7 @@ describe('adnuntiusBidAdapter', function() { expect(request[0].data).to.equal('{"adUnits":[{"auId":"000000000008b6bc","targetId":"123","maxDeals":1,"dimensions":[[640,480],[600,400]]},{"auId":"0000000000000551","targetId":"adn-0000000000000551","dimensions":[[1640,1480],[1600,1400]]}]}'); }); - it('Test requests with no local storage', function() { + it('Test requests with no local storage', function () { storage.setDataInLocalStorage('adn.metaData', JSON.stringify([{}])); const request = spec.buildRequests(bidderRequests, {}); expect(request.length).to.equal(1); @@ -504,8 +504,8 @@ describe('adnuntiusBidAdapter', function() { expect(request2[0].url).to.equal(ENDPOINT_URL_BASE); }); - it('Test request changes for voided au ids', function() { - storage.setDataInLocalStorage('adn.metaData', JSON.stringify([{key: 'voidAuIds', value: [{auId: '11118b6bc', exp: misc.getUnixTimestamp(1)}, {auId: '0000000000000023', exp: misc.getUnixTimestamp(1)}]}])); + it('Test request changes for voided au ids', function () { + storage.setDataInLocalStorage('adn.metaData', JSON.stringify([{ key: 'voidAuIds', value: [{ auId: '11118b6bc', exp: misc.getUnixTimestamp(1) }, { auId: '0000000000000023', exp: misc.getUnixTimestamp(1) }] }])); const bRequests = bidderRequests.concat([{ bidId: 'adn-11118b6bc', bidder: 'adnuntius', @@ -556,7 +556,7 @@ describe('adnuntiusBidAdapter', function() { expect(request[0].data).to.equal('{"adUnits":[{"auId":"000000000008b6bc","targetId":"123","maxDeals":1,"dimensions":[[640,480],[600,400]]},{"auId":"0000000000000551","targetId":"adn-0000000000000551","dimensions":[[1640,1480],[1600,1400]]},{"auId":"13","targetId":"adn-13","dimensions":[[164,140],[10,1400]]}]}'); }); - it('Test Video requests', function() { + it('Test Video requests', function () { const request = spec.buildRequests(videoBidderRequest, {}); expect(request.length).to.equal(1); expect(request[0]).to.have.property('bid'); @@ -566,12 +566,12 @@ describe('adnuntiusBidAdapter', function() { expect(request[0].url).to.equal(ENDPOINT_URL_VIDEO); }); - it('should pass segments if available in config', function() { + it('should pass segments if available in config', function () { const ortb2 = { user: { data: [{ name: 'adnuntius', - segment: [{id: 'segment1'}, {id: 'segment2'}, {invalidSegment: 'invalid'}, {id: 123}, {id: ['3332']}] + segment: [{ id: 'segment1' }, { id: 'segment2' }, { invalidSegment: 'invalid' }, { id: 123 }, { id: ['3332'] }] }, { name: 'other', @@ -580,18 +580,55 @@ describe('adnuntiusBidAdapter', function() { } }; - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, {ortb2})); + const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, { ortb2 })); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL_SEGMENTS); }); - it('should skip segments in config if not either id or array of strings', function() { + it('should pass site data ext as key values to ad server', function () { + const ortb2 = { + site: { + ext: { + data: { + '12345': 'true', + '45678': 'true' + } + } + } + }; + + const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, { ortb2 })); + expect(request.length).to.equal(1); + expect(request[0]).to.have.property('url') + const data = JSON.parse(request[0].data); + expect(data.adUnits[0].kv).to.have.property('12345'); + expect(data.adUnits[0].kv['12345']).to.equal('true'); + expect(data.adUnits[0].kv).to.have.property('45678'); + expect(data.adUnits[0].kv['45678']).to.equal('true'); + }); + + it('should skip passing site data ext if missing', function () { + const ortb2 = { + site: { + ext: { + } + } + }; + + const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, { ortb2 })); + expect(request.length).to.equal(1); + expect(request[0]).to.have.property('url') + const data = JSON.parse(request[0].data); + expect(data.adUnits[0]).to.not.have.property('kv'); + }); + + it('should skip segments in config if not either id or array of strings', function () { const ortb2 = { user: { data: [{ name: 'adnuntius', - segment: [{id: 'segment1'}, {id: 'segment2'}, {id: 'segment3'}] + segment: [{ id: 'segment1' }, { id: 'segment2' }, { id: 'segment3' }] }, { name: 'other', @@ -602,34 +639,34 @@ describe('adnuntiusBidAdapter', function() { } }; - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, {ortb2})); + const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, { ortb2 })); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL_SEGMENTS); }); }); - describe('user privacy', function() { - it('should send GDPR Consent data if gdprApplies', function() { - let request = spec.buildRequests(bidderRequests, {gdprConsent: {gdprApplies: true, consentString: 'consentString'}}); + describe('user privacy', function () { + it('should send GDPR Consent data if gdprApplies', function () { + let request = spec.buildRequests(bidderRequests, { gdprConsent: { gdprApplies: true, consentString: 'consentString' } }); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL_CONSENT); }); - it('should not send GDPR Consent data if gdprApplies equals undefined', function() { - let request = spec.buildRequests(bidderRequests, {gdprConsent: {gdprApplies: undefined, consentString: 'consentString'}}); + it('should not send GDPR Consent data if gdprApplies equals undefined', function () { + let request = spec.buildRequests(bidderRequests, { gdprConsent: { gdprApplies: undefined, consentString: 'consentString' } }); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL); }); - it('should pass segments if available in config', function() { + it('should pass segments if available in config', function () { const ortb2 = { user: { data: [{ name: 'adnuntius', - segment: [{id: 'segment1'}, {id: 'segment2'}] + segment: [{ id: 'segment1' }, { id: 'segment2' }] }, { name: 'other', @@ -638,18 +675,18 @@ describe('adnuntiusBidAdapter', function() { } } - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, {ortb2})); + const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, { ortb2 })); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL_SEGMENTS); }); - it('should skip segments in config if not either id or array of strings', function() { + it('should skip segments in config if not either id or array of strings', function () { const ortb2 = { user: { data: [{ name: 'adnuntius', - segment: [{id: 'segment1'}, {id: 'segment2'}, {id: 'segment3'}] + segment: [{ id: 'segment1' }, { id: 'segment2' }, { id: 'segment3' }] }, { name: 'other', @@ -660,20 +697,20 @@ describe('adnuntiusBidAdapter', function() { } }; - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, {ortb2})); + const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, { ortb2 })); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL_SEGMENTS); }); - it('should user user ID if present in ortb2.user.id field', function() { + it('should user user ID if present in ortb2.user.id field', function () { const ortb2 = { user: { id: usi } }; - const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, {ortb2})); + const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidderRequests, { ortb2 })); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL); @@ -721,24 +758,24 @@ describe('adnuntiusBidAdapter', function() { }); }); - describe('user privacy', function() { - it('should send GDPR Consent data if gdprApplies', function() { - let request = spec.buildRequests(bidderRequests, {gdprConsent: {gdprApplies: true, consentString: 'consentString'}}); + describe('user privacy', function () { + it('should send GDPR Consent data if gdprApplies', function () { + let request = spec.buildRequests(bidderRequests, { gdprConsent: { gdprApplies: true, consentString: 'consentString' } }); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL_CONSENT); }); - it('should not send GDPR Consent data if gdprApplies equals undefined', function() { - let request = spec.buildRequests(bidderRequests, {gdprConsent: {gdprApplies: undefined, consentString: 'consentString'}}); + it('should not send GDPR Consent data if gdprApplies equals undefined', function () { + let request = spec.buildRequests(bidderRequests, { gdprConsent: { gdprApplies: undefined, consentString: 'consentString' } }); expect(request.length).to.equal(1); expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL); }); }); - describe('use cookie', function() { - it('should send noCookie in url if set to false.', function() { + describe('use cookie', function () { + it('should send noCookie in url if set to false.', function () { config.setBidderConfig({ bidders: ['adnuntius'], config: { @@ -753,8 +790,8 @@ describe('adnuntiusBidAdapter', function() { }); }); - describe('validate auId', function() { - it('should fail when auId is not hexadecimal', function() { + describe('validate auId', function () { + it('should fail when auId is not hexadecimal', function () { const invalidRequest = { bidId: 'adn-000000000008b6bc', bidder: 'adnuntius', @@ -766,7 +803,7 @@ describe('adnuntiusBidAdapter', function() { expect(valid).to.equal(false); }); - it('should pass when auId is hexadecimal', function() { + it('should pass when auId is hexadecimal', function () { const invalidRequest = { bidId: 'adn-000000000008b6bc', bidder: 'adnuntius', @@ -779,8 +816,8 @@ describe('adnuntiusBidAdapter', function() { }); }); - describe('request deals', function() { - it('Should set max deals.', function() { + describe('request deals', function () { + it('Should set max deals.', function () { config.setBidderConfig({ bidders: ['adnuntius'] }); @@ -797,7 +834,7 @@ describe('adnuntiusBidAdapter', function() { expect(bidderRequests[1].params).to.not.have.property('maxBids'); expect(data.adUnits[1].maxDeals).to.equal(undefined); }); - it('Should allow a maximum of 5 deals.', function() { + it('Should allow a maximum of 5 deals.', function () { config.setBidderConfig({ bidders: ['adnuntius'], }); @@ -820,7 +857,7 @@ describe('adnuntiusBidAdapter', function() { expect(data.adUnits.length).to.equal(1); expect(data.adUnits[0].maxDeals).to.equal(5); }); - it('Should allow a minumum of 0 deals.', function() { + it('Should allow a minumum of 0 deals.', function () { config.setBidderConfig({ bidders: ['adnuntius'], }); @@ -843,7 +880,7 @@ describe('adnuntiusBidAdapter', function() { expect(data.adUnits.length).to.equal(1); expect(data.adUnits[0].maxDeals).to.equal(undefined); }); - it('Should set max deals using bidder config.', function() { + it('Should set max deals using bidder config.', function () { config.setBidderConfig({ bidders: ['adnuntius'], config: { @@ -856,7 +893,7 @@ describe('adnuntiusBidAdapter', function() { expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL + '&ds=2'); }); - it('Should allow a maximum of 5 deals when using bidder config.', function() { + it('Should allow a maximum of 5 deals when using bidder config.', function () { config.setBidderConfig({ bidders: ['adnuntius'], config: { @@ -869,7 +906,7 @@ describe('adnuntiusBidAdapter', function() { expect(request[0]).to.have.property('url') expect(request[0].url).to.equal(ENDPOINT_URL + '&ds=5'); }); - it('Should allow a minimum of 0 deals when using bidder config.', function() { + it('Should allow a minimum of 0 deals when using bidder config.', function () { config.setBidderConfig({ bidders: ['adnuntius'], config: { @@ -885,8 +922,8 @@ describe('adnuntiusBidAdapter', function() { }); }); - describe('interpretResponse', function() { - it('should return valid response when passed valid server response', function() { + describe('interpretResponse', function () { + it('should return valid response when passed valid server response', function () { config.setBidderConfig({ bidders: ['adnuntius'], config: { @@ -960,7 +997,7 @@ describe('adnuntiusBidAdapter', function() { expect(randomApiEntry.exp).to.be.greaterThan(misc.getUnixTimestamp(90)); }); - it('should not process valid response when passed alt bidder that is an adndeal', function() { + it('should not process valid response when passed alt bidder that is an adndeal', function () { const altBidder = { bid: [ { @@ -978,7 +1015,7 @@ describe('adnuntiusBidAdapter', function() { serverResponse.body.adUnits[0].deals = deals; }); - it('should return valid response when passed alt bidder', function() { + it('should return valid response when passed alt bidder', function () { const altBidder = { bid: [ { @@ -1015,8 +1052,8 @@ describe('adnuntiusBidAdapter', function() { }); }); - describe('interpretVideoResponse', function() { - it('should return valid response when passed valid server response', function() { + describe('interpretVideoResponse', function () { + it('should return valid response when passed valid server response', function () { const interpretedResponse = spec.interpretResponse(serverVideoResponse, videoBidRequest); const ad = serverVideoResponse.body.adUnits[0].ads[0] const deal = serverVideoResponse.body.adUnits[0].deals[0]