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

Revert "Glimpse: update api and request shape, optimize and refactor" #8254

Merged
merged 1 commit into from
Apr 4, 2022
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
265 changes: 147 additions & 118 deletions modules/glimpseBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,201 +1,230 @@
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { config } from '../src/config.js';
import { BANNER } from '../src/mediaTypes.js';
import { getStorageManager } from '../src/storageManager.js';
import {
isArray,
isEmpty,
isEmptyStr,
isStr,
isPlainObject,
} from '../src/utils.js';

const GVLID = 1012;
const BIDDER_CODE = 'glimpse';
const storageManager = getStorageManager({
gvlid: GVLID,
bidderCode: BIDDER_CODE,
});
const ENDPOINT = 'https://market.glimpsevault.io/public/v1/prebid';
import { BANNER } from '../src/mediaTypes.js'
import { config } from '../src/config.js'
import { getStorageManager } from '../src/storageManager.js'
import { isArray } from '../src/utils.js'
import { registerBidder } from '../src/adapters/bidderFactory.js'

const GVLID = 1012
const BIDDER_CODE = 'glimpse'
const storageManager = getStorageManager({bidderCode: BIDDER_CODE})
const ENDPOINT = 'https://api.glimpsevault.io/ads/serving/public/v1/prebid'
const LOCAL_STORAGE_KEY = {
vault: {
jwt: 'gp_vault_jwt',
},
};
}

export const spec = {
gvlid: GVLID,
code: BIDDER_CODE,
supportedMediaTypes: [BANNER],

/**
* Determines if the bid request is valid
* Determines whether or not the given bid request is valid
* @param bid {BidRequest} The bid to validate
* @return {boolean}
*/
isBidRequestValid: (bid) => {
const pid = bid?.params?.pid;
return isStr(pid) && !isEmptyStr(pid);
return (
hasValue(bid) &&
hasValue(bid.params) &&
hasStringValue(bid.params.placementId)
)
},

/**
* Builds the http request
* Builds http request for Glimpse bids
* @param validBidRequests {BidRequest[]}
* @param bidderRequest {BidderRequest}
* @returns {ServerRequest}
*/
buildRequests: (validBidRequests, bidderRequest) => {
const url = buildQuery(bidderRequest);
const auth = getVaultJwt();
const referer = getReferer(bidderRequest);
const imp = validBidRequests.map(processBidRequest);
const fpd = getFirstPartyData();
const auth = getVaultJwt()
const referer = getReferer(bidderRequest)
const gdprConsent = getGdprConsentChoice(bidderRequest)
const bidRequests = validBidRequests.map(processBidRequest)
const firstPartyData = getFirstPartyData()

const data = {
auth,
data: {
referer,
imp,
fpd,
},
};
gdprConsent,
bidRequests,
site: firstPartyData.site,
user: firstPartyData.user,
bidderCode: spec.code,
}
}

return {
method: 'POST',
url,
url: ENDPOINT,
data: JSON.stringify(data),
options: {},
};
}
},

/**
* Parse http response
* @param response {ServerResponse}
* Parse response from Glimpse server
* @param bidResponse {ServerResponse}
* @returns {Bid[]}
*/
interpretResponse: (response) => {
if (isValidResponse(response)) {
const { auth, data } = response.body;
setVaultJwt(auth);
const bids = data.bids.map(processBidResponse);
return bids;
interpretResponse: (bidResponse) => {
const isValidResponse = isValidBidResponse(bidResponse)

if (isValidResponse) {
const {auth, data} = bidResponse.body
setVaultJwt(auth)
return data.bids
}
return [];

return []
},
};
}

function setVaultJwt(auth) {
storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth);
storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth)
}

function getVaultJwt() {
return (
storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || ''
);
return storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || ''
}

function getReferer(bidderRequest) {
return bidderRequest?.refererInfo?.referer || '';
const hasReferer =
hasValue(bidderRequest) &&
hasValue(bidderRequest.refererInfo) &&
hasStringValue(bidderRequest.refererInfo.referer)

if (hasReferer) {
return bidderRequest.refererInfo.referer
}

return ''
}

function buildQuery(bidderRequest) {
let url = appendQueryParam(ENDPOINT, 'ver', '$prebid.version$');
function getGdprConsentChoice(bidderRequest) {
const hasGdprConsent =
hasValue(bidderRequest) &&
hasValue(bidderRequest.gdprConsent)

const timeout = config.getConfig('bidderTimeout');
url = appendQueryParam(url, 'tmax', timeout);
if (hasGdprConsent) {
const gdprConsent = bidderRequest.gdprConsent
const hasGdprApplies = hasBooleanValue(gdprConsent.gdprApplies)

if (gdprApplies(bidderRequest)) {
const consentString = bidderRequest.gdprConsent.consentString;
url = appendQueryParam(url, 'reg', 'gdpr');
url = appendQueryParam(url, 'cs', consentString);
} else if (ccpaApplies(bidderRequest)) {
url = appendQueryParam(url, 'reg', 'ccpa');
url = appendQueryParam(url, 'cs', bidderRequest.uspConsent);
} else {
url = appendQueryParam(url, 'reg', 'none');
return {
consentString: gdprConsent.consentString || '',
vendorData: gdprConsent.vendorData || {},
gdprApplies: hasGdprApplies ? gdprConsent.gdprApplies : true,
}
}
return url;
}

function appendQueryParam(url, key, value) {
if (!value) {
return url;
return {
consentString: '',
vendorData: {},
gdprApplies: false,
}
const prefix = url.includes('?') ? '&' : '?';
return `${url}${prefix}${key}=${encodeURIComponent(value)}`;
}

function gdprApplies(bidderRequest) {
return Boolean(bidderRequest?.gdprConsent?.gdprApplies);
}

function ccpaApplies(bidderRequest) {
return (
!isEmptyStr(bidderRequest.uspConsent) &&
bidderRequest.uspConsent.substr(1, 3) !== '---'
);
}

function processBidRequest(bid) {
const sizes = normalizeSizes(bid.sizes);
function processBidRequest(bidRequest) {
const demand = bidRequest.params.demand || 'glimpse'
const sizes = normalizeSizes(bidRequest.sizes)
const keywords = bidRequest.params.keywords || {}

return {
bid: bid.bidId,
pid: bid.params.pid,
demand,
sizes,
};
keywords,
bidId: bidRequest.bidId,
placementId: bidRequest.params.placementId,
unitCode: bidRequest.adUnitCode,
}
}

function normalizeSizes(sizes) {
const isSingleSize =
isArray(sizes) &&
sizes.length === 2 &&
!isArray(sizes[0]) &&
!isArray(sizes[1]);
!isArray(sizes[1])

if (isSingleSize) {
return [sizes];
return [sizes]
}

return sizes;
return sizes
}

function getFirstPartyData() {
let fpd = config.getConfig('ortb2') || {};
optimizeObject(fpd);
return fpd;
}
const siteKeywords = parseGlobalKeywords('site')
const userKeywords = parseGlobalKeywords('user')

function optimizeObject(obj) {
if (!isPlainObject(obj)) {
return;
}
for (const [key, value] of Object.entries(obj)) {
optimizeObject(value);
// only delete empty object, array, or string
if (
(isPlainObject(value) || isArray(value) || isStr(value)) &&
isEmpty(value)
) {
delete obj[key];
}
const siteAttributes = getConfig('ortb2.site.ext.data', {})
const userAttributes = getConfig('ortb2.user.ext.data', {})

return {
site: {
keywords: siteKeywords,
attributes: siteAttributes,
},
user: {
keywords: userKeywords,
attributes: userAttributes,
},
}
}

function isValidResponse(bidResponse) {
const auth = bidResponse?.body?.auth;
const bids = bidResponse?.body?.data?.bids;
return isStr(auth) && isArray(bids) && !isEmpty(bids);
function parseGlobalKeywords(scope) {
const keywords = getConfig(`ortb2.${scope}.keywords`, '')

return keywords
.split(', ')
.filter((keyword) => keyword !== '')
}

function processBidResponse(bid) {
const meta = bid.meta || {};
meta.advertiserDomains = bid.meta?.advertiserDomains || [];
function getConfig(path, defaultValue) {
return config.getConfig(path) || defaultValue
}

return {
...bid,
meta,
};
function isValidBidResponse(bidResponse) {
return (
hasValue(bidResponse) &&
hasValue(bidResponse.body) &&
hasValue(bidResponse.body.data) &&
hasArrayValue(bidResponse.body.data.bids) &&
hasStringValue(bidResponse.body.auth)
)
}

function hasValue(value) {
return (
value !== undefined &&
value !== null
)
}

function hasBooleanValue(value) {
return (
hasValue(value) &&
typeof value === 'boolean'
)
}

function hasStringValue(value) {
return (
hasValue(value) &&
typeof value === 'string' &&
value.length > 0
)
}

function hasArrayValue(value) {
return (
hasValue(value) &&
isArray(value) &&
value.length > 0
)
}

registerBidder(spec);
registerBidder(spec)
15 changes: 8 additions & 7 deletions modules/glimpseBidAdapter.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ const adUnits = [
sizes: [[300, 250]],
},
},
bids: [
{
bidder: 'glimpse',
params: {
pid: 'e53a7f564f8f44cc913b',
bids: [{
bidder: 'glimpse',
params: {
placementId: 'e53a7f564f8f44cc913b',
keywords: {
country: 'uk',
},
},
],
}],
},
];
]
```
Loading