Avito is one of the largest classifieds Web sites in the world, with more than 1 billion ad impressions per day. We use many different ad-selling channels: direct sales, ad networks, RTB exchanges, header bidding solutions, and others.
Our goal is to monetise all traffic with maximum efficiency. To do so, we have to decide how impressions should be distributed among demand sources. Through analysis, we have developed a simple formula for maximising online advertising opportunities.
However, demand sources are fundamentally different:
- They may pay different prices for the same impressions.
- Not all demand sources can tell us in advance how much are they willing to pay or if they want to buy impressions.
- Ad networks do not allow setting a minimum impression price.
- Not all ad systems can provide granular statistics.
To solve this problem, we developed an iterative optimisation approach for revenue maximisation.
First, we arrange demand sources into a waterfall. If we are closely integrated with a demand source, and we know for sure that it will buy an impression for a high price, we give it higher priority in the waterfall.
If we do not know the price or do not know if a demand source is willing to buy an impression at all — or if we know that it is buying impressions for a low price — we give it lower priority in the waterfall. Each lower level receives an impression only if it was not sold on a higher level.
Next we choose what floor prices for impressions to set where we can set them. The higher the floor price is, the higher the CPM will show this demand source, but the fewer impressions it will buy.
When we have several ad networks and exchanges, we need to prioritise each one. For example, if ad network shows higher CPM than a non-guaranteed direct sales campaign, we should call ad network first.
The main idea here is to find combination of floor prices and priorities that maximise total performance of all sales channels on a website together. We measure ad selling performance as rCPM — revenue per 1,000 impressions spent (sold and unsold).
To do this, we build a regression model of performance. We choose input parameters (floor prices and networks priorities), split users into several non-overlapping groups by cookie, choose what combination of parameter values will be used for model building, and assign each user group one combination.
Then we run an experiment for several days, measure impressions bought by each demand source and revenue that we got from it in each group, and calculate total ad selling performance in each group. Using data points (1 group – 1 point) we build a regressions model of performance:
rCPM = function (floor price 1, network 1 rate, network 2 rate, ...)
This gives a prediction of the optimal parameter combination. To confirm it, we validate this combination by A/B test. For 50% of our users, we use old demand source parameters, and for another 50% we use the new combination. If total performance of ad selling with new parameters is better, we apply them to 100% of our users.
This process is iterative. It means that in the next stage, we can split our inventory into smaller targeting segments and repeat optimisation in each segment, tuning parameters more and more precisely.
And what are the results?
Last year, after two iterations of optimisation on the desktop version of the Avito.ru Web site, we had a 6% revenue uplift in waterfall. This year, after one iteration of optimisation on the mobile version of the Web site, we had an 8% revenue uplift in waterfall.
This approach proved to be a successful tool for addressing complexity of traffic distribution problems and publisher revenue maximisation.
However, there still remains a question of regular price floors and rate updates, since conditions in the market are constantly changing and values of optimal parameters drift over time.
One possible solution might be to use a multi-armed bandit approach to constantly test new configurations on a small fraction of traffic and to apply optimal values on the largest part.
However, this approach has its own downsides because resulting performance and optimal parameter values depend heavily on the volumes of traffic you send to them. The configuration that maximises revenue on 5% of traffic might be really not optimal for all 100%.