diff --git a/modules/equativBidAdapter.js b/modules/equativBidAdapter.js index 2c071fe832a..c7cb304d22b 100644 --- a/modules/equativBidAdapter.js +++ b/modules/equativBidAdapter.js @@ -2,6 +2,7 @@ import { BANNER } from '../src/mediaTypes.js'; import { getBidFloor } from '../libraries/equativUtils/equativUtils.js' import { ortbConverter } from '../libraries/ortbConverter/converter.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; +import { getStorageManager } from '../src/storageManager.js'; import { deepAccess, deepSetValue, mergeDeep } from '../src/utils.js'; /** @@ -9,8 +10,15 @@ import { deepAccess, deepSetValue, mergeDeep } from '../src/utils.js'; * @typedef {import('../src/adapters/bidderFactory.js').ServerRequest} ServerRequest */ +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 PID_COOKIE_NAME = 'eqt_pid'; + +export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); + export const spec = { - code: 'equativ', + code: BIDDER_CODE, gvlid: 45, supportedMediaTypes: [BANNER], @@ -53,24 +61,24 @@ export const spec = { /** * @param syncOptions - * @param serverResponse * @returns {{type: string, url: string}[]} */ - // getUserSyncs: (syncOptions, serverResponse) => { - // if (syncOptions.iframeEnabled && serverResponses[0]?.body.cSyncUrl) { - // return [ - // { - // type: 'iframe', - // url: serverResponses[0].body.cSyncUrl, - // }, - // ]; - // } - // return (syncOptions.pixelEnabled && serverResponse.body?.dspPixels) - // ? serverResponse.body.dspPixels.map((pixel) => ({ - // type: 'image', - // url: pixel, - // })) : []; - // }, + getUserSyncs: (syncOptions) => { + if (syncOptions.iframeEnabled) { + window.addEventListener('message', function handler(event) { + if (event.origin === COOKIE_SYNC_ORIGIN && event.data.pid) { + const exp = new Date(); + exp.setTime(Date.now() + 31536000000); // in a year + storage.setCookie(PID_COOKIE_NAME, event.data.pid, exp.toUTCString()); + this.removeEventListener('message', handler); + } + }); + + return [{ type: 'iframe', url: COOKIE_SYNC_URL }]; + } + + return []; + } }; export const converter = ortbConverter({ @@ -126,6 +134,11 @@ export const converter = ortbConverter({ deepSetValue(req, 'site.publisher.id', bid.params.networkId); } + const pid = storage.getCookie(PID_COOKIE_NAME); + if (pid) { + deepSetValue(req, 'user.buyeruid', pid); + } + return req; }, }); diff --git a/test/spec/modules/equativBidAdapter_spec.js b/test/spec/modules/equativBidAdapter_spec.js index b3009e38710..c52507a000b 100644 --- a/test/spec/modules/equativBidAdapter_spec.js +++ b/test/spec/modules/equativBidAdapter_spec.js @@ -1,6 +1,6 @@ import { BANNER } from 'src/mediaTypes.js'; import { getBidFloor } from 'libraries/equativUtils/equativUtils.js' -import { spec, converter } from 'modules/equativBidAdapter.js'; +import { converter, spec, storage } from 'modules/equativBidAdapter.js'; describe('Equativ bid adapter tests', () => { const DEFAULT_BID_REQUESTS = [ @@ -259,6 +259,56 @@ describe('Equativ bid adapter tests', () => { const request = spec.buildRequests(bidRequests, bidderRequest); expect(request.data.imp[0]).to.not.have.property('dt'); }); + + it('should read and send pid as buyeruid', () => { + const cookieData = { + 'eqt_pid': '7789746781' + }; + const getCookieStub = sinon.stub(storage, 'getCookie'); + getCookieStub.callsFake(cookieName => cookieData[cookieName]); + + const request = spec.buildRequests( + DEFAULT_BID_REQUESTS, + DEFAULT_BIDDER_REQUEST + ); + + expect(request.data.user).to.have.property('buyeruid').that.eq(cookieData['eqt_pid']); + + getCookieStub.restore(); + }); + + it('should not send buyeruid', () => { + const getCookieStub = sinon.stub(storage, 'getCookie'); + getCookieStub.callsFake(() => null); + + const request = spec.buildRequests( + DEFAULT_BID_REQUESTS, + DEFAULT_BIDDER_REQUEST + ); + + expect(request.data).to.not.have.property('user'); + + getCookieStub.restore(); + }); + + it('should pass buyeruid defined in config', () => { + const getCookieStub = sinon.stub(storage, 'getCookie'); + getCookieStub.callsFake(() => undefined); + + const bidRequest = { + ...DEFAULT_BIDDER_REQUEST, + ortb2: { + user: { + buyeruid: 'buyeruid-provided-by-publisher' + } + } + }; + const request = spec.buildRequests([ DEFAULT_BID_REQUESTS[0] ], bidRequest); + + expect(request.data.user.buyeruid).to.deep.eq(bidRequest.ortb2.user.buyeruid); + + getCookieStub.restore(); + }); }); describe('getBidFloor', () => { @@ -327,32 +377,91 @@ describe('Equativ bid adapter tests', () => { }); }); - // describe('getUserSyncs', () => { - // it('should return empty array if no pixel sync not enabled', () => { - // const syncs = spec.getUserSyncs({}, RESPONSE_WITH_DSP_PIXELS); - // expect(syncs).to.deep.equal([]); - // }); - - // it('should return empty array if no pixels available', () => { - // const syncs = spec.getUserSyncs( - // { pixelEnabled: true }, - // SAMPLE_RESPONSE - // ); - // expect(syncs).to.deep.equal([]); - // }); - - // it('should register dsp pixels', () => { - // const syncs = spec.getUserSyncs( - // { pixelEnabled: true }, - // RESPONSE_WITH_DSP_PIXELS - // ); - // expect(syncs).to.have.lengthOf(3); - // expect(syncs[1]).to.deep.equal({ - // type: 'image', - // url: '2nd-pixel', - // }); - // }); - // }); + describe('getUserSyncs', () => { + let setCookieStub; + + beforeEach(() => setCookieStub = sinon.stub(storage, 'setCookie')); + + afterEach(() => setCookieStub.restore()); + + it('should return empty array if iframe sync not enabled', () => { + const syncs = spec.getUserSyncs({}, SAMPLE_RESPONSE); + expect(syncs).to.deep.equal([]); + }); + + it('should retrieve and save user pid', (done) => { + const userSyncs = spec.getUserSyncs( + { iframeEnabled: true }, + SAMPLE_RESPONSE + ); + + window.dispatchEvent(new MessageEvent('message', { + data: { + pid: '7767825890726' + }, + origin: 'https://apps.smartadserver.com' + })); + + const exp = new Date(); + exp.setTime(Date.now() + 31536000000); + + setTimeout(() => { + expect(setCookieStub.calledOnce).to.be.true; + expect(setCookieStub.calledWith('eqt_pid', '7767825890726', exp.toUTCString())).to.be.true; + done(); + }); + }); + + it('should not save user pid coming from not origin', (done) => { + const userSyncs = spec.getUserSyncs( + { iframeEnabled: true }, + SAMPLE_RESPONSE + ); + + window.dispatchEvent(new MessageEvent('message', { + data: { + pid: '7767825890726' + }, + origin: 'https://another-origin.com' + })); + + setTimeout(() => { + expect(setCookieStub.notCalled).to.be.true; + done(); + }); + }); + + it('should not save empty pid', (done) => { + const userSyncs = spec.getUserSyncs( + { iframeEnabled: true }, + SAMPLE_RESPONSE + ); + + window.dispatchEvent(new MessageEvent('message', { + data: { + pid: '' + }, + origin: 'https://apps.smartadserver.com' + })); + + setTimeout(() => { + expect(setCookieStub.notCalled).to.be.true; + done(); + }); + }); + + it('should return array including iframe cookie sync object', () => { + const syncs = spec.getUserSyncs( + { iframeEnabled: true }, + SAMPLE_RESPONSE + ); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0]).to.deep.equal({ + type: 'iframe', + url: 'https://apps.smartadserver.com/diff/templates/asset/csync.html' + }); + }); + }); describe('interpretResponse', () => { it('should return data returned by ORTB converter', () => {