Skip to content

Commit

Permalink
CleanIO RTD Module: support billable event (prebid#8750)
Browse files Browse the repository at this point in the history
* clean.io RTD Module: send billable events

* Added unit test for billable events

* attempt to trigger circleci

* Fixed some analytics test to expect Clean.io billableEvents too.

Co-authored-by: mkikot-sigma <[email protected]>
Co-authored-by: Patrick McCann <[email protected]>
Co-authored-by: eugen-tikhonov <[email protected]>
Co-authored-by: yevhen.tykhonov <[email protected]>
  • Loading branch information
5 people authored and jorgeluisrocha committed May 18, 2023
1 parent 3e5319d commit 3e13c11
Show file tree
Hide file tree
Showing 16 changed files with 91 additions and 18 deletions.
29 changes: 29 additions & 0 deletions modules/cleanioRtdProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import { submodule } from '../src/hook.js';
import { logError, generateUUID, insertElement } from '../src/utils.js';
import * as events from '../src/events.js';
import CONSTANTS from '../src/constants.json';

// ============================ MODULE STATE ===============================

Expand Down Expand Up @@ -147,6 +149,26 @@ function readConfig(config) {
}
}

/**
* The function to be called upon module init
* Defined as a variable to be able to reset it naturally
*/
let startBillableEvents = function() {
// Upon clean.io submodule initialization, every winner bid is considered to be protected
// and therefore, subjected to billing
events.on(CONSTANTS.EVENTS.BID_WON, winnerBidResponse => {
events.emit(CONSTANTS.EVENTS.BILLABLE_EVENT, {
vendor: 'clean.io',
billingId: generateUUID(),
type: 'impression',
// TODO: if absolutely crucial, winnerBidResponse may be used
// to track down auctionId and transactionId
// However, those seem to be of importance for Demand Managers,
// while these billable events are for publishers
});
});
}

// ============================ MODULE REGISTRATION ===============================

