Skip to content

Commit

Permalink
Nexverse Bid Adapter : initial relese (#12297)
Browse files Browse the repository at this point in the history
* Add nexverseBidAdapter implementation and tests

* Updated Nexverse adapter to support OpenRTB 2.5, handle 204 responses, and added device and connection type detection

* Resolved conflicts and merged master into nexverse-bid-adapter

* Code optimization:
* created utils for all common code
* reused prebid inbuild functions
* created nexverse.html to text nexverse adaptor
* changed test specs based on main js

* Code optimization:
* created utils for all common code
* reused prebid inbuild functions
* created nexverse.html to text nexverse adaptor
* changed test specs based on main js

* * Removed bidfloor from Adunit
* Fixed issues of 1.Category 2.Domain 3.Attributes
* Added Nexverse Demo html for testing with sample bid
* Handled Height and width issue

* * Added test cases for bid param checks
* fixed bidFloor issue

* * Added testcases for utils functions
'

* * removed duplicate function and used from available library

* * removed unwated logging

* * added logger in try catch

* fixed linter error

* * fixed linter issue

* fixed the getOsVersion missing function issue

* fixed the getOsVersion missing function issue

* removed hardcoded cpm value

* Added comment for is debug param

---------

Co-authored-by: yogeshverse <[email protected]>
  • Loading branch information
anand-nexverse and yogeshverse authored Dec 11, 2024
1 parent 84a2278 commit 0b1c521
Show file tree
Hide file tree
Showing 5 changed files with 747 additions and 0 deletions.
126 changes: 126 additions & 0 deletions integrationExamples/gpt/nexverse.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<!--
This page calls a single bidder for a single ad slot. It can be considered a "hello world" example for using
Prebid with the Google Publisher Tag.
It also makes a good test page for new adapter PR submissions. Simply set your server's Bid Params object in the
bids array inside the adUnits, and it will use your adapter to load an ad.
NOTE that many ad servers won't send back an ad if the URL is localhost... so you might need to
set an alias in your /etc/hosts file so that you can load this page from a different domain.
-->

<html>

<head>
<title>NexVerse Prebid.Js Demo</title>
<script async src="../../build/dev/prebid.js"></script>
<script async src="https://www.googletagservices.com/tag/js/gpt.js"></script>
<script>
var FAILSAFE_TIMEOUT = 3300;
var PREBID_TIMEOUT = 1000;

var adUnits = [{
code: 'div-banner-native-1',
mediaTypes: {
banner: {
sizes: [[970, 90]],
}
},

// Replace this object to test a new Adapter!
bids: [{
bidder: 'nexverse',
params: {
uid: '77d4a2eb3d209ce6c7691dc79fcab358',
pubId: '24051',
pubEpid: '34561'
},
isDebug: false // Optional, i.e True for debug mode
}]

},{
code: 'div-banner-native-2',
mediaTypes: {
banner: {
sizes: [[300, 250]],
}
},

// Replace this object to test a new Adapter!
bids: [{
bidder: 'nexverse',
params: {
uid: '77d4a2eb3d209ce6c7691dc79fcab358',
pubId: '24051',
pubEpid: '34561'
},
isDebug: false // Optional, i.e True for debug mode
}]

}];

var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];

</script>

<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
googletag.cmd.push(function () {
googletag.pubads().disableInitialLoad();
});

pbjs.que.push(function () {
pbjs.addAdUnits(adUnits);

pbjs.requestBids({
bidsBackHandler: sendAdserverRequest,
timeout: PREBID_TIMEOUT
});
});

function sendAdserverRequest() {
if (pbjs.adserverRequestSent) return;
pbjs.adserverRequestSent = true;
googletag.cmd.push(function () {
pbjs.que.push(function () {
pbjs.setTargetingForGPTAsync();
googletag.pubads().refresh();
});
});
}

setTimeout(function () {
sendAdserverRequest();
}, FAILSAFE_TIMEOUT);

</script>

