a Performance & optimisation "co-pilot" for your buy-side campaigns with automated optimisation triggers
This platform is an additional UI to the Appnexus Xandr console. It's built on top of the Xandr buy-side API (formerly called Appnexus)
It helps media-buyers optimise campaigns based on CPA by automatically collecting the data via API and displaying it in a Pivottable.
fig. 1 See Conversions, CPA, CTR, etc per placement from your Xandr campaigns. Blacklist under-performing PLACEMENTS or DOMAINS with one click.
The Xandr UI (or "console" as they call it) is built by engineers, for engineers. Even the latest attempts to pretty it up have not really made it a "Perfomance platform" To a media-buyer, who is responsible for performance results (eg: conversions, leads, ecomm sales) this is very poor UX. It drains hours and patience. Mistakes get made The purpose of this UI is to be a simple assistant 🚦 so you don't need to use excel so much and can quickly:
✔️ see what's converting, at what cost,
✔️ white-list or black-list placements,
✔️ pause (blacklist for a set time, then reactivate) placements,
✔️ drill-down on what is converting and see: creative, carrier, device-type, OS, etc.
The system uses the reporting API to collect it's data by default. The data is pulled via API and stored in a PostGreSQL DB. Reporting sometimes comes after 6 hours from Xandr. This delay can kill your campaign. For this we additionally built :
- impression tracker
- click tracker
- conversion tracker (Contact us to get access to these separate repos)
You will need to set this up on top of your own domain and get it approved by Xandr support. 1 and 2 above need to be submitted at least 48 hrs before going live.
- Automatic Pivot-tables: CPA's are automatically calculated on yesterday's perfomance.
- "CPA-buckets" are generated per: placement/domain, creative, creative size, Carrier, Seller/network/Exchange
- Create your own Rules to manage AppNexus' traffic, auto-blacklist based on CPM, CTR, CPA, CPC
- Placement ID' matching Placement ID's are core to optimising campaigs in AppNexus. They are the ID's of individual placements, either on a page or site-section. When you run an "Analytics Report" in Xandr you can retrieve "placement ID", but not domain, eg: Xandr Analytics Report
Then if you run a "Site Domain Performance" report you can pull the Seller and Domain/App, but not the placement ID, eg: Xandr Site Domain Performance report
However you can't pull a report to see both Domain and placement ID together. When it comes to CPA, this can make a huge difference. Some specific placements on a site are never profitable. But that doesn't mean the entire domain is not profitable.
The Xandr Rainmaker combines the two reports pulled via API into one as much as possible, based on the data compiled via the API's, and separate impression tracker, click tracker and conversion tracker, as shown in image above 👆
Optimisation in our UI is per placement, not per domain. If buying from Google this doesn;t count, as Google Auth Buyers (AdX) doesn't support placement ID's. So it reverts to domain targeting 🍼
As soon as you set a state in the co-pilot, it will be reflected in the Appnexus console (give or take a minute. And vice-versa) if you blacklist a specific placement in console, it will get displayed as such in the UI.
Click "blacklist" inside the Rainmaker UI like this And a few seconds later it is reflected in Xandr Console Vice-versa, also works. :grey_exclamation: Note: that Xandr doesn't recognise its own placement ID's when you import it back into Xandr. Hence it always marks it as "unknown" or "Undisclosed Placement" :shrug: This doesn't affect your campaign though. The adjustment made in our UI is still obeyed by Xandr.
The optimisation that you do remains in the scope of that Campaign, ie:
- Blacklist = block that placement ID in this campaign . Blacklisting one publisher doesn't mean it gets blacklisted across other campaigns.
- Whitelist = No matter what you do, this placement is immune, ie: Always advertise on this placement ID in this campaign .
- Suspend = Temporarily block this placement
Building rules that autimatically edit your campaign settings is support. To have this work accurately you can not rely on the APNX Reporting API, as it has delays of 6 hours. You must use the impression tracker module and conversion tracker module. Building a rule example: This Rule says: IF impressions reach 1000, AND clicks are 0, THEN blacklist.
How to generate this example decision tree 🌴 Rule
- set a benchmark such as '>= 1000 impressions'
- click the 'F+' button to add a field
- set AND
- set '<= 0 clicks'
- THEN Blacklist
- Save Rule
You can also add a Group of Fields, which will create a bracket that will get calculated first, following standard arithmetic Orders of Operation
Please see the wiki.
-
Create virtutalenv and install requirements pip install -r requirements.txt python manage.py runserver
-
Migrating tables
python manage.py migrate
-
Shedule jobs python manage.py crontab add On Windows run Job_install.bat
-
To run export data proc manually: python manage.py crontab show
look at task hash code (now there is exact one task)
python manage.py crontab run <task_id>
-
To load all data for the last month, type: python manage.py loadreportdata To load data for specifed day (date format --): python manage.py loadreportdata 2016-05-31
-
Create service table for cache: python manage.py createcachetable rtb_cache_table
-
For create superuser, run python manage.py createsuperuser ======================================
Kmeans modeling has been started, but is not complete. The intention is to predict whether or not any particular placement will stand a good chance of getting a click and conversion.
- Create test set for learning python manage.py mlcreatetestset
- Learn k-means model python manage.py mllearnsavemodel <test_type> <test_name> <advertiser_type> valid test types:
- kmeans
- log - logistic regression valid test names:
- ctr_viewrate (kmeans)
- ctr_cvr_cpc_cpm_cpa (kmeans, log) valid advertiser type:
- ecommerceAd (kmeans)
- leadGenerationAd (kmeans)
- Predict placement and save to database python manage.py mlpredictkmeans <placement_id> <test_type> <test_name> Example for one placement: python manage.py mlpredictkmeans 3898 kmeans ctr_cvr_cpc_cpm_cpa Example for all placements: python manage.py mlpredictkmeans -1 log ctr_cvr_cpc_cpm_cpa Valid test types:
- kmeans;
- log;
- tree - classifier decision tree
- Create csv-file with prediction results python manage.py mlcreatecsvresult
- Check if placement good or bad python manage.py mlcheckplacement <placement_id> <test_type> <test_name> ======================================
- Add new shedule jobs python manage.py crontab add python manage.py crontab show
- To get the data manually python manage.py imp_tracker '2016-10-10 22:00' '2016-10-21 23:00' Impression/Click/Conversion
rtb_impression_tracker — table for impressions from imp_tracker.
rtb_impression_tracker_placement — table for placement and domain from table rtb_impression_tracker.
rtb_impression_tracker_placement_domain — table for placement and domain from table rtb_impression_tracker_placement . Every one placement have your domain or parts domain's level
rtb_click_tracker — table for clicks from imp_tracker. With fields:
CpId -
rtb_conversion_tracker — table for conversions from imp_tracker. With fields
CpId - ${ADV_ID}
AdvId - $ {CP_ID}
CreativeId - ${CREATIVE_ID}
AuctionId - $ {AUCTION_ID}
cron jobs ('* * * * *', 'rtb.crons.placement_state_cron.change_state_placement_by_cron_settings') This task checks placement state in our base every minute and sends all changes to appnexus.
('*/15 * * * *', 'rtb.crons.placement_state_cron.platform_placement_targets') This task updates our placements states (white/black) in datatable with changes of platform_placement_targets value, which we are getting from appnexus. This task runs every 15 minutes.
('* * * * *', 'rtb.crons.placement_state_cron.suspend_state_middleware_cron') Cronjob finds placements with suspend state and changes their state in appnexus to exclude. This task runs every minute.
('0 */4 * * *', 'rtb.crons.imp_tracker_cron.get') This task loadsdata from our impression tracker.
('5 0 * * *', 'rtb.cron.dayly_task') This task loads reports and entities fromAppnexus.
('0 */1 * * *', 'rtb.crons.ml_predict_new_placements_cron.mlPredictNewPlacementsCron') This task predicts GOO/BAD clustersfor new placements.
('0 6 * * 7', 'rtb.crons.ml_refresh_view_full_placements_data_cron.mlRefreshViewFullPlacementsDataCron') This task updates materialized view for ML purposes.
('0 */1 * * *', 'rtb.crons.campaign_rules_cron.checkRulesByCron') Those rules check condition and change placements states
The 'Advertiser must first be configured in the Admin panel. Assign an ad_type
field equals to leadGenerationAd
or videoAds
in database, like so: