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

EightPod Bid Adapter + EightPod Analytic Adapter - Support multiple adUnit, updated event tracking, added UserId support #11944

Merged
merged 5 commits into from
Jul 11, 2024
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
62 changes: 28 additions & 34 deletions modules/eightPodAnalyticsAdapter.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {logError, logInfo} from '../src/utils.js';
import {logError, logInfo, logMessage} from '../src/utils.js';
import {ajax} from '../src/ajax.js';
import adapter from '../libraries/analyticsAdapter/AnalyticsAdapter.js';
import { EVENTS } from '../src/constants.js';
Expand All @@ -9,72 +9,72 @@ import {getStorageManager} from '../src/storageManager.js';
const analyticsType = 'endpoint';
const MODULE_NAME = `eightPod`;
const MODULE = `${MODULE_NAME}AnalyticProvider`;
let interval;

/**
* Custom tracking server that gets internal events from EightPod's ad unit
*/
const trackerUrl = 'https://demo.8pod.com/tracker/track';

export const storage = getStorageManager({moduleType: MODULE_TYPE_ANALYTICS, moduleName: MODULE_NAME})

const {
BID_WON
} = EVENTS;

export let queue = [];
export let context;
let context = {};

/**
* Create eightPod Analytic adapter
*/
let eightPodAnalytics = Object.assign(adapter({ analyticsType }), {
let eightPodAnalytics = Object.assign(adapter({url: trackerUrl, analyticsType}), {
/**
* Execute on bid won - setup basic settings, save context about EightPod's bid. We will send it with our events later
*/
track({ eventType, args }) {
switch (eventType) {
case BID_WON:
if (args.bidder === 'eightPod') {
context[args.adUnitCode] = makeContext(args);

eightPodAnalytics.setupPage(args);
context = makeContext(args);
break;
}
}
},

/**
* Execute on bid won - subscribe on events from adUnit
* Execute on bid won upload events from local storage
*/
setupPage() {
eightPodAnalytics.eventSubscribe();
queue = getEventFromLocalStorage();
queue = this.getEventFromLocalStorage();
},

/**
* Subscribe on internal ad unit tracking events
*/
eventSubscribe() {
window.addEventListener('message', async (event) => {
const data = event?.data;
const data = event.data;

if (!data?.detail?.name) {
return;
}
const frameElement = event.source.frameElement;
const parentElement = frameElement?.parentElement;
const adUnitCode = parentElement?.id;

trackEvent(data);
trackEvent(data, adUnitCode);
});

// Send queue of event every 10 seconds
if (!interval) {
interval = setInterval(sendEvents, 10_000);
}
setInterval(sendEvents, 10_000);
},
resetQueue() {
queue = [];
},
getContext() {
return context;
}
},
resetContext() {
context = {};
},
getEventFromLocalStorage,
});

/**
Expand All @@ -84,8 +84,8 @@ function makeContext(args) {
const params = args?.params?.[0];
return {
bidId: args.seatBidId,
variantId: args.creativeId || 'variantId',
campaignId: 'campaignId',
variantId: args.creativeId || '',
campaignId: args.cid || '',
publisherId: params.publisherId,
placementId: params.placementId,
};
Expand All @@ -94,19 +94,21 @@ function makeContext(args) {
/**
* Create event, add context and push it to queue
*/
export function trackEvent(event) {
export function trackEvent(event, adUnitCode) {
if (!event.detail) {
return;
}

const fullEvent = {
context: eightPodAnalytics.getContext(),
context: eightPodAnalytics.getContext()[adUnitCode],
eventType: event.detail.type,
eventClass: 'adunit',
timestamp: new Date().getTime(),
eventName: event.detail.name,
payload: event.detail.payload
};

logMessage(fullEvent);
addEvent(fullEvent);
}

Expand Down Expand Up @@ -158,7 +160,7 @@ function sendEvents() {
* Send event to our custom tracking server
*/
function sendEventsApi(eventList, callbacks) {
ajax(trackerUrl, callbacks, JSON.stringify(eventList));
ajax(trackerUrl, callbacks, JSON.stringify(eventList), {keepalive: true});
}

/**
Expand All @@ -173,21 +175,13 @@ eightPodAnalytics.originEnableAnalytics = eightPodAnalytics.enableAnalytics;
eightPodAnalytics.eventsStorage = [];

// override enableAnalytics so we can get access to the config passed in from the page
// Subscribe on events from adUnit
eightPodAnalytics.enableAnalytics = function (config) {
eightPodAnalytics.originEnableAnalytics(config);
logInfo(MODULE, 'init', config);
eightPodAnalytics.eventSubscribe();
};

eightPodAnalytics.disableAnalytics = (function (orig) {
return function (...args) {
if (interval) {
clearInterval(interval);
interval = null;
}
return orig.apply(this, args);
};
})(eightPodAnalytics.disableAnalytics);

/**
* Register Analytics Adapter
*/
Expand Down
170 changes: 113 additions & 57 deletions modules/eightPodBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BANNER } from '../src/mediaTypes.js'
import * as utils from '../src/utils.js'

export const BIDDER_CODE = 'eightPod'
const url = 'https://demo.8pod.com/bidder/rtb/eightpod_exchange/bid?trace=true';
const url = 'https://demo.8pod.com/bidder/rtb/eightpod_exchange/bid';

export const spec = {
code: BIDDER_CODE,
Expand Down Expand Up @@ -49,8 +49,9 @@ function isBidRequestValid(bidRequest) {
function buildRequests(bids, bidderRequest) {
let bannerBids = bids.filter((bid) => isBannerBid(bid))
let requests = bannerBids.length
? [createRequest(bannerBids, bidderRequest, BANNER)]
? createRequest(bannerBids, bidderRequest, BANNER)
: []

return requests
}

Expand All @@ -61,8 +62,10 @@ function bidResponse(buildBidResponse, bid, context) {

bidResponse.height = context?.imp?.banner?.format?.[0].h;
bidResponse.width = context?.imp?.banner?.format?.[0].w;
bidResponse.cid = bid.cid;

bidResponse.burl = replacePriceInUrl(bid.burl, bidResponse.originalCpm || bidResponse.cpm);

return bidResponse;
}

Expand Down Expand Up @@ -119,64 +122,75 @@ export function getPageKeywords(win = window) {
}

function createRequest(bidRequests, bidderRequest, mediaType) {
const data = converter.toORTB({
bidRequests,
bidderRequest,
context: { mediaType },
});

data.adSlotPositionOnScreen = 'ABOVE_THE_FOLD';
data.at = 1;

const params = getBidderParams(bidRequests);

data.device = {
...data.device,
model: parseUserAgent().device,
os: parseUserAgent().platform,
osv: parseUserAgent().version,
geo: {
country: params.country || 'GRB'
},
language: params.language || data.device.language,
}
data.site = {
...data.site,
keywords: getPageKeywords(window),
}
data.imp = [
{
...data.imp?.[0],
pmp: params.dealId
? {
...data.pmp,
deals: [
{
bidfloor: 0.5,
at: 2,
id: params.dealId,
},
],
private_auction: 1,
}
: data.pmp,
const requests = bidRequests.map((bidRequest) => {
const data = converter.toORTB({
bidRequests: [bidRequest],
bidderRequest,
context: { mediaType },
});

data.adSlotPositionOnScreen = 'ABOVE_THE_FOLD';
data.at = 1;

const userId =
utils.deepAccess(bidRequest, 'userId.unifiedId.id') ||
utils.deepAccess(bidRequest, 'userId.id5id.uid') ||
utils.deepAccess(bidRequest, 'userId.idl_env');

const params = getBidderParams(bidRequest);
data.device = {
...data.device,
devicetype: 4,
geo: {
country: params.country || 'GRB'
},
language: params.language || data.device.language,
}
data.site = {
...data.site,
keywords: getPageKeywords(window),
publisher: {
id: params.publisherId
}
}
data.imp = [
{
...data.imp?.[0],
secure: 1,
pmp: params.dealId
? {
...data.pmp,
deals: [
{
id: params.dealId,
},
],
private_auction: 1,
}
: data.pmp,
}
]
data.adSlotPlacementId = params.placementId;

if (userId) {
data.user = {
id: userId
}
}
]
data.adSlotPlacementId = params.placementId;

const req = {
method: 'POST',
url,
data
}
return req
}
const req = {
method: 'POST',
url: url && params.trace ? url + '?trace=true' : url,
options: { withCredentials: false },
data
}
return req
})

function getBidderParams(bidRequests) {
const bid = bidRequests.find(bid => {
return bid.bidder === BIDDER_CODE
});
return requests;
}

function getBidderParams(bid) {
return bid?.params ? bid.params : undefined;
}

Expand All @@ -189,5 +203,47 @@ function isBannerBid(bid) {
}

function interpretResponse(resp, req) {
return converter.fromORTB({ request: req.data, response: resp.body })
const impressionId = resp.body.seatbid[0].bid[0].impid;
const bidResponses = converter.fromORTB({ request: req.data, response: resp.body });
const ad = bidResponses[0].ad;
const trackingTag = `<script src="https://cdn.doubleverify.com/dvtp_src.js?ctx=818052&cmp=APAC_Cert_20&sid=se_a551&plc=240411845&adsrv=0&btreg=ad-unit-container&auevent=${impressionId}&btadsrv=&crt=01&tagtype=&dvtagver=6.1.src" type="text/javascript"></script>
<script type="text/javascript">
(function() {
/** CONFIGURATION START **/
var _sf_async_config = window._sf_async_config = (window._sf_async_config || {});
_sf_async_config.uid = 67171;
_sf_async_config.domain = 'demo.8pod.com';
_sf_async_config.flickerControl = false;
_sf_async_config.useCanonical = true;
_sf_async_config.useCanonicalDomain = true;
_sf_async_config.sections = '';
_sf_async_config.authors = '';
/** CONFIGURATION END **/
function loadChartbeat() {
var e = document.createElement('script');
var n = document.getElementsByTagName('script')[0];
e.type = 'text/javascript';
e.async = true;
e.src = '//static.chartbeat.com/js/chartbeat.js';
n.parentNode.insertBefore(e, n);
}
loadChartbeat();
})();
</script>
<script async src="//static.chartbeat.com/js/chartbeat_mab.js"></script>

<script type="text/javascript">
var utag_data = {
}
</script>
<script type="text/javascript">
(function(a,b,c,d){
a='https://tags.tiqcdn.com/utag/sales-richard-coghlan/8pod/prod/utag.js';
b=document;c='script';d=b.createElement(c);d.src=a;d.type='text/java'+c;d.async=true;
a=b.getElementsByTagName(c)[0];a.parentNode.insertBefore(d,a);
})();
</script>`

bidResponses[0].ad = ad.replace('</head>', trackingTag + '</head>');
return bidResponses;
}
Loading