If you would like to collect Reporting data from Ad Revenue Insights, this short guide will help you build the API call, and explain the basics.
Ad Revenue Insights module comes with a Pull API, for you to utilise the API data we collect in other systems, or maybe just for data dumps.
Preparations:
There are a few steps that might be good to go through, before you will see your data:
1. You can either use an existing "Admin User" in the system, or you can create a new "Admin user" and utilise it as a dedicated API user. We do recommend creating a new Admin User, that you use as a dedicated API user, to avoid any changes if you would need to close down specific Users in the system.
So a new clean Admin user, only used for the API, is actually a good way of doing this.
2. Get the credentials for the new Admin user, that you would like to use as the API connection User.
3. Make sure you have the right URL. All clients have their own unique Domain URL, and your account is no different, so please ask your Techncial Account Manager for the correct domain to call.
The script example:
This example highlights the functions with some explanations, that will be more detailed in the later section:
from datetime import datetime
import requests
import json
import os
import re
import csv
import collections
url = "insert_your_domain"
credentials = {"email" : 'your-email',"password" : 'your_password'}
date = '2022-04-11'
csvFileName = 'output_' + date + '.csv'
response = requests.post(url + "/users/login",data=credentials)
if response.status_code > 400:
raise Exception('Status code: '+str(response.status_code))
token_value = response.json()["result"]["token"]
def runCommand(path, params):
resp = requests.post(
url=url + path,
headers={
"accept": "*/*",
"authorization": token_value,
"content-type": "application/json"
},
data=json.dumps(params)
)
if resp.status_code >= 400:
raise Exception('Status code: '+str(resp.status_code))
return resp.json()['result']
groupBy = [
'date', # Date
'siteId', # Site
'publisherId', # Publisher
'placementId', # Placement
'sourceId', # Source
'sspId', # SSP
'revenueType', # Revenue type
'advertiserNr', # Advertiser
'buyerNr', # Buyer
'dealNr', # Deal
'bidderNr', # DSP
'size', # Crative Size
'paymentTypeId', # Payment type
'mediaTypeId', # Media type
'dealTypeId', # Deal type
'orderNr', # Order
'lineItemNr', # Line item
]
sums = [
'revenue', # API Gross revenue
'revenueAfterSsp', # Total revenue
'soldImpressions', # Sold impressions
'clicks', # Clicks
'ism', # Viewable Imps
'ismMeasured', # Viewable measured
]
reportSettings = {
"customCommand": "reportProgrammatic",
"reportFormat": "array", # new array-format..
"start": date,
"end": date,
# set the below to something high to include all advertisers/buyers etc without grouping them into "[Smaller advertisers]" etc.
"maxAdvertisers": '10000000',
"attributes": {
"advertiserNr": {
"externalId": True,
},
"dealNr": {
"dealId": True,
"name": True,
},
"sourceId": {
"id": True,
"name": True,
}
},
"groupBy": groupBy,
"sums": sums,
# uncomment the 'advMappingId'-row to not use the default advertiser mappings, that would be the same as using this report UI-setting:
# Other options => Advertiser mapping => [Ignore default mappings]
# "advMappingId": "no_mapping_magic",
}
result = runCommand("/reports", reportSettings)
arr = result['data']
if len(arr):
with open(csvFileName, 'w') as file:
wr = csv.writer(file, quoting=csv.QUOTE_ALL)
wr.writerow(arr[0].keys())
for row in arr:
wr.writerow(row.values())
else:
print("Report is empty")
# List import-status for all systems:
# "completed" => OK
# "failed" => Error at Import
# "none" => Import not run (yet)
ssps = runCommand("/ssps", { "customCommand": "getAll" })
tasks = runCommand("/tasks", { "customCommand": "getTasks", "start": date, "end": date, "type": "SSPimport" })
print("====== Import status by system ======")
for ssp in ssps:
if ssp['active']: # Only include active systems
task = next(t for t in tasks if t['objectId'] == ssp['id'])
state = task['state'] if task else "none"
print("\t" + ssp['name'] + ": " + state)
print("Done")
1. Setting up the Credentials, the Domain you need to access and the name of the Output file:
url = "INSERT_YOUR_DOMAIN"
credentials = {"email" : 'bla',"password" : 'bla'}
date = '2022-04-11'
csvFileName = 'output_' + date + '.csv'
2. Options on how to group your output:
groupBy = [
'date', # Date
'siteId', # Site
'publisherId', # Publisher
'placementId', # Placement
'sourceId', # Source
'sspId', # SSP
'revenueType', # Revenue type
'advertiserNr', # Advertiser
'buyerNr', # Buyer
'dealNr', # Deal
'bidderNr', # DSP
'size', # Crative Size
'paymentTypeId', # Payment type
'mediaTypeId', # Media type
'dealTypeId', # Deal type
'orderNr', # Order
'lineItemNr', # Line item
This corresponds to the Dimensions in your normal GUI reporting.
3. Selecting the Metrics you would like to report on:
sums = [
'revenue', # API Gross revenue
'revenueAfterSsp', # Total revenue
'soldImpressions', # Sold impressions
'clicks', # Clicks
'ism', # Viewable Imps
'ismMeasured', # Viewable measured
4. Putting the settings together:
reportSettings = {
"customCommand": "reportProgrammatic",
"reportFormat": "array", # new array-format..
"start": date,
"end": date,
# set the below to something high to include all advertisers/buyers etc without grouping them into "[Smaller advertisers]" etc.
"maxAdvertisers": '10000000',
"attributes": {
"advertiserNr": {
"externalId": True,
},
"dealNr": {
"dealId": True,
"name": True,
},
"sourceId": {
"id": True,
"name": True,
}
},
"groupBy": groupBy,
"sums": sums,
# uncomment the 'advMappingId'-row to not use the default advertiser mappings, that would be the same as using this report UI-setting:
# Other options => Advertiser mapping => [Ignore default mappings]
# "advMappingId": "no_mapping_magic",
This is where you put the options listed above into a coherent report.
- "maxAdvertisers" can be used if there is a very large number of advertisers, it might make sense to limit them.
- The "attributes" are additional information that can be added if needed.
- "advMapping" defines if you would like to use the advertiser mappings that you might utilize in the GUI.