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

Audiencelogy Bid Adapter : Initial Release #11853

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
161 changes: 161 additions & 0 deletions modules/audiencelogyBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import {
deepAccess,
generateUUID,
isArray,
logError
} from '../src/utils.js';
import {
BANNER
} from '../src/mediaTypes.js';
import {
registerBidder
} from '../src/adapters/bidderFactory.js';

const BIDDER_CODE = 'audiencelogy';
const ENDPOINT_URL = 'https://rtb.audiencelogy.com/prebid';

// Export const spec
export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: BANNER,
// Determines whether or not the given bid request is valid
isBidRequestValid: function (bid) {
return !!(bid.params.placement_id && bid.params.user_id && bid.params.nid);
},
// Make a server request from the list of BidRequests
buildRequests: function (bidRequests, bidderRequest) {
const requests = [];
let nid = 0;
// Loop for each bid request
bidRequests.forEach(bid => {
// Create the bid request object
const request = {
id: generateUUID(),
imp: [{
id: bid.bidId,
bidfloor: fetchFloor(bid),
banner: fetchBanner(bid)
}],
placementId: bid.params.placement_id,
site: fetchSite(bidderRequest),
user: setUser(bid)
};
// Fetch GPP Consent from bidderRequest
if (bidderRequest?.gppConsent?.gppString) {
request.gpp = bidderRequest.gppConsent.gppString;
request.gpp_sid = bidderRequest.gppConsent.applicableSections;
} else if (bidderRequest?.ortb2?.regs?.gpp) {
request.gpp = bidderRequest.ortb2.regs.gpp;
request.gpp_sid = bidderRequest.ortb2.regs.gpp_sid;
}
// Fetch coppa compliance from bidderRequest
if (bidderRequest?.ortb2?.regs?.coppa) {
request.coppa = 1;
}
// Fetch uspConsent from bidderRequest
if (bidderRequest && bidderRequest.uspConsent) {
request.us_privacy = bidderRequest.uspConsent;
}
// Push the created bid request to the requests array
requests.push(request);
// Set nid value
nid = bid.params.nid;
});
// Return the array of bid requests
return {
method: 'POST',
url: `${ENDPOINT_URL}/${nid}`,
data: JSON.stringify(requests),
options: {
contentType: 'application/json',
}
};
},
// Unpack the response from the server into a list of bids.
interpretResponse: function (bidResponse, bidRequest) {
let resp = [];
if (bidResponse && bidResponse.body) {
try {
let bids = bidResponse.body.seatbid && bidResponse.body.seatbid[0] ? bidResponse.body.seatbid[0].bid : [];
if (bids) {
bids.forEach(bidObj => {
let newBid = buildResponse(bidObj);
newBid.mediaType = BANNER;
resp.push(newBid);
});
}
} catch (err) {
logError(err);
}
}
return resp;
}
}
// Function to fetch bid_floor
const fetchFloor = (bid) => {
if (bid.params && bid.params.bid_floor) {
return bid.params.bid_floor;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make sure to check the getFloor function from the request

} else {
return 0;
}
}
// Function to fetch banner details
const fetchBanner = (bid) => {
if (deepAccess(bid, 'mediaTypes.banner')) {
// Fetch width and height from MediaTypes object, if not provided in bid params
if (deepAccess(bid, 'mediaTypes.banner.sizes') && !bid.params.height && !bid.params.width) {
let sizes = deepAccess(bid, 'mediaTypes.banner.sizes');
if (isArray(sizes) && sizes.length > 0) {
return {
h: sizes[0][1],
w: sizes[0][0]
};
}
} else {
return {
h: bid.params.height,
w: bid.params.width
};
}
}
}
// Function to fetch site details
const fetchSite = (bidderRequest) => {
let site = {};
if (bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.page) {
site.name = bidderRequest.refererInfo.domain;
} else {
site.name = '';
}
return site;
}
// Function to create response
const buildResponse = (bid) => {
let response = {};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't accept changes designed to fool the duplication checker

Copy link
Contributor Author

@hasanideepak hasanideepak Jun 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, we are an advertising tech company helping different clients like relevate health. We are fine with adding common code, please let me know where to add common functions in library?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! Thank you. See #11854 for example or #11879

response.requestId = bid && bid.impid ? bid.impid : undefined;
response.width = bid && bid.w ? bid.w : 0;
response.height = bid && bid.h ? bid.h : 0;
response.cpm = bid && bid.price ? bid.price : 0.0;
response.ad = bid && bid.adm ? bid.adm : '';
response.creativeId = bid && bid.crid ? bid.crid : undefined;
response.meta = {
advertiserDomains: bid && bid.adomain ? bid.adomain : []
};
response.netRevenue = false;
response.currency = bid && bid.cur ? bid.cur : 'USD';
response.dealId = bid && bid.dealId ? bid.dealId : undefined;
response.ttl = 300;
return response;
}
// Function to build the user object
const setUser = (bid) => {
let user = {};
if (bid && bid.params) {
user.buyeruid = localStorage.getItem('adx_profile_guid') ? localStorage.getItem('adx_profile_guid') : '';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to import the storage manager to do this, publishers manage bidder access to storage depending on consent or their preferences

user.id = bid.params.user_id && typeof bid.params.user_id == 'string' ? bid.params.user_id : '';
user.keywords = bid.params.keywords && typeof bid.params.keywords == 'string' ? bid.params.keywords : '';
user.customdata = bid.params.customdata && typeof bid.params.customdata == 'string' ? bid.params.customdata : '';
}
return user;
}
registerBidder(spec);
41 changes: 41 additions & 0 deletions modules/audiencelogyBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Overview

```
Module Name: Audiencelogy Bidder Adapter
Module Type: Bidder Adapter
Maintainer: support@audiencelogy.com
```

# Description

Audiencelogy currently supports the BANNER type ads through prebid js

Module that connects to audiencelogy's demand sources.

# Banner Test Request
```
var adUnits = [
{
code: 'display-ad',
mediaTypes: {
banner: {
sizes: [[160, 600]],
}
}
bids: [
{
bidder: 'audiencelogy',
params: {
user_id: '1111111' // Required parameter
nid: 1, // Required parameter
placement_id: 584, // Required parameter
width: 160, // Optional parameter
height: 600, // Optional parameter
domain: '', // Optional parameter
bid_floor: 0.5 // Optional parameter
}
}
]
}
];
```
Loading
Loading