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

Rubicon Analytics: General Enhancements #6991

Merged
merged 1 commit into from
Jun 9, 2021
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
41 changes: 30 additions & 11 deletions modules/rubiconAnalyticsAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ function formatSource(src) {
return src.toLowerCase();
}

function sendMessage(auctionId, bidWonId) {
function sendMessage(auctionId, bidWonId, trigger) {
function formatBid(bid) {
return utils.pick(bid, [
'bidder',
Expand Down Expand Up @@ -163,7 +163,12 @@ function sendMessage(auctionId, bidWonId) {
let auctionCache = cache.auctions[auctionId];
let referrer = config.getConfig('pageUrl') || (auctionCache && auctionCache.referrer);
let message = {
eventTimeMillis: Date.now(),
timestamps: {
prebidLoaded: rubiconAdapter.MODULE_INITIALIZED_TIME,
auctionEnded: auctionCache.endTs,
eventTime: Date.now()
},
trigger,
integration: rubiConf.int_type || DEFAULT_INTEGRATION,
version: '$prebid.version$',
referrerUri: referrer,
Expand Down Expand Up @@ -319,6 +324,10 @@ function sendMessage(auctionId, bidWonId) {
);
}

function adUnitIsOnlyInstream(adUnit) {
return adUnit.mediaTypes && Object.keys(adUnit.mediaTypes).length === 1 && utils.deepAccess(adUnit, 'mediaTypes.video.context') === 'instream';
}

function getBidPrice(bid) {
// get the cpm from bidResponse
let cpm;
Expand Down Expand Up @@ -498,9 +507,9 @@ function subscribeToGamSlots() {
clearTimeout(cache.timeouts[auctionId]);
delete cache.timeouts[auctionId];
if (rubiConf.analyticsEventDelay > 0) {
setTimeout(() => sendMessage.call(rubiconAdapter, auctionId), rubiConf.analyticsEventDelay)
setTimeout(() => sendMessage.call(rubiconAdapter, auctionId, undefined, 'delayedGam'), rubiConf.analyticsEventDelay)
} else {
sendMessage.call(rubiconAdapter, auctionId)
sendMessage.call(rubiconAdapter, auctionId, undefined, 'gam')
}
}
});
Expand All @@ -509,6 +518,7 @@ function subscribeToGamSlots() {

let baseAdapter = adapter({analyticsType: 'endpoint'});
let rubiconAdapter = Object.assign({}, baseAdapter, {
MODULE_INITIALIZED_TIME: Date.now(),
referrerHostname: '',
enableAnalytics(config = {}) {
let error = false;
Expand Down Expand Up @@ -594,7 +604,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, {
// mark adUnits we expect bidWon events for
cache.auctions[args.auctionId].bidsWon[bid.adUnitCode] = false;

if (rubiConf.waitForGamSlots) {
if (rubiConf.waitForGamSlots && !adUnitIsOnlyInstream(bid)) {
cache.auctions[args.auctionId].gamHasRendered[bid.adUnitCode] = false;
}

Expand Down Expand Up @@ -750,7 +760,7 @@ let rubiconAdapter = Object.assign({}, baseAdapter, {

// check if this BID_WON missed the boat, if so send by itself
if (auctionCache.sent === true) {
sendMessage.call(this, args.auctionId, args.requestId);
sendMessage.call(this, args.auctionId, args.requestId, 'soloBidWon');
} else if (!rubiConf.waitForGamSlots && Object.keys(auctionCache.bidsWon).reduce((memo, adUnitCode) => {
// only send if we've received bidWon events for all adUnits in auction
memo = memo && auctionCache.bidsWon[adUnitCode];
Expand All @@ -759,14 +769,23 @@ let rubiconAdapter = Object.assign({}, baseAdapter, {
clearTimeout(cache.timeouts[args.auctionId]);
delete cache.timeouts[args.auctionId];

sendMessage.call(this, args.auctionId);
sendMessage.call(this, args.auctionId, undefined, 'allBidWons');
}
break;
case AUCTION_END:
// start timer to send batched payload just in case we don't hear any BID_WON events
cache.timeouts[args.auctionId] = setTimeout(() => {
sendMessage.call(this, args.auctionId);
}, rubiConf.analyticsBatchTimeout || SEND_TIMEOUT);
// see how long it takes for the payload to come fire
cache.auctions[args.auctionId].endTs = Date.now();

const isOnlyInstreamAuction = args.adUnits && args.adUnits.every(adUnit => adUnitIsOnlyInstream(adUnit));
// If only instream, do not wait around, just send payload
if (isOnlyInstreamAuction) {
sendMessage.call(this, args.auctionId, undefined, 'instreamAuction');
} else {
// start timer to send batched payload just in case we don't hear any BID_WON events
cache.timeouts[args.auctionId] = setTimeout(() => {
sendMessage.call(this, args.auctionId, undefined, 'auctionEnd');
}, rubiConf.analyticsBatchTimeout || SEND_TIMEOUT);
}
break;
case BID_TIMEOUT:
args.forEach(badBid => {
Expand Down
15 changes: 13 additions & 2 deletions test/spec/modules/rubiconAnalyticsAdapter_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,12 @@ const MOCK = {
}
}
},
'mediaType': 'video',
'mediaTypes': {
'video': {
'context': 'instream',
'playerSize': [640, 480]
}
},
'adUnitCode': '/19968336/header-bid-tag-0',
'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014',
'sizes': [[640, 480]],
Expand Down Expand Up @@ -362,7 +367,6 @@ const STUBBED_UUID = '12345678-1234-1234-1234-123456789abc';

const ANALYTICS_MESSAGE = {
'channel': 'web',
'eventTimeMillis': 1519767013781,
'integration': 'pbjs',
'version': '$prebid.version$',
'referrerUri': 'http://www.test.com/page.html',
Expand All @@ -371,6 +375,12 @@ const ANALYTICS_MESSAGE = {
'id': STUBBED_UUID,
'start': 1519767013781
},
'timestamps': {
'auctionEnded': 1519767013781,
'eventTime': 1519767013781,
'prebidLoaded': rubiconAnalyticsAdapter.MODULE_INITIALIZED_TIME
},
'trigger': 'allBidWons',
'referrerHostname': 'www.test.com',
'auctions': [
{
Expand Down Expand Up @@ -1658,6 +1668,7 @@ describe('rubicon analytics adapter', function () {
lineItemId: 6666,
adSlot: '/19968336/header-bid-tag1'
};
expectedMessage.trigger = 'gam';
expect(message).to.deep.equal(expectedMessage);
});

Expand Down
5 changes: 0 additions & 5 deletions test/spec/modules/rubiconAnalyticsSchema.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"description": "A batched data object describing the lifecycle of an auction or multiple auction across a single page view.",
"type": "object",
"required": [
"eventTimeMillis",
"integration",
"version"
],
Expand All @@ -21,10 +20,6 @@
}
],
"properties": {
"eventTimeMillis": {
"type": "integer",
"description": "Unix timestamp of time of creation for this batched event in milliseconds."
},
"integration": {
"type": "string",
"description": "Integration type that generated this event.",
Expand Down