Skip to content
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
44 changes: 44 additions & 0 deletions libraries/equativUtils/equativUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { VIDEO } from '../../src/mediaTypes.js';
import { deepAccess, isFn } from '../../src/utils.js';
import { tryAppendQueryString } from '../urlUtils/urlUtils.js';

const DEFAULT_FLOOR = 0.0;

Expand Down Expand Up @@ -152,3 +153,46 @@ export function prepareSplitImps(imps, bid, currency, impIdMap, adapter) {

return splitImps;
}

export const COOKIE_SYNC_ORIGIN = 'https://apps.smartadserver.com';
export const COOKIE_SYNC_URL = `${COOKIE_SYNC_ORIGIN}/diff/templates/asset/csync.html`;
export const PID_STORAGE_NAME = 'eqt_pid';

/**
* Handles cookie sync logic
*
* @param syncOptions
* @param serverResponses
* @param gdprConsent
* @param networkId
* @param storage
* @returns {{type: string, url: string}[]}
*/
export function handleCookieSync(syncOptions, serverResponses, gdprConsent, networkId, storage) {
if (syncOptions.iframeEnabled) {
window.addEventListener('message', function handler(event) {
if (event.origin === COOKIE_SYNC_ORIGIN && event.data.action === 'getConsent') {
if (event.source && event.source.postMessage) {
event.source.postMessage({
action: 'consentResponse',
id: event.data.id,
consents: gdprConsent.vendorData.vendor.consents
}, event.origin);
}

if (event.data.pid) {
storage.setDataInLocalStorage(PID_STORAGE_NAME, event.data.pid);
}

this.removeEventListener('message', handler);
}
});

let url = tryAppendQueryString(COOKIE_SYNC_URL + '?', 'nwid', networkId);
url = tryAppendQueryString(url, 'gdpr', (gdprConsent?.gdprApplies ? '1' : '0'));

return [{ type: 'iframe', url }];
}

return [];
}
46 changes: 9 additions & 37 deletions modules/equativBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
import { prepareSplitImps } from '../libraries/equativUtils/equativUtils.js';
import { tryAppendQueryString } from '../libraries/urlUtils/urlUtils.js';
import { handleCookieSync, PID_STORAGE_NAME, prepareSplitImps } from '../libraries/equativUtils/equativUtils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { config } from '../src/config.js';
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
Expand All @@ -14,16 +13,13 @@ import { deepAccess, deepSetValue, logError, logWarn, mergeDeep } from '../src/u
*/

const BIDDER_CODE = 'equativ';
const COOKIE_SYNC_ORIGIN = 'https://apps.smartadserver.com';
const COOKIE_SYNC_URL = `${COOKIE_SYNC_ORIGIN}/diff/templates/asset/csync.html`;
const DEFAULT_TTL = 300;
const LOG_PREFIX = 'Equativ:';
const OUTSTREAM_RENDERER_URL = 'https://apps.sascdn.com/diff/video-outstream/equativ-video-outstream.js';
const PID_STORAGE_NAME = 'eqt_pid';

let feedbackArray = [];
let impIdMap = {};
let nwid = 0;
let networkId = 0;
let tokens = {};

/**
Expand Down Expand Up @@ -96,7 +92,7 @@ export const spec = {
const requests = [];

bidRequests.forEach(bid => {
const data = converter.toORTB({bidRequests: [bid], bidderRequest});
const data = converter.toORTB({ bidRequests: [bid], bidderRequest });
requests.push({
data,
method: 'POST',
Expand Down Expand Up @@ -154,36 +150,12 @@ export const spec = {

/**
* @param syncOptions
* @param serverResponses
* @param gdprConsent
* @returns {{type: string, url: string}[]}
*/
getUserSyncs: (syncOptions, serverResponses, gdprConsent) => {
if (syncOptions.iframeEnabled) {
window.addEventListener('message', function handler(event) {
if (event.origin === COOKIE_SYNC_ORIGIN && event.data.action === 'getConsent') {
if (event.source && event.source.postMessage) {
event.source.postMessage({
action: 'consentResponse',
id: event.data.id,
consents: gdprConsent.vendorData.vendor.consents
}, event.origin);
}

if (event.data.pid) {
storage.setDataInLocalStorage(PID_STORAGE_NAME, event.data.pid);
}

this.removeEventListener('message', handler);
}
});

let url = tryAppendQueryString(COOKIE_SYNC_URL + '?', 'nwid', nwid);
url = tryAppendQueryString(url, 'gdpr', (gdprConsent?.gdprApplies ? '1' : '0'));

return [{ type: 'iframe', url }];
}

return [];
}
getUserSyncs: (syncOptions, serverResponses, gdprConsent) =>
handleCookieSync(syncOptions, serverResponses, gdprConsent, networkId, storage)
};

