Skip to content

Commit 185ae3d

Browse files
nickjacobjorgeluisrocha
authored andcommitted
AMX Bid Adapter: add gpp support (prebid#9556)
* AMX bid adapter: add gpp support, cookie sync improvements * fix unit tests
1 parent 5e3e583 commit 185ae3d

File tree

2 files changed

+196
-4
lines changed

2 files changed

+196
-4
lines changed

modules/amxBidAdapter.js

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
triggerPixel,
1010
isFn,
1111
logError,
12+
isArray,
1213
} from '../src/utils.js';
1314
import { config } from '../src/config.js';
1415
import { getStorageManager } from '../src/storageManager.js';
@@ -192,6 +193,51 @@ function resolveSize(bid, request, bidId) {
192193
return [bidRequest.aw, bidRequest.ah];
193194
}
194195

196+
function isSyncEnabled(syncConfigP, syncType) {
197+
const syncConfig = syncConfigP[syncType];
198+
if (syncConfig == null) {
199+
return false;
200+
}
201+
202+
if (syncConfig.bidders === '*' || (isArray(syncConfig.bidders) && syncConfig.bidders.indexOf('amx') !== -1)) {
203+
return syncConfig.filter == null || syncConfig.filter === 'include';
204+
}
205+
206+
return false;
207+
}
208+
209+
const SYNC_IMAGE = 1;
210+
const SYNC_IFRAME = 2;
211+
212+
function getSyncSettings() {
213+
const syncConfig = config.getConfig('userSync');
214+
if (syncConfig == null) {
215+
return {
216+
d: 0,
217+
l: 0,
218+
t: 0,
219+
e: true
220+
};
221+
}
222+
223+
const settings = { d: syncConfig.syncDelay, l: syncConfig.syncsPerBidder, t: 0, e: syncConfig.syncEnabled }
224+
const all = isSyncEnabled(syncConfig.filterSettings, 'all')
225+
226+
if (all) {
227+
settings.t = SYNC_IMAGE & SYNC_IFRAME;
228+
return settings;
229+
}
230+
231+
if (isSyncEnabled(syncConfig.filterSettings, 'iframe')) {
232+
settings.t |= SYNC_IFRAME;
233+
}
234+
if (isSyncEnabled(syncConfig.filterSettings, 'image')) {
235+
settings.t |= SYNC_IMAGE;
236+
}
237+
238+
return settings;
239+
}
240+
195241
function values(source) {
196242
if (Object.values != null) {
197243
return Object.values(source);
@@ -202,6 +248,30 @@ function values(source) {
202248
});
203249
}
204250

251+
function getGpp(bidderRequest) {
252+
if (bidderRequest?.gppConsent != null) {
253+
return bidderRequest.gppConsent;
254+
}
255+
256+
return bidderRequest?.ortb2?.regs?.gpp ?? {gppString: '', applicableSections: ''};
257+
}
258+
259+
function buildReferrerInfo(bidderRequest) {
260+
if (bidderRequest.refererInfo == null) {
261+
return {r: '', t: false, c: '', l: 0, s: []}
262+
}
263+
264+
const re = bidderRequest.refererInfo;
265+
266+
return {
267+
r: re.topmostLocation,
268+
t: re.reachedTop,
269+
l: re.numIframes,
270+
s: re.stack,
271+
c: re.canonicalUrl,
272+
}
273+
}
274+
205275
const isTrue = (boolValue) =>
206276
boolValue === true || boolValue === 1 || boolValue === 'true';
207277

