Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NoBid Analytics Adapter: initial release #10343

Merged
merged 38 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
0eba11e
Enable supplyChain support
redaguermas Mar 4, 2020
c0fb8ee
Added support for COPPA
redaguermas Mar 5, 2020
36fab76
Merge branch 'master' of https://github.com/prebid/Prebid.js
redaguermas Mar 13, 2020
51525d7
Merge branch 'master' of https://github.com/prebid/Prebid.js
redaguermas Apr 13, 2020
c473780
Merge remote-tracking branch 'upstream/master'
Jun 1, 2020
33757b8
Merge branch 'master' of https://github.com/prebid/Prebid.js
Jun 4, 2020
9e1758b
Merge branch 'master' of https://github.com/prebid/Prebid.js
Jun 19, 2020
1d7db5d
Merge branch 'master' of https://github.com/prebid/Prebid.js
Aug 18, 2020
8fca715
Merge branch 'master' of https://github.com/prebid/Prebid.js
Aug 26, 2020
c11a5b3
rebuilt
Sep 27, 2020
c44bd3f
Merge branch 'master' of https://github.com/prebid/Prebid.js
Sep 27, 2020
9c8440c
Added support for Extended User IDs.
Sep 28, 2020
ec5cde7
Merge branch 'master' of https://github.com/prebid/Prebid.js
May 28, 2021
ff10bbe
Added support for the "meta" attribute in bid response.
May 28, 2021
4a4c253
Merge branch 'master' of https://github.com/prebid/Prebid.js
Jul 13, 2021
01a2d94
Merge branch 'master' of https://github.com/prebid/Prebid.js
Sep 27, 2021
61583a2
Merge branch 'master' of https://github.com/prebid/Prebid.js
Mar 7, 2023
00142cc
Merge branch 'master' of https://github.com/prebid/Prebid.js
Mar 31, 2023
d6160fa
Merge branch 'master' of https://github.com/prebid/Prebid.js
Jul 4, 2023
388d3e0
Delete nobidBidAdapter.js.orig
redaguermas Jul 28, 2023
1c3f853
Delete a
redaguermas Jul 28, 2023
38dc58a
Delete .jsdtscope
redaguermas Jul 28, 2023
2818cbe
Delete org.eclipse.wst.jsdt.ui.superType.container
redaguermas Jul 28, 2023
ad8662d
Delete org.eclipse.wst.jsdt.ui.superType.name
redaguermas Jul 28, 2023
8ddb9a9
Delete .project
redaguermas Jul 28, 2023
a164194
Merge branch 'master' of https://github.com/redaguermas/Prebid.js
Aug 7, 2023
0a5fbc6
Merge branch 'master' of https://github.com/prebid/Prebid.js
Aug 10, 2023
53de134
New NoBid Analytics Adapter.
Aug 10, 2023
c2a5fc4
Merge branch 'master' of https://github.com/prebid/Prebid.js
Aug 10, 2023
14a13ed
Merge branch 'master' into NoBid-Analytics-1.0.0
Aug 10, 2023
579edf6
Added NoBid Analytics Adapter unit tests.
Aug 21, 2023
a144f4a
Merge branch 'master' of https://github.com/prebid/Prebid.js
Aug 21, 2023
131fab1
Merge branch 'master' into NoBid-Analytics-1.0.0
Aug 21, 2023
19caf0e
Merge branch 'master' of https://github.com/prebid/Prebid.js
Aug 21, 2023
2ece9e0
Merge branch 'master' into NoBid-Analytics-1.0.0
Aug 21, 2023
4bb3e02
Added NoBid Analytics Module documentation.
Aug 24, 2023
e92612e
Merge branch 'master' of https://github.com/prebid/Prebid.js
Aug 24, 2023
a345ef3
Merge branch 'master' into NoBid-Analytics-1.0.0
Aug 24, 2023
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
199 changes: 199 additions & 0 deletions modules/nobidAnalyticsAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import {deepClone, logError, getParameterByName} from '../src/utils.js';
import {ajax} from '../src/ajax.js';
import {getStorageManager} from '../src/storageManager.js';
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
import CONSTANTS from '../src/constants.json';
import adapterManager from '../src/adapterManager.js';
import {MODULE_TYPE_ANALYTICS} from '../src/activities/modules.js';