/**
Expand All @@ -160,6 +182,13 @@ function beforeInit() {
try {
readConfig(config);
onModuleInit();

// Subscribing once to ensure no duplicate events
// in case module initialization code runs multiple times
// This should have been a part of submodule definition, but well...
// The assumption here is that in production init() will be called exactly once
startBillableEvents();
startBillableEvents = () => {};
return true;
} catch (err) {
if (err instanceof ConfigError) {
Expand Down
23 changes: 23 additions & 0 deletions test/spec/modules/cleanioRtdProvider_spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as utils from '../../../src/utils.js';
import * as hook from '../../../src/hook.js'
import * as events from '../../../src/events.js';
import CONSTANTS from '../../../src/constants.json';

import { __TEST__ } from '../../../modules/cleanioRtdProvider.js';

Expand Down Expand Up @@ -184,5 +186,26 @@ describe('clean.io RTD module', function () {
onBidResponseEvent(fakeBidResponse3, {}, {});
ensurePrependToBidResponse(fakeBidResponse3);
});

it('should send billable event per bid won event', function () {
const { init } = getModule();
expect(init({ params: { cdnUrl: 'https://abc1234567890.cloudfront.net/script.js', protectionMode: 'full' } }, {})).to.equal(true);

const eventCounter = { registerCleanioBillingEvent: function() {} };
sinon.spy(eventCounter, 'registerCleanioBillingEvent');

events.on(CONSTANTS.EVENTS.BILLABLE_EVENT, (evt) => {
if (evt.vendor === 'clean.io') {
eventCounter.registerCleanioBillingEvent()
}
});

events.emit(CONSTANTS.EVENTS.BID_WON, {});
events.emit(CONSTANTS.EVENTS.BID_WON, {});
events.emit(CONSTANTS.EVENTS.BID_WON, {});
events.emit(CONSTANTS.EVENTS.BID_WON, {});

sinon.assert.callCount(eventCounter.registerCleanioBillingEvent, 4);
});
});
});
3 changes: 2 additions & 1 deletion test/spec/modules/concertAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ describe('ConcertAnalyticsAdapter', function() {
sandbox.spy(concertAnalytics, 'track');

fireBidEvents(events);
sandbox.assert.callCount(concertAnalytics.track, 5);
// 5 Concert events + 1 Clean.io event
sandbox.assert.callCount(concertAnalytics.track, 6);
});

it('should report data for BID_RESPONSE, BID_WON events', function() {
Expand Down
4 changes: 2 additions & 2 deletions test/spec/modules/eplanningAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ describe('eplanning analytics adapter', function () {
// Step 10 check that the host to send the ajax request is configurable via options
expect(eplAnalyticsAdapter.context.host).to.equal(initOptions.host);

// Step 11 verify that we received 6 events
sinon.assert.callCount(eplAnalyticsAdapter.track, 6);
// Step 11 verify that we received 7 events (6 E-Planning events + 1 Clean.io event)
sinon.assert.callCount(eplAnalyticsAdapter.track, 7);
});
});
});
3 changes: 2 additions & 1 deletion test/spec/modules/fintezaAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ describe('finteza analytics adapter', function () {
expect(url.search.value).to.equal(String(cpm));
expect(url.search.unit).to.equal('usd');

sinon.assert.callCount(fntzAnalyticsAdapter.track, 1);
// 1 Finteza event + 1 Clean.io event
sinon.assert.callCount(fntzAnalyticsAdapter.track, 2);
});
});

Expand Down
11 changes: 8 additions & 3 deletions test/spec/modules/invisiblyAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,9 @@ describe('Invisibly Analytics Adapter test suite', function () {
events.emit(constants.EVENTS.BID_REQUESTED, MOCK.BID_REQUESTED);
events.emit(constants.EVENTS.BID_RESPONSE, MOCK.BID_RESPONSE);
events.emit(constants.EVENTS.BID_WON, MOCK.BID_WON);
sinon.assert.callCount(invisiblyAdapter.track, 5);

// 5 Invisibly events + 1 Clean.io event
sinon.assert.callCount(invisiblyAdapter.track, 6);
});

it('should not catch events triggered without invisibly account config', function () {
Expand Down Expand Up @@ -380,7 +382,9 @@ describe('Invisibly Analytics Adapter test suite', function () {
expect(invisiblyEvents.event_data.pageViewId).to.exist;
expect(invisiblyEvents.event_data.ver).to.equal(1);
expect(invisiblyEvents.event_type).to.equal('PREBID_bidWon');
sinon.assert.callCount(invisiblyAdapter.track, 1);

// 1 Invisibly event + 1 Clean.io event
sinon.assert.callCount(invisiblyAdapter.track, 2);
});

// spec for bidder done event
Expand Down Expand Up @@ -551,7 +555,8 @@ describe('Invisibly Analytics Adapter test suite', function () {
events.emit(constants.EVENTS.ADD_AD_UNITS, MOCK.ADD_AD_UNITS);
events.emit(constants.EVENTS.AD_RENDER_FAILED, MOCK.AD_RENDER_FAILED);

sinon.assert.callCount(invisiblyAdapter.track, 13);
// 13 Invisibly events + 1 Clean.io event
sinon.assert.callCount(invisiblyAdapter.track, 14);
});
});

Expand Down
3 changes: 2 additions & 1 deletion test/spec/modules/konduitAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ describe(`Konduit Analytics Adapter`, () => {
expect(requestBody.konduitId).to.be.equal(konduitId);
expect(requestBody.prebidVersion).to.be.equal('$prebid.version$');
expect(requestBody.environment).to.be.an('object');
sinon.assert.callCount(konduitAnalyticsAdapter.track, 6);
// 6 Konduit events + 1 Clean.io event
sinon.assert.callCount(konduitAnalyticsAdapter.track, 7);
});
});
3 changes: 2 additions & 1 deletion test/spec/modules/optimonAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ describe('Optimon Analytics Adapter', () => {
events.emit(constants.EVENTS.BID_TIMEOUT, optmn_arguments)
events.emit(constants.EVENTS.BID_WON, optmn_arguments)

expect(optmn_queue.length).to.eql(3);
// 3 Optimon events + 1 Clean.io event
expect(optmn_queue.length).to.eql(4);
});
});
4 changes: 4 additions & 0 deletions test/spec/modules/pianoDmpAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ describe('Piano DMP Analytics Adapter', () => {

// Then
const callQueue = (window.cX || {}).callQueue;
const billableEventIndex = callQueue.findIndex(([, params]) => params.eventType === constants.EVENTS.BILLABLE_EVENT);
if (billableEventIndex > -1) {
callQueue.splice(billableEventIndex, 1);
}

expect(callQueue).to.be.an('array');
expect(callQueue.length).to.equal(testEvents.length);
Expand Down
3 changes: 2 additions & 1 deletion test/spec/modules/prebidmanagerAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ describe('Prebid Manager Analytics Adapter', function () {
events.emit(constants.EVENTS.AUCTION_END, {});
events.emit(constants.EVENTS.BID_TIMEOUT, {});

sinon.assert.callCount(prebidmanagerAnalytics.track, 6);
// 6 Prebid Manager events + 1 Clean.io event
sinon.assert.callCount(prebidmanagerAnalytics.track, 7);
});
});

Expand Down
3 changes: 2 additions & 1 deletion test/spec/modules/pubperfAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ describe('Pubperf Analytics Adapter', function() {
events.emit(constants.EVENTS.AUCTION_END, {});
events.emit(constants.EVENTS.BID_TIMEOUT, {});

sinon.assert.callCount(pubperfAnalytics.track, 6);
// 6 Pubperf events + 1 Clean.io event
sinon.assert.callCount(pubperfAnalytics.track, 7);
});
});
});
3 changes: 2 additions & 1 deletion test/spec/modules/pubstackAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ describe('Pubstack Analytics Adapter', () => {
events.emit(constants.EVENTS.NO_BID, args)

// Then
expect(queue.length).to.eql(6);
// 6 Pubstack events + 1 Clean.io event
expect(queue.length).to.eql(7);
});
});
6 changes: 3 additions & 3 deletions test/spec/modules/pubwiseAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ describe('PubWise Prebid Analytics', function () {
events.emit(constants.EVENTS.AUCTION_END, {});

// eslint-disable-next-line
//console.log(requests);
//console.log(requests);

/* testing for 6 calls, including the 2 we're not currently tracking */
sandbox.assert.callCount(pubwiseAnalytics.track, 7);
sandbox.assert.callCount(pubwiseAnalytics.track, 8);
});