export const converter = ortbConverter({
Expand Down Expand Up @@ -247,8 +219,8 @@ export const converter = ortbConverter({
let req = buildRequest(splitImps, bidderRequest, context);

let env = ['ortb2.site.publisher', 'ortb2.app.publisher', 'ortb2.dooh.publisher'].find(propPath => deepAccess(bid, propPath)) || 'ortb2.site.publisher';
nwid = deepAccess(bid, env + '.id') || bid.params.networkId;
deepSetValue(req, env.replace('ortb2.', '') + '.id', nwid);
networkId = deepAccess(bid, env + '.id') || bid.params.networkId;
deepSetValue(req, env.replace('ortb2.', '') + '.id', networkId);

[
{ path: 'mediaTypes.video', props: ['mimes', 'placement'] },
Expand Down
31 changes: 22 additions & 9 deletions modules/sharethroughBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js';
import { config } from '../src/config.js';
import { ortbConverter } from '../libraries/ortbConverter/converter.js';
import { prepareSplitImps } from '../libraries/equativUtils/equativUtils.js';
import { handleCookieSync, PID_STORAGE_NAME, prepareSplitImps } from '../libraries/equativUtils/equativUtils.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { deepAccess, generateUUID, inIframe, isPlainObject, logWarn, mergeDeep } from '../src/utils.js';
import { getStorageManager } from '../src/storageManager.js';

const VERSION = '4.3.0';
const BIDDER_CODE = 'sharethrough';
Expand All @@ -14,8 +15,11 @@ const STR_ENDPOINT = `https://btlr.sharethrough.com/universal/v1?supply_id=${SUP
const IDENTIFIER_PREFIX = 'Sharethrough:';

const impIdMap = {};
let eqtvNetworkId = 0;
let isEqtvTest = null;

const storage = getStorageManager({ bidderCode: BIDDER_CODE });

/**
* Gets value of the local variable impIdMap
* @returns {*} Value of impIdMap
Expand Down Expand Up @@ -94,12 +98,21 @@ export const sharethroughAdapterSpec = {
test: 0,
};

req.user = nullish(firstPartyData.user, {});
if (!req.user.ext) req.user.ext = {};
req.user.ext.eids = bidRequests[0].userIdAsEids || [];

if (bidRequests[0].params.equativNetworkId) {
isEqtvTest = true;
eqtvNetworkId = bidRequests[0].params.equativNetworkId;
req.site.publisher = {
id: bidRequests[0].params.equativNetworkId,
...req.site.publisher
};
const pid = storage.getDataFromLocalStorage(PID_STORAGE_NAME);
if (pid) {
req.user.buyeruid = pid;
}
}

if (bidderRequest.ortb2?.device?.ext?.cdep) {
Expand All @@ -111,10 +124,6 @@ export const sharethroughAdapterSpec = {
mergeDeep(req.device, bidderRequest.ortb2.device);
}

req.user = nullish(firstPartyData.user, {});
if (!req.user.ext) req.user.ext = {};
req.user.ext.eids = bidRequests[0].userIdAsEids || [];

if (bidderRequest.gdprConsent) {
const gdprApplies = bidderRequest.gdprConsent.gdprApplies === true;
req.regs.ext.gdpr = gdprApplies ? 1 : 0;
Expand Down Expand Up @@ -327,11 +336,15 @@ export const sharethroughAdapterSpec = {
}
},

getUserSyncs: (syncOptions, serverResponses) => {
const shouldCookieSync =
syncOptions.pixelEnabled && deepAccess(serverResponses, '0.body.cookieSyncUrls') !== undefined;
getUserSyncs: (syncOptions, serverResponses, gdprConsent) => {
if (isEqtvTest) {
return handleCookieSync(syncOptions, serverResponses, gdprConsent, eqtvNetworkId, storage)
} else {
const shouldCookieSync =
syncOptions.pixelEnabled && deepAccess(serverResponses, '0.body.cookieSyncUrls') !== undefined;

return shouldCookieSync ? serverResponses[0].body.cookieSyncUrls.map((url) => ({ type: 'image', url: url })) : [];
return shouldCookieSync ? serverResponses[0].body.cookieSyncUrls.map((url) => ({ type: 'image', url: url })) : [];
}
},

// Empty implementation for prebid core to be able to find it
Expand Down
143 changes: 143 additions & 0 deletions test/spec/libraries/equativUtils/equativUtils_spec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as equativUtils from "../../../../libraries/equativUtils/equativUtils";
import { storage } from "../../../../modules/equativBidAdapter";

describe('equativUtils', () => {
describe('prepareSplitImps', () => {
Expand Down Expand Up @@ -40,4 +41,146 @@ describe('equativUtils', () => {
expect(result.banner.topframe).to.equal(1);
})
})

describe('handleCookieSync', () => {
let setDataInLocalStorageStub;
let addEventListenerStub;
let messageHandler;

const SAMPLE_RESPONSE = {
body: {
id: '12h712u7-k22g-8124-ab7a-h268s22dy271',
seatbid: [
{
bid: [
{
id: '1bh7jku7-ko2g-8654-ab72-h268shvwy271',
impid: 'r12gwgf231',
price: 0.6565,
adm: '<h1>AD</h1>',
adomain: ['abc.com'],
cid: '1242512',
crid: '535231',
w: 300,
h: 600,
mtype: 1,
cat: ['IAB19', 'IAB19-1'],
cattax: 1,
},
],
seat: '4212',
},
],
cur: 'USD',
statuscode: 0,
},
};

beforeEach(() => {
setDataInLocalStorageStub = sinon.stub(storage, 'setDataInLocalStorage');
addEventListenerStub = sinon.stub(window, 'addEventListener').callsFake((type, handler) => {
if (type === 'message') {
messageHandler = handler;
}
return addEventListenerStub.wrappedMethod.call(this, type, handler);
});
});
afterEach(() => {
setDataInLocalStorageStub.restore();
addEventListenerStub.restore();
});

it('should return empty array if iframe sync not enabled', () => {
const syncs = equativUtils.handleCookieSync({}, SAMPLE_RESPONSE, {}, 73, storage);
expect(syncs).to.deep.equal([]);
});

it('should retrieve and save user pid', (done) => {
equativUtils.handleCookieSync(
{ iframeEnabled: true },
SAMPLE_RESPONSE,
{ gdprApplies: true, vendorData: { vendor: { consents: {} } } },
73,
storage
);

messageHandler.call(window, {
origin: 'https://apps.smartadserver.com',
data: { action: 'getConsent', pid: '7767825890726' },
source: { postMessage: sinon.stub() }
});

expect(setDataInLocalStorageStub.calledOnce).to.be.true;
expect(setDataInLocalStorageStub.calledWith('eqt_pid', '7767825890726')).to.be.true;
done();
});

it('should not save user pid coming from incorrect origin', (done) => {
equativUtils.handleCookieSync(
{ iframeEnabled: true },
SAMPLE_RESPONSE,
{ gdprApplies: true, vendorData: { vendor: { consents: {} } } },
73,
storage
);

messageHandler.call(window, {
origin: 'https://another-origin.com',
data: { action: 'getConsent', pid: '7767825890726' },
source: { postMessage: sinon.stub() }
});

expect(setDataInLocalStorageStub.notCalled).to.be.true;
done();
});

it('should not save empty pid', (done) => {
equativUtils.handleCookieSync(
{ iframeEnabled: true },
SAMPLE_RESPONSE,
{ gdprApplies: true, vendorData: { vendor: { consents: {} } } },
73,
storage
);

messageHandler.call(window, {
origin: 'https://apps.smartadserver.com',
data: { action: 'getConsent', pid: '' },
source: { postMessage: sinon.stub() }
});

expect(setDataInLocalStorageStub.notCalled).to.be.true;
done();
});

it('should return array including iframe cookie sync object (gdprApplies=true)', () => {
const syncs = equativUtils.handleCookieSync(
{ iframeEnabled: true },
SAMPLE_RESPONSE,
{ gdprApplies: true },
73,
storage
);
expect(syncs).to.have.lengthOf(1);
expect(syncs[0]).to.deep.equal({
type: 'iframe',
url: 'https://apps.smartadserver.com/diff/templates/asset/csync.html?nwid=73&gdpr=1&'
});
});

it('should return array including iframe cookie sync object (gdprApplies=false)', () => {
const syncs = equativUtils.handleCookieSync(
{ iframeEnabled: true },
SAMPLE_RESPONSE,
{ gdprApplies: false },
73,
storage
);
expect(syncs).to.have.lengthOf(1);
expect(syncs[0]).to.deep.equal({
type: 'iframe',
url: 'https://apps.smartadserver.com/diff/templates/asset/csync.html?nwid=73&gdpr=0&'
});
});
});
})
Loading
Loading