const VERSION = '1.0.4';
const MODULE_NAME = 'nobidAnalyticsAdapter';
const ANALYTICS_DATA_NAME = 'analytics.nobid.io';
const RETENTION_SECONDS = 7 * 24 * 3600;
const TEST_ALLOCATION_PERCENTAGE = 5; // dont block 5% of the time;
window.nobidAnalyticsVersion = VERSION;
const analyticsType = 'endpoint';
const url = 'localhost:8383/event';
const GVLID = 816;
const storage = getStorageManager({gvlid: GVLID, moduleName: MODULE_NAME, moduleType: MODULE_TYPE_ANALYTICS});
const {
EVENTS: {
AUCTION_INIT,
BID_REQUESTED,
BID_TIMEOUT,
BID_RESPONSE,
BID_WON,
AUCTION_END,
AD_RENDER_SUCCEEDED
}
} = CONSTANTS;
function log (msg) {
// eslint-disable-next-line no-console
console.log(`%cNoBid Analytics ${VERSION}`, 'padding: 2px 8px 2px 8px; background-color:#f50057; color: white', msg);
}
function isJson (str) {
return str && str.startsWith('{') && str.endsWith('}');
}
function isExpired (data, retentionSeconds) {
retentionSeconds = retentionSeconds || RETENTION_SECONDS;
if (data.ts + retentionSeconds * 1000 < Date.now()) return true;
return false;
}
function sendEvent (event, eventType) {
function resolveEndpoint() {
var ret = 'https://carbon-nv.servenobids.com/admin/status';
var env = (typeof getParameterByName === 'function') && (getParameterByName('nobid-env'));
env = window.location.href.indexOf('nobid-env=dev') > 0 ? 'dev' : env;
if (!env) ret = 'https://carbon-nv.servenobids.com';
else if (env == 'dev') ret = 'https://localhost:8383';
return ret;
}
if (!nobidAnalytics.initOptions || !nobidAnalytics.initOptions.siteId || !event) return;
if (nobidAnalytics.isAnalyticsDisabled()) {
log('NoBid Analytics is Disabled');
return;
}
try {
const endpoint = `${resolveEndpoint()}/event/${eventType}?pubid=${nobidAnalytics.initOptions.siteId}`;
ajax(endpoint,
function (response) {
try {
nobidAnalytics.processServerResponse(response);
} catch (e) {
logError(e);
}
},
JSON.stringify(event),
{
contentType: 'application/json',
method: 'POST'
}
);
} catch (err) {
log(`Sending event error ${err}`);
}
}
function cleanupObjectAttributes (obj, attributes) {
if (!obj) return;
if (Array.isArray(obj)) {
obj.forEach(item => {
Object.keys(item).forEach(attr => { if (!attributes.includes(attr)) delete item[attr] });
});
} else Object.keys(obj).forEach(attr => { if (!attributes.includes(attr)) delete obj[attr] });
}
function sendBidWonEvent (event, eventType) {
const data = deepClone(event);
cleanupObjectAttributes(data, ['bidderCode', 'size', 'statusMessage', 'adId', 'requestId', 'mediaType', 'adUnitCode', 'cpm', 'timeToRespond']);
if (nobidAnalytics.topLocation) data.topLocation = nobidAnalytics.topLocation;
sendEvent(data, eventType);
}
function sendAuctionEndEvent (event, eventType) {
if (event?.bidderRequests?.length > 0 && event?.bidderRequests[0]?.refererInfo?.topmostLocation) {
nobidAnalytics.topLocation = event.bidderRequests[0].refererInfo.topmostLocation;
}
const data = deepClone(event);

cleanupObjectAttributes(data, ['timestamp', 'timeout', 'auctionId', 'bidderRequests', 'bidsReceived']);
if (data) cleanupObjectAttributes(data.bidderRequests, ['bidderCode', 'bidderRequestId', 'bids', 'refererInfo']);
if (data) cleanupObjectAttributes(data.bidsReceived, ['bidderCode', 'width', 'height', 'adUnitCode', 'statusMessage', 'requestId', 'mediaType', 'cpm']);
if (data) cleanupObjectAttributes(data.noBids, ['bidder', 'sizes', 'bidId']);
if (data.bidderRequests) cleanupObjectAttributes(data.bidderRequests.bids, ['mediaTypes', 'adUnitCode', 'sizes', 'bidId']);
if (data.bidderRequests) cleanupObjectAttributes(data.bidderRequests.refererInfo, ['topmostLocation']);
sendEvent(data, eventType);
}
function auctionInit (event) {
if (event?.bidderRequests?.length > 0 && event?.bidderRequests[0]?.refererInfo?.topmostLocation) {
nobidAnalytics.topLocation = event.bidderRequests[0].refererInfo.topmostLocation;
}
}
let nobidAnalytics = Object.assign(adapter({url, analyticsType}), {
track({ eventType, args }) {
switch (eventType) {
case AUCTION_INIT:
auctionInit(args);
break;
case BID_REQUESTED:
break;
case BID_RESPONSE:
break;
case BID_WON:
sendBidWonEvent(args, eventType);
break;
case BID_TIMEOUT:
break;
case AUCTION_END:
sendAuctionEndEvent(args, eventType);
break;
case AD_RENDER_SUCCEEDED:
break;
default:
break;
}
}
});