<script>
googletag.cmd.push(function () {
googletag.defineSlot('/19968336/header-bid-tag-0', [[970, 90]], 'div-banner-native-1').addService(googletag.pubads());
googletag.defineSlot('/19968336/header-bid-tag-1', [[300, 250]], 'div-banner-native-2').addService(googletag.pubads());

googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
</head>

<body>
<h2>Nexverse Prebid.js Test</h2>
<h5>Div-1</h5>
<div id='div-banner-native-1'>
<script type='text/javascript'>
googletag.cmd.push(function () { googletag.display('div-banner-native-1'); });
</script>
</div>

<h5>Div-2</h5>
<div id='div-banner-native-2'>
<script type='text/javascript'>
googletag.cmd.push(function () { googletag.display('div-banner-native-2'); });
</script>
</div>
</body>

</html>
130 changes: 130 additions & 0 deletions libraries/nexverseUtils/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { logError, logInfo, logWarn, generateUUID } from '../../src/utils.js';

const LOG_WARN_PREFIX = '[Nexverse warn]: ';
const LOG_ERROR_PREFIX = '[Nexverse error]: ';
const LOG_INFO_PREFIX = '[Nexverse info]: ';
const NEXVERSE_USER_COOKIE_KEY = 'user_nexverse';

/**
* Determines the device model (if possible).
* @returns {string} The device model or a fallback message if not identifiable.
*/
export function getDeviceModel() {
const ua = navigator.userAgent;
if (/iPhone/i.test(ua)) {
return 'iPhone';
} else if (/iPad/i.test(ua)) {
return 'iPad';
} else if (/Android/i.test(ua)) {
const match = ua.match(/Android.*;\s([a-zA-Z0-9\s]+)\sBuild/);
return match ? match[1].trim() : 'Unknown Android Device';
} else if (/Windows Phone/i.test(ua)) {
return 'Windows Phone';
} else if (/Macintosh/i.test(ua)) {
return 'Mac';
} else if (/Linux/i.test(ua)) {
return 'Linux';
} else if (/Windows/i.test(ua)) {
return 'Windows PC';
}
return '';
}

/**
* Prepapre the endpoint URL based on passed bid request.
* @param {string} bidderEndPoint - Bidder End Point.
* @param {object} bid - Bid details.
* @returns {string} The Endpoint URL with required parameters.
*/
export function buildEndpointUrl(bidderEndPoint, bid) {
const { uid, pubId, pubEpid } = bid.params;
const isDebug = bid.isDebug;
let endPoint = `${bidderEndPoint}?uid=${encodeURIComponent(uid)}&pub_id=${encodeURIComponent(pubId)}&pub_epid=${encodeURIComponent(pubEpid)}`;
if (isDebug) {
endPoint = `${endPoint}&test=1`;
}
return endPoint;
}
/**
* Validates the bid request to ensure all required parameters are present.
* @param {Object} bid - The bid request object.
* @returns {boolean} True if the bid request is valid, false otherwise.
*/
export function isBidRequestValid(bid) {
const isValid = !!(
bid.params &&
bid.params.uid && bid.params.uid.trim() &&
bid.params.pubId && bid.params.pubId.trim() &&
bid.params.pubEpid && bid.params.pubEpid.trim()
);
if (!isValid) {
logError(`${LOG_ERROR_PREFIX} Missing required bid parameters.`);
}

return isValid;
}

/**
* Parses the native response from the server into Prebid's native format.
*
* @param {string} adm - The adm field from the bid response (JSON string).
* @returns {Object} The parsed native response object.
*/
export function parseNativeResponse(adm) {
try {
const admObj = JSON.parse(adm);
return admObj.native;
} catch (e) {
printLog('error', `Error parsing native response: `, e)
logError(`${LOG_ERROR_PREFIX} Error parsing native response: `, e);
return {};
}
}

/**
* Parses the native response from the server into Prebid's native format.
* @param {type} type - Type of log. default is info
* @param {args} args - Log data.
*/
export function printLog(type, ...args) {
// Determine the prefix based on the log type
const prefixes = {
error: LOG_ERROR_PREFIX,
warning: LOG_WARN_PREFIX, // Assuming warning uses the same prefix as error
info: LOG_INFO_PREFIX
};

// Construct the log message by joining all arguments into a single string
const logMessage = args
.map(arg => (arg instanceof Error ? `${arg.name}: ${arg.message}` : arg))
.join(' '); // Join all arguments into a single string with a space separator
// Add prefix and punctuation (for info type)
const formattedMessage = `${prefixes[type] || LOG_INFO_PREFIX} ${logMessage}${type === 'info' ? '.' : ''}`;
// Map the log type to its corresponding log function
const logFunctions = {
error: logError,
warning: logWarn,
info: logInfo
};

// Call the appropriate log function (defaulting to logInfo)
(logFunctions[type] || logInfo)(formattedMessage);
}
/**
* Get or Create Uid for First Party Cookie
*/
export const getUid = (storage) => {
let nexverseUid = storage.getCookie(NEXVERSE_USER_COOKIE_KEY);
if (!nexverseUid) {
nexverseUid = generateUUID();
}
try {
const expirationInMs = 60 * 60 * 24 * 1000; // 1 day in milliseconds
const expirationTime = new Date(Date.now() + expirationInMs); // Set expiration time
// Set the cookie with the expiration date
storage.setCookie(NEXVERSE_USER_COOKIE_KEY, nexverseUid, expirationTime.toUTCString());
} catch (e) {
printLog('error', `Failed to set UID cookie: ${e.message}`);
}
return nexverseUid;
};
Loading

0 comments on commit 0b1c521

Please sign in to comment.