forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
AdvRed Analytics Adapter : initial release (prebid#11703)
* Initial version of AdvRed analytics adapter * Initial version of AdvRed analytics adapter
- Loading branch information
1 parent
10c0336
commit 664712c
Showing
3 changed files
with
342 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
import {generateUUID, logInfo} from '../src/utils.js' | ||
import {ajaxBuilder} from '../src/ajax.js' | ||
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js' | ||
import adapterManager from '../src/adapterManager.js' | ||
import {EVENTS} from '../src/constants.js' | ||
import {getRefererInfo} from '../src/refererDetection.js'; | ||
|
||
/** | ||
* advRedAnalyticsAdapter.js - analytics adapter for AdvRed | ||
*/ | ||
const DEFAULT_EVENT_URL = 'https://api.adv.red/api/event' | ||
|
||
let ajax = ajaxBuilder(10000) | ||
let pwId | ||
let initOptions | ||
let flushInterval | ||
let queue = [] | ||
|
||
let advRedAnalytics = Object.assign(adapter({url: DEFAULT_EVENT_URL, analyticsType: 'endpoint'}), { | ||
track({eventType, args}) { | ||
handleEvent(eventType, args) | ||
} | ||
}) | ||
|
||
function sendEvents() { | ||
if (queue.length > 0) { | ||
const message = { | ||
pwId: pwId, | ||
publisherId: initOptions.publisherId, | ||
events: queue, | ||
pageUrl: getRefererInfo().page | ||
} | ||
queue = [] | ||
|
||
const url = initOptions.url ? initOptions.url : DEFAULT_EVENT_URL | ||
ajax( | ||
url, | ||
() => logInfo('AdvRed Analytics sent ' + queue.length + ' events'), | ||
JSON.stringify(message), | ||
{ | ||
method: 'POST', | ||
contentType: 'application/json', | ||
withCredentials: true | ||
} | ||
) | ||
} | ||
} | ||
|
||
function convertAdUnit(adUnit) { | ||
if (!adUnit) return adUnit | ||
|
||
const shortAdUnit = {} | ||
shortAdUnit.code = adUnit.code | ||
shortAdUnit.sizes = adUnit.sizes | ||
return shortAdUnit | ||
} | ||
|
||
function convertBid(bid) { | ||
if (!bid) return bid | ||
|
||
const shortBid = {} | ||
shortBid.adUnitCode = bid.adUnitCode | ||
shortBid.bidder = bid.bidder | ||
shortBid.cpm = bid.cpm | ||
shortBid.currency = bid.currency | ||
shortBid.mediaTypes = bid.mediaTypes | ||
shortBid.sizes = bid.sizes | ||
shortBid.serverResponseTimeMs = bid.serverResponseTimeMs | ||
return shortBid | ||
} | ||
|
||
function convertAuctionInit(origEvent) { | ||
let shortEvent = {} | ||
shortEvent.auctionId = origEvent.auctionId | ||
shortEvent.timeout = origEvent.timeout | ||
shortEvent.adUnits = origEvent.adUnits && origEvent.adUnits.map(convertAdUnit) | ||
return shortEvent | ||
} | ||
|
||
function convertBidRequested(origEvent) { | ||
let shortEvent = {} | ||
shortEvent.bidderCode = origEvent.bidderCode | ||
shortEvent.bids = origEvent.bids && origEvent.bids.map(convertBid) | ||
shortEvent.timeout = origEvent.timeout | ||
return shortEvent | ||
} | ||
|
||
function convertBidTimeout(origEvent) { | ||
let shortEvent = {} | ||
shortEvent.bids = origEvent && origEvent.map ? origEvent.map(convertBid) : origEvent | ||
return shortEvent | ||
} | ||
|
||
function convertBidderError(origEvent) { | ||
let shortEvent = {} | ||
shortEvent.bids = origEvent.bidderRequest && origEvent.bidderRequest.bids && origEvent.bidderRequest.bids.map(convertBid) | ||
return shortEvent | ||
} | ||
|
||
function convertAuctionEnd(origEvent) { | ||
let shortEvent = {} | ||
shortEvent.adUnitCodes = origEvent.adUnitCodes | ||
shortEvent.bidsReceived = origEvent.bidsReceived && origEvent.bidsReceived.map(convertBid) | ||
shortEvent.noBids = origEvent.noBids && origEvent.noBids.map(convertBid) | ||
return shortEvent | ||
} | ||
|
||
function convertBidWon(origEvent) { | ||
let shortEvent = {} | ||
shortEvent.adUnitCode = origEvent.adUnitCode | ||
shortEvent.bidderCode = origEvent.bidderCode | ||
shortEvent.mediaType = origEvent.mediaType | ||
shortEvent.netRevenue = origEvent.netRevenue | ||
shortEvent.cpm = origEvent.cpm | ||
shortEvent.size = origEvent.size | ||
shortEvent.currency = origEvent.currency | ||
return shortEvent | ||
} | ||
|
||
function handleEvent(eventType, origEvent) { | ||
try { | ||
origEvent = origEvent ? JSON.parse(JSON.stringify(origEvent)) : {} | ||
} catch (e) { | ||
} | ||
|
||
let shortEvent | ||
switch (eventType) { | ||
case EVENTS.AUCTION_INIT: { | ||
shortEvent = convertAuctionInit(origEvent) | ||
break | ||
} | ||
case EVENTS.BID_REQUESTED: { | ||
shortEvent = convertBidRequested(origEvent) | ||
break | ||
} | ||
case EVENTS.BID_TIMEOUT: { | ||
shortEvent = convertBidTimeout(origEvent) | ||
break | ||
} | ||
case EVENTS.BIDDER_ERROR: { | ||
shortEvent = convertBidderError(origEvent) | ||
break | ||
} | ||
case EVENTS.AUCTION_END: { | ||
shortEvent = convertAuctionEnd(origEvent) | ||
break | ||
} | ||
case EVENTS.BID_WON: { | ||
shortEvent = convertBidWon(origEvent) | ||
break | ||
} | ||
default: | ||
return | ||
} | ||
|
||
shortEvent.eventType = eventType | ||
shortEvent.auctionId = origEvent.auctionId | ||
shortEvent.timestamp = origEvent.timestamp || Date.now() | ||
|
||
sendEvent(shortEvent) | ||
} | ||
|
||
function sendEvent(event) { | ||
queue.push(event) | ||
|
||
if (event.eventType === EVENTS.AUCTION_END) { | ||
sendEvents() | ||
} | ||
} | ||
|
||
advRedAnalytics.originEnableAnalytics = advRedAnalytics.enableAnalytics | ||
advRedAnalytics.enableAnalytics = function (config) { | ||
initOptions = config.options || {} | ||
pwId = generateUUID() | ||
flushInterval = setInterval(sendEvents, 1000) | ||
|
||
advRedAnalytics.originEnableAnalytics(config) | ||
} | ||
|
||
advRedAnalytics.originDisableAnalytics = advRedAnalytics.disableAnalytics | ||
advRedAnalytics.disableAnalytics = function () { | ||
clearInterval(flushInterval) | ||
sendEvents() | ||
advRedAnalytics.originDisableAnalytics() | ||
} | ||
|
||
adapterManager.registerAnalyticsAdapter({ | ||
adapter: advRedAnalytics, | ||
code: 'advRed' | ||
}) | ||
|
||
advRedAnalytics.getOptions = function () { | ||
return initOptions | ||
} | ||
|
||
advRedAnalytics.sendEvents = sendEvents | ||
|
||
export default advRedAnalytics |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Overview | ||
``` | ||
Module Name: AdvRed Analytics Adapter | ||
Module Type: Analytics Adapter | ||
Maintainer: support@adv.red | ||
``` | ||
|
||
### Usage | ||
|
||
The AdvRed analytics adapter can be used by all clients after approval. For more information, | ||
please visit <https://ams.adv.red/> | ||
|
||
### Analytics Options | ||
| Param enableAnalytics | Scope | Type | Description | Example | | ||
|-----------------------|----------|--------|------------------------------------------------------|----------------------------------------| | ||
| provider | Required | String | The name of this Adapter. | `'advRed'` | | ||
| params | Required | Object | Details of module params. | | | ||
| params.publisherId | Required | String | This is the Publisher ID value obtained from AdvRed. | `'123456'` | | ||
| params.url | Optional | String | Custom URL of the endpoint to collect the events | `'https://pub1.api.adv.red/api/event'` | | ||
|
||
### Example Configuration | ||
|
||
```javascript | ||
pbjs.enableAnalytics({ | ||
provider: 'advRed', | ||
options: { | ||
publisherId: '123456' // change to the Publisher ID you received from AdvRed | ||
} | ||
}); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import advRedAnalytics from 'modules/advRedAnalyticsAdapter.js'; | ||
import {expect} from 'chai'; | ||
import {server} from 'test/mocks/xhr.js'; | ||
import {expectEvents} from '../../helpers/analytics.js'; | ||
import { EVENTS } from 'src/constants.js'; | ||
import sinon from 'sinon'; | ||
|
||
let events = require('src/events'); | ||
|
||
describe('AdvRed Analytics Adapter', function () { | ||
let bidWonEvent = { | ||
'bidderCode': 'appnexus', | ||
'width': 300, | ||
'height': 250, | ||
'adId': '1ebb82ec35375e', | ||
'mediaType': 'banner', | ||
'cpm': 0.5, | ||
'requestId': '1582271863760569973', | ||
'creative_id': '96846035', | ||
'creativeId': '96846035', | ||
'ttl': 60, | ||
'currency': 'USD', | ||
'netRevenue': true, | ||
'auctionId': '9c7b70b9-b6ab-4439-9e71-b7b382797c18', | ||
'responseTimestamp': 1537521629657, | ||
'requestTimestamp': 1537521629331, | ||
'bidder': 'appnexus', | ||
'adUnitCode': 'div-gpt-ad-1460505748561-0', | ||
'timeToRespond': 326, | ||
'size': '300x250', | ||
'status': 'rendered', | ||
'eventType': 'bidWon', | ||
'ad': 'some ad', | ||
'adUrl': 'ad url' | ||
}; | ||
|
||
describe('AdvRed Analytic tests', function () { | ||
beforeEach(function () { | ||
sinon.stub(events, 'getEvents').returns([]); | ||
}); | ||
|
||
afterEach(function () { | ||
advRedAnalytics.disableAnalytics(); | ||
events.getEvents.restore(); | ||
}); | ||
|
||
it('support custom endpoint', function () { | ||
let custom_endpoint = 'custom url'; | ||
advRedAnalytics.enableAnalytics({ | ||
provider: 'advRed', | ||
options: { | ||
url: custom_endpoint, | ||
publisherId: '1234567890' | ||
} | ||
}); | ||
|
||
expect(advRedAnalytics.getOptions().url).to.equal(custom_endpoint); | ||
}); | ||
|
||
it('bid won event', function() { | ||
let publisherId = '1234567890'; | ||
advRedAnalytics.enableAnalytics({ | ||
provider: 'advRed', | ||
options: { | ||
publisherId: publisherId | ||
} | ||
}); | ||
|
||
events.emit(EVENTS.BID_WON, bidWonEvent); | ||
advRedAnalytics.sendEvents(); | ||
|
||
expect(server.requests.length).to.equal(1); | ||
expect(server.requests[0].url).to.equal('https://api.adv.red/api/event'); | ||
|
||
const message = JSON.parse(server.requests[0].requestBody); | ||
expect(message.pwId).to.exist; | ||
expect(message.publisherId).to.equal(publisherId); | ||
expect(message.events.length).to.equal(1); | ||
expect(message.events[0].eventType).to.equal('bidWon'); | ||
expect(message.events[0].ad).to.be.undefined; | ||
expect(message.events[0].adUrl).to.be.undefined; | ||
}); | ||
|
||
it('track event', function () { | ||
sinon.spy(advRedAnalytics, 'track'); | ||
|
||
advRedAnalytics.enableAnalytics({ | ||
provider: 'advRed', | ||
options: { | ||
publisherId: '1234567890' | ||
} | ||
}); | ||
|
||
expectEvents().to.beTrackedBy(advRedAnalytics.track); | ||
}); | ||
}); | ||
|
||
describe('pageUrl detection', function () { | ||
afterEach(function () { | ||
advRedAnalytics.disableAnalytics() | ||
}); | ||
it('check pageUrl property', function () { | ||
advRedAnalytics.enableAnalytics({ | ||
provider: 'advRed', | ||
options: { | ||
publisherId: '1234567890' | ||
} | ||
}); | ||
|
||
const message = JSON.parse(server.requests[0].requestBody); | ||
expect(message.pageUrl).to.equal(window.top.location.href); | ||
}); | ||
}); | ||
}); |