nobidAnalytics = {
...nobidAnalytics,
originEnableAnalytics: nobidAnalytics.enableAnalytics, // save the base class function
enableAnalytics: function (config) { // override enableAnalytics so we can get access to the config passed in from the page
if (!config.options.siteId) {
logError('NoBid Analytics - siteId parameter is not defined. Analytics won\'t work');
return;
}
this.initOptions = config.options;
this.originEnableAnalytics(config); // call the base class function
},
retentionSeconds: RETENTION_SECONDS,
isExpired (data) {
return isExpired(data, this.retentionSeconds);
},
isAnalyticsDisabled () {
let stored = storage.getDataFromLocalStorage(ANALYTICS_DATA_NAME);
if (!isJson(stored)) return false;
stored = JSON.parse(stored);
if (this.isExpired(stored)) return false;
return stored.disabled;
},
processServerResponse (response) {
if (!isJson(response)) return;
const resp = JSON.parse(response);
storage.setDataInLocalStorage(ANALYTICS_DATA_NAME, JSON.stringify({ ...resp, ts: Date.now() }));
}
}

adapterManager.registerAnalyticsAdapter({
adapter: nobidAnalytics,
code: 'nobidAnalytics',
gvlid: GVLID
});
window.nobidCarbonizer = {
getStoredLocalData: function () {
return storage.getDataFromLocalStorage(ANALYTICS_DATA_NAME);
},
isActive: function () {
let stored = storage.getDataFromLocalStorage(ANALYTICS_DATA_NAME);
if (!isJson(stored)) return false;
stored = JSON.parse(stored);
if (isExpired(stored, nobidAnalytics.retentionSeconds)) return false;
return stored.carbonizer_active || false;
},
carbonizeAdunits: function (adunits, skipTestGroup) {
function carbonizeAdunit (adunit) {
let stored = storage.getDataFromLocalStorage(ANALYTICS_DATA_NAME);
if (!isJson(stored)) return;
stored = JSON.parse(stored);
if (isExpired(stored, nobidAnalytics.retentionSeconds)) return;
const carbonizerBidders = stored.bidders || [];
const allowedBidders = adunit.bids.filter(rec => carbonizerBidders.includes(rec.bidder));
adunit.bids = allowedBidders;
}
if (this.isActive()) {
// 5% of the time do not block;
if (!skipTestGroup && Math.floor(Math.random() * 101) <= TEST_ALLOCATION_PERCENTAGE) return;
adunits.forEach(adunit => {
carbonizeAdunit(adunit);
});
}
}
};
export default nobidAnalytics;
38 changes: 38 additions & 0 deletions modules/nobidAnalyticsAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Overview
Module Name: NoBid Analytics Adapter

Module Type: Analytics Adapter

Maintainer: [nobid.io](https://nobid.io)


# NoBid Analytics Registration

The NoBid Analytics Adapter is free to use during our Beta period, but requires a simple registration with NoBid. Please visit [www.nobid.io](https://www.nobid.io/contact-1/) to sign up and request your NoBid Site ID to get started. If you're already using the NoBid Prebid Adapter, you may use your existing Site ID with the NoBid Analytics Adapter.

The NoBid privacy policy is at [nobid.io/privacy-policy](https://www.nobid.io/privacy-policy/).

## NoBid Analytics Configuration

First, make sure to add the NoBid Analytics submodule to your Prebid.js package with:

```
gulp build --modules=...,nobidAnalyticsAdapter...
```

The following configuration parameters are available:

```javascript
pbjs.enableAnalytics({
provider: 'nobidAnalytics',
options: {
siteId: 123 // change to the Site ID you received from NoBid
}
});
```

{: .table .table-bordered .table-striped }
| Parameter | Scope | Type | Description | Example |
| --- | --- | --- | --- | --- |
| provider | Required | String | The name of this module: `nobidAnalytics` | `nobidAnalytics` |
| options.siteId | Required | Number | This is the NoBid Site ID Number obtained from registering with NoBid. | `1234` |
Loading