it('should initialize the auction properly', function () {
Expand All @@ -92,7 +92,7 @@ describe('PubWise Prebid Analytics', function () {
let request = requests[0];
let data = JSON.parse(request.requestBody);
// eslint-disable-next-line
// console.log(data.metaData);
// console.log(data.metaData);
expect(data.metaData, 'metaData property').to.exist;
expect(data.metaData.pbjs_version, 'pbjs version').to.equal('$prebid.version$')
expect(data.metaData.session_id, 'session id').not.to.be.empty
Expand Down
2 changes: 1 addition & 1 deletion test/spec/modules/sigmoidAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ describe('sigmoid Prebid Analytic', function () {
events.emit(constants.EVENTS.BID_RESPONSE, {});
events.emit(constants.EVENTS.BID_WON, {});

sinon.assert.callCount(sigmoidAnalytic.track, 7);
sinon.assert.callCount(sigmoidAnalytic.track, 8);
});
});
describe('build utm tag data', function () {
Expand Down
3 changes: 2 additions & 1 deletion test/spec/modules/sovrnAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@ describe('Sovrn Analytics Adapter', function () {
events.emit(constants.EVENTS.BID_RESPONSE, {});
events.emit(constants.EVENTS.BID_WON, {});

sinon.assert.callCount(sovrnAnalyticsAdapter.track, 5);
// 5 SovrnAnalytics events + 1 Clean.io event
sinon.assert.callCount(sovrnAnalyticsAdapter.track, 6);
});

it('should catch no events if no affiliate id', function () {
Expand Down
6 changes: 5 additions & 1 deletion test/spec/modules/yieldoneAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,11 @@ describe('Yieldone Prebid Analytic', function () {
setTimeout(function() {
events.emit(constants.EVENTS.BID_WON, winner);

sinon.assert.callCount(sendStatStub, 2);
sinon.assert.callCount(sendStatStub, 2)
const billableEventIndex = yieldoneAnalytics.eventsStorage[auctionId].events.findIndex(event => event.eventType === constants.EVENTS.BILLABLE_EVENT);
if (billableEventIndex > -1) {
yieldoneAnalytics.eventsStorage[auctionId].events.splice(billableEventIndex, 1);
}
expect(yieldoneAnalytics.eventsStorage[auctionId]).to.deep.equal(wonExpectedResult);

delete yieldoneAnalytics.eventsStorage[auctionId];
Expand Down

0 comments on commit 3e13c11

Please sign in to comment.