@@ -249,6 +319,7 @@ export const spec = {
249319
w: screen.width,
250320
gs: deepAccess(bidderRequest, 'gdprConsent.gdprApplies', ''),
251321
gc: deepAccess(bidderRequest, 'gdprConsent.consentString', ''),
322+
gpp: getGpp(bidderRequest),
252323
u: refInfo(bidderRequest, 'page', loc.href),
253324
do: refInfo(bidderRequest, 'site', loc.hostname),
254325
re: refInfo(bidderRequest, 'ref'),
@@ -261,6 +332,8 @@ export const spec = {
261332
fpd2: bidderRequest.ortb2,
262333
tmax: config.getConfig('bidderTimeout'),
263334
amp: refInfo(bidderRequest, 'isAmp', null),
335+
ri: buildReferrerInfo(bidderRequest),
336+
sync: getSyncSettings(),
264337
eids: values(
265338
bidRequests.reduce((all, bid) => {
266339
// we only want unique ones in here
@@ -287,17 +360,38 @@ export const spec = {
287360
};
288361
},
289362

290-
getUserSyncs(syncOptions, serverResponses) {
363+
getUserSyncs(syncOptions, serverResponses, gdprConsent, uspConsent, gppConsent) {
364+
const qp = {
365+
gdpr_consent: enc(gdprConsent?.consentString || ''),
366+
gdpr: enc(gdprConsent?.gdprApplies ? 1 : 0),
367+
us_privacy: enc(uspConsent || ''),
368+
gpp: enc(gppConsent?.gppString || ''),
369+
gpp_sid: enc(gppConsent?.applicableSections || '')
370+
};
371+
372+
const iframeSync = {
373+
url: `https://prebid.a-mo.net/isyn?${formatQS(qp)}`,
374+
type: 'iframe'
375+
};
376+
291377
if (serverResponses == null || serverResponses.length === 0) {
378+
if (syncOptions.iframeEnabled) {
379+
return [iframeSync]
380+
}
381+
292382
return [];
293383
}
384+
294385
const output = [];
386+
let hasFrame = false;
387+
295388
_each(serverResponses, function ({ body: response }) {
296389
if (response != null && response.p != null && response.p.hreq) {
297390
_each(response.p.hreq, function (syncPixel) {
298391
const pixelType =
299392
syncPixel.indexOf('__st=iframe') !== -1 ? 'iframe' : 'image';
300393
if (syncOptions.iframeEnabled || pixelType === 'image') {
394+
hasFrame = hasFrame || (pixelType === 'iframe') || (syncPixel.indexOf('cchain') !== -1)
301395
output.push({
302396
url: syncPixel,
303397
type: pixelType,
@@ -306,6 +400,11 @@ export const spec = {
306400
});
307401
}
308402
});
403+
404+
if (!hasFrame && output.length < 2) {
405+
output.push(iframeSync)
406+
}
407+
309408
return output;
310409
},
311410

test/spec/modules/amxBidAdapter_spec.js

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { expect } from 'chai';
22
import { spec } from 'modules/amxBidAdapter.js';
33
import { createEidsArray } from 'modules/userId/eids.js';
44
import { BANNER, VIDEO } from 'src/mediaTypes.js';
5+
import { config } from 'src/config.js';
56
import * as utils from 'src/utils.js';
67

78
const sampleRequestId = '82c91e127a9b93e';
@@ -34,9 +35,17 @@ const sampleBidderRequest = {
3435
consentString: utils.getUniqueIdentifierStr(),
3536
vendorData: {},
3637
},
38+
gppConsent: {
39+
gppString: 'example',
40+
applicableSections: 'example'
41+
},
3742
auctionId: utils.getUniqueIdentifierStr(),
3843
uspConsent: '1YYY',
3944
refererInfo: {
45+
reachedTop: true,
46+
numIframes: 10,
47+
stack: ['https://www.prebid.org'],
48+
canonicalUrl: 'https://prebid.org',
4049
location: 'https://www.prebid.org',
4150
site: 'prebid.org',
4251
topmostLocation: 'https://www.prebid.org',
@@ -195,9 +204,12 @@ describe('AmxBidAdapter', () => {
195204
});
196205
});
197206
describe('getUserSync', () => {
198-
it('will only sync from valid server responses', () => {
207+
it('Will perform an iframe sync even if there is no server response..', () => {
199208
const syncs = spec.getUserSyncs({ iframeEnabled: true });
200-
expect(syncs).to.eql([]);
209+
expect(syncs).to.eql([{
210+
type: 'iframe',
211+
url: 'https://prebid.a-mo.net/isyn?gdpr_consent=&gdpr=0&us_privacy=&gpp=&gpp_sid='
212+
}]);
201213
});
202214

203215
it('will return valid syncs from a server response', () => {
@@ -260,6 +272,15 @@ describe('AmxBidAdapter', () => {
260272
expect(data.tm).to.equal(true);
261273
});
262274

275+
it('will attach additional referrer info data', () => {
276+
const { data } = spec.buildRequests([sampleBidRequestBase], sampleBidderRequest);
277+
expect(data.ri.r).to.equal(sampleBidderRequest.refererInfo.topmostLocation);
278+
expect(data.ri.t).to.equal(sampleBidderRequest.refererInfo.reachedTop);
279+
expect(data.ri.l).to.equal(sampleBidderRequest.refererInfo.numIframes);
280+
expect(data.ri.s).to.equal(sampleBidderRequest.refererInfo.stack);
281+
expect(data.ri.c).to.equal(sampleBidderRequest.refererInfo.canonicalUrl);
282+
});
283+
263284
it('if prebid is in an iframe, will use the frame url as domain, if the topmost is not avialable', () => {
264285
const { data } = spec.buildRequests([sampleBidRequestBase], {
265286
...sampleBidderRequest,
@@ -286,7 +307,7 @@ describe('AmxBidAdapter', () => {
286307
expect(data.re).to.equal('http://search-traffic-source.com');
287308
});
288309

289-
it('handles referer data and GDPR, USP Consent, COPPA', () => {
310+
it('handles GDPR, USP Consent, COPPA, and GPP', () => {
290311
const { data } = spec.buildRequests(
291312
[sampleBidRequestBase],
292313
sampleBidderRequest
@@ -295,6 +316,7 @@ describe('AmxBidAdapter', () => {
295316
expect(data.gs).to.equal(sampleBidderRequest.gdprConsent.gdprApplies);
296317
expect(data.gc).to.equal(sampleBidderRequest.gdprConsent.consentString);
297318
expect(data.usp).to.equal(sampleBidderRequest.uspConsent);
319+
expect(data.gpp).to.equal(sampleBidderRequest.gppConsent);
298320
expect(data.cpp).to.equal(0);
299321
});
300322

@@ -316,6 +338,70 @@ describe('AmxBidAdapter', () => {
316338
expect(data.bwc).to.equal(bidderWinsCount);
317339
expect(data.trc).to.equal(0);
318340
});
341+
342+
it('will attach sync configuration', () => {
343+
const request = () => spec.buildRequests(
344+
[sampleBidRequestBase],
345+
sampleBidderRequest
346+
);
347+
348+
const setConfig = (filterSettings) =>
349+
config.setConfig({
350+
userSync: {
351+
syncsPerBidder: 2,
352+
syncDelay: 2300,
353+
syncEnabled: true,
354+
filterSettings,
355+
}
356+
});
357+
358+
const test = (filterSettings) => {
359+
setConfig(filterSettings);
360+
return request().data.sync;
361+
}
362+
363+
const base = { d: 2300, l: 2, e: true };
364+
365+
const tests = [[{
366+
image: {
367+
bidders: '*',
368+
filter: 'include'
369+
},
370+
iframe: {
371+
bidders: '*',
372+
filter: 'include'
373+
}
374+
}, { ...base, t: 3 }], [{
375+
image: {
376+
bidders: ['amx'],
377+
},
378+
iframe: {
379+
bidders: '*',
380+
filter: 'include'
381+
}
382+
}, { ...base, t: 3 }], [{
383+
image: {
384+
bidders: ['other'],
385+
},
386+
iframe: {
387+
bidders: '*'
388+
}
389+
}, { ...base, t: 2 }], [{
390+
image: {
391+
bidders: ['amx']
392+
},
393+
iframe: {
394+
bidders: ['amx'],
395+
filter: 'exclude'
396+
}
397+
}, { ...base, t: 1 }]]
398+
399+
for (let i = 0, l = tests.length; i < l; i++) {
400+
const [result, expected] = tests[i];
401+
expect(test(result), `input: ${JSON.stringify(result)}`).to.deep.equal(expected);
402+
}
403+
});
404+
319405
it('will forward first-party data', () => {
320406
const { data } = spec.buildRequests(
321407
[sampleBidRequestBase],
@@ -509,7 +595,14 @@ describe('AmxBidAdapter', () => {
509595
before(() => {
510596
_Image = window.Image;
511597
window.Image = class FakeImage {
598+
_src = '';
599+
600+
get src() {
601+
return this._src;
602+
}
603+
512604
set src(value) {
605+
this._src = value;
513606
firedPixels.push(value);
514607
}
515608
};

0 commit comments

Comments
 (0)