Skip to content

Instantly share code, notes, and snippets.

@romanych
Created December 3, 2020 16:36
Show Gist options
  • Save romanych/61ee873aa56e592f255a86932a645b98 to your computer and use it in GitHub Desktop.
Save romanych/61ee873aa56e592f255a86932a645b98 to your computer and use it in GitHub Desktop.
Miniproxy for DV360 IR
const axios = require("axios");
const rax = require("retry-axios");
const { GoogleAuth } = require('google-auth-library');
async function getDV360AccessToken() {
const auth = new GoogleAuth({ scopes: [ 'https://www.googleapis.com/auth/doubleclickbidmanager' ] });
return await auth.getAccessToken();
};
const Functions = new function () {
const dbmAPI = axios.create({
baseURL: "https://www.googleapis.com/doubleclickbidmanager/v1.1",
});
dbmAPI.interceptors.request.use(async function (config) {
config.headers["Authorization"] = `Bearer ${await getDV360AccessToken()}`;
return config;
});
dbmAPI.defaults.raxConfig = {
instance: dbmAPI,
retry: 5,
noResponseRetries: 3,
retryDelay: 1500,
httpMethodsToRetry: ["GET", "DELETE", "PUT", "POST"],
statusCodesToRetry: [ [100, 199], [429, 429], [500, 599] ],
onRetryAttempt: err => {
const cfg = rax.getConfig(err);
console.log(`Retry attempt #${cfg.currentRetryAttempt}`);
}
};
rax.attach(dbmAPI);
this.getQueries = async ({pageToken}) => {
const response = await dbmAPI.get("/queries", { params: { pageToken: pageToken } });
return response.data;
};
this.getQuery = async ({queryId}) => {
const response = await dbmAPI.get(`/query/${queryId}`);
return response.data;
};
this.createQuery = async ({query}) => {
const queriesResponse = await dbmAPI.post("/query", query);
return queriesResponse.data;
};
this.runQuery = async ({queryId, data}) => {
const response = await dbmAPI.post(`/query/${queryId}`, data);
return response.data;
};
this.getQueryReports = async ({queryId, pageToken}) => {
const response = await dbmAPI.get(`/queries/${queryId}/reports`, { params: { pageToken: pageToken } });
return response.data;
};
};
const ALLOWED_REPORTS = {
"TYPE_GENERAL": {
metrics: ["METRIC_IMPRESSIONS"],
dimensions: ["FILTER_PARTNER", "FILTER_PARTNER_NAME", "FILTER_ADVERTISER", "FILTER_ADVERTISER_NAME", "FILTER_MEDIA_PLAN", "FILTER_MEDIA_PLAN_NAME", "FILTER_INSERTION_ORDER", "FILTER_INSERTION_ORDER_NAME", "FILTER_DATE", "FILTER_LINE_ITEM", "FILTER_LINE_ITEM_TYPE"]
},
"TYPE_TRUEVIEW": {
metrics: [ "METRIC_IMPRESSIONS", "METRIC_RICH_MEDIA_VIDEO_FIRST_QUARTILE_COMPLETES", "METRIC_RICH_MEDIA_VIDEO_MIDPOINTS", "METRIC_RICH_MEDIA_VIDEO_THIRD_QUARTILE_COMPLETES", "METRIC_RICH_MEDIA_VIDEO_COMPLETIONS" ],
dimensions: [ "FILTER_PARTNER", "FILTER_PARTNER_NAME", "FILTER_ADVERTISER", "FILTER_ADVERTISER_NAME", "FILTER_INSERTION_ORDER", "FILTER_INSERTION_ORDER_NAME", "FILTER_DATE", "FILTER_LINE_ITEM", "FILTER_LINE_ITEM_TYPE", "FILTER_TRUEVIEW_GENDER", "FILTER_TRUEVIEW_AGE", "FILTER_TRUEVIEW_COUNTRY" ]
},
"TYPE_REACH_AND_FREQUENCY": {
metrics: ["METRIC_UNIQUE_REACH_IMPRESSION_REACH"],
dimensions: [ "FILTER_PARTNER", "FILTER_PARTNER_NAME", "FILTER_ADVERTISER", "FILTER_ADVERTISER_NAME", "FILTER_MEDIA_PLAN", "FILTER_MEDIA_PLAN_NAME", "FILTER_INSERTION_ORDER", "FILTER_INSERTION_ORDER_NAME", "FILTER_DATE", "FILTER_LINE_ITEM", "FILTER_LINE_ITEM_TYPE", "FILTER_COUNTRY" ]
}
};
async function processRequest(request) {
if (request.operation === "createQuery") {
console.log(request.arguments);
const { type, groupBys, filters, metrics } = request.arguments.query.params;
const allowedConfiguration = ALLOWED_REPORTS[type];
if (!type) {
throw new Error(`Not allowed query type ${type} attempted to be created`);
}
const notAllowedMetrics = metrics.filter(m => allowedConfiguration.metrics.indexOf(m) === -1);
const queriedDimensions = [...groupBys, ...filters.map(f => f.type)];
const notAllowedDimensions = queriedDimensions.filter(d => allowedConfiguration.dimensions.indexOf(d) === -1);
if (notAllowedDimensions.length !== 0 || notAllowedMetrics.length !== 0) {
throw new Error(`Requested not allowed metrics (${notAllowedMetrics}) or dimensions ${notAllowedDimensions}`);
}
}
const operationFunction = Functions[request.operation];
if (!operationFunction) {
throw new Error(`Called unspupported operaion ${request.operation}`);
}
const result = await operationFunction.call(null, request.arguments);
return result;
}
exports.miniproxy = (req, res) => {
console.log("Incoming request", req.body);
processRequest(req.body).then(response => {
console.log("Operation successfully executed");
res.status(200);
res.json(response);
}, err => {
console.log("Operation failed", err.message);
res.status(200);
res.json({error: true, message: err.message});
});
};
{
"name": "miniproxy",
"version": "1.0.0",
"private": true,
"dependencies": {
"axios": "^0.19.2",
"google-auth-library": "^6.1.3",
"retry-axios": "^2.2.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment