Optimization of an advertising campaign for launching a new product on the market#
Description: The modern world is unthinkable without advertising. Advertising is the engine of progress. When developing and conducting advertising campaigns, companies strive to maximize the effectiveness of their advertising dollars. In this case, the effectiveness of advertising is measured by the degree to which the campaign goals are achieved. The main goals of an advertising campaign can be:
Increase in sales;
Attraction of new clients;
Launch of a new product on the market;
Increasing/maintaining market share or profit level.
When developing and planning an advertising campaigns, it is necessary to take into account many factors that influence the final effectiveness of advertising, namely:
Characteristics of advertising channels (availability, cost, etc.);
Structure and composition of the target audience of each advertising channel;
Conversion rates for various advertising channels;
Limitation of the budget allocated for advertising;
Cost of 1 impression/click;
Localization of the target audience;
The intensity of advertising displays during the day, week;
Marketing activity of competitors;
Mathematical optimization allows you to synchronize all the specified factors and limitations of advertising channels with each other, and determine, among many options, the most effective (from the point of view of campaign goals) plan for investing in advertising.
Tags: Marketing, Advertisement, Deterministic model, Piecewise-linear, mip, ampl-only, cbc
Notebook author: Mikhail Riabtsev <mail@solverytic.com>
Let’s start by downloading the necessary extensions and libraries
# Install dependencies
%pip install -q amplpy pandas
import pandas as pd # Loading panda to work with pandas.DataFrame objects (https://pandas.pydata.org/)
import numpy as np # Loading numpy to perform multidimensional calculations numpy.matrix (https://numpy.org/)
# Google Colab & Kaggle integration
from amplpy import AMPL, ampl_notebook
ampl = ampl_notebook(
modules=["cbc"], # modules to install
license_uuid="default", # license to use
) # instantiate AMPL object and register magics
1. Problem statement#
The company plans to launch a new product on the market of 2 large cities (City1, City2). To inform customers about the new offer, the company is considering the possibility of placing the following types of advertisements:
Type of advertising |
Unit |
Cost 1 unit |
Audience, person |
Conversion, impressions to clicks, % |
---|---|---|---|---|
TV: сhannel#1_time 0PM-5PM |
minute |
1 000 |
18 000 |
3 |
TV: сhannel#1_time 5PM-10PM |
minute |
1 200 |
25 000 |
3 |
Magazine A: cover |
page |
200 |
7 000 |
6 |
Magazine B: inner page |
page |
220 |
8 000 |
6 |
Radio A: time 5PM-10PM |
minute |
200 |
11 000 |
5 |
Radio B: time 5PM-10PM |
minute |
250 |
15 000 |
5 |
Subway: red line |
page to week |
250 |
15 000 |
4 |
WebSite1 |
week |
500 |
10 000 |
15 |
WebSite2 |
week |
400 |
7 000 |
14 |
Billboard: 1place per week |
place |
400 |
3 000 |
3 |
Table.1. Main characteristics of advertisements.
The audience of advertising consists of the following user segments, % of the total audience:
Type of advertising |
14-17 years old |
17-25 years old |
25-40 years old |
40-60 years old |
over 60 |
---|---|---|---|---|---|
TV: сhannel#1_time 0PM-5PM |
7 |
25 |
25 |
27 |
16 |
TV: сhannel#1_time 5PM-10PM |
5 |
18 |
32 |
30 |
15 |
Magazine A: cover |
1 |
5 |
35 |
45 |
14 |
Magazine B: inner page |
5 |
18 |
32 |
30 |
15 |
Radio A: time 5PM-10PM |
15 |
32 |
18 |
30 |
5 |
Radio B: time 5PM-10PM |
14 |
45 |
35 |
5 |
1 |
Subway: red line |
16 |
27 |
25 |
25 |
7 |
WebSite1 |
5 |
18 |
32 |
30 |
15 |
WebSite2 |
15 |
32 |
18 |
30 |
5 |
Billboard: 1place per week |
5 |
18 |
32 |
30 |
15 |
Table.2. Segment composition of advertising audiences, %.
In addition, the audience of advertising media is distributed differently in cities (City1, City2), %:
Type of advertising |
City#1 |
City#2 |
---|---|---|
TV: сhannel#1_time 0PM-5PM |
60 |
40 |
TV: сhannel#1_time 5PM-10PM |
70 |
30 |
Magazine A: cover |
0 |
100 |
Magazine B: inner page |
80 |
20 |
Radio A: time 5PM-10PM |
80 |
20 |
Radio B: time 5PM-10PM |
20 |
80 |
Subway: red line |
0 |
100 |
WebSite1 |
75 |
25 |
WebSite2 |
80 |
20 |
Billboard: 1place per week |
0 |
100 |
Table.3. Distribution of the audience of broadcasters by city, %
When developing an advertising campaign, it is necessary to take into account that the effectiveness of advertisements decreases as the number of views increases. So the first 10 views have the one indicated in Table 1. conversion rate, while the next 10 impressions are 10% less effective, and impressions >20 are 40% less effective.
Data on the reduction rate of advertising effectiveness are given in the following table, %:
Type of advertising |
10-20 views |
>20 views |
---|---|---|
TV: сhannel#1_time 0PM-5PM |
10 |
40 |
TV: сhannel#1_time 5PM-10PM |
10 |
40 |
Magazine A: cover |
5 |
20 |
Magazine B: inner page |
20 |
40 |
Radio A: time 5PM-10PM |
20 |
40 |
Radio B: time 5PM-10PM |
20 |
80 |
Subway: red line |
5 |
40 |
WebSite1 |
10 |
40 |
WebSite2 |
10 |
40 |
Billboard: 1place per week |
10 |
20 |
Table.4. Indicators of decrease in the effectiveness of advertisements, %.
One of the client’s requirements is the need to allocate at least 20% of the budget to TV advertising.
Optimization goals
It is necessary to distribute the advertising budget in such a way as to maximize the following indicators:
Inform the maximum number of people about the release of a new product;
Inform the maximum number of people from the target audience (persons 25-40 years old) about the release of a new product;
Maximize the total number of conversions (purchases) of the target audience.
2. Mathematical formulation of the problem#
Let’s start by describing index sets
\(i\) - list of available types of advertising, for \(i\) = “TV: сhannel#1_time 0PM-5PM”,…, I.
\(i'\) - list of TV types of advertising, \(i' \in\) I. \(i'\) = ‘TV: сhannel#1_time 0PM-5PM’, ‘TV: сhannel#1_time 5PM-10PM’.
\(j\) - segments of advertising audiences, for \(j\) = “14-17 years old”,…, J.
\(j'\) - types of target segment. \(j'\) = “25-40”.
\(k\) - list of cities for broadcasting advertisements, for \(k\) = “City#1”,… K.
\(A_i\) - number of people in the advertising \(i\) audience (Table 1).
\(B_i\) - the cost of displaying 1 unit of advertising \(i\) (Table 1).
\(C_i\) - the conversion rate of advertising \(i\) into targeted customer actions (Table 1).
Parameters
\(D_{ij}\) - the share of various target groups (\(j\)) in the total number of advertising audiences (\(i\)) (Table 2).
\(F_{ij}\) - distribution of advertising audience (\(i\)) between cities (\(j\)) (Table 3).
\(M\) - available advertising budget, $.
\(R_i\) - The coefficient of decrease in advertising effectiveness \(i\) with increasing number impressions (Table 4).
To describe the conditions for changing the effectiveness of advertisements after n number of impressions, we use the concept of Piecewise-Linear Programing. Thus, the objective function of the model is to maximize the number of targeted actions of the ‘25-40’ audience as a result of advertising impressions.
The variables in this case are
\(x_i\): Number of advertisement broadcasts \(i\), for \(i\) = “TV: сhannel#1_time 0PM-5PM”,…, N.
Objective function is
max \( \sum_i^I \sum_k^K \sum_{j'}^J X_i * A_i * D_{ij} * F_{ij} * R_i\) (goal 3)
The constraints are
s.t. \( \sum_i^I X_i * B_i <= M \)
s.t. \( \sum_{i'}^I X_{i'} * B_{i'} <= M * 0.2\)
3. AMPL formulation of the model#
Use %%ampl_eval to evaluate AMPL commands and declarations
%%ampl_eval
reset;
### SETS
set ADVERTISEMENT; # List of all available advertisements
set AUDIENCE; # Broadcaster's audience segments
set SET within AUDIENCE; # Types of target segments
set CITY; # Target cities of the advertising campaign
### PARAMETERS
param Cost {ADVERTISEMENT} >= 0; # Cost of 1 unit of advertising broadcasting for each type of advertising
param Auditoria {ADVERTISEMENT} >= 0; # Internal number of consumer groups for each advertisement
param Conversion {ADVERTISEMENT} >= 0; # Conversion rate of advertisements into purchases
param TargetAudience {ADVERTISEMENT, AUDIENCE} >= 0; # Segment composition of advertising audiences
param City {ADVERTISEMENT, CITY} >= 0; # Distribution of the audience of broadcasters by city
param Money; # Advertising campaign budget, USD
### Indicators of reduction in advertising effectiveness (we use Piecewise-Linear Programing to describe this conception)
param npiece integer >= 1; # Number of efficiency ranges
# Ad effectiveness value in each range
param rate {ad in ADVERTISEMENT, p in 1..npiece} >= 0;
param limit {p in 1..npiece-1} > if p=1 then 0 else limit [p-1];
### VARIABLES
var X {ADVERTISEMENT} >= 0; # Number/duration of each type of advertisement
### OBJECTIVE
maximize TotalAudienceInform: # Inform the maximum number of people about the release of a new product
sum {ad in ADVERTISEMENT, c in CITY, a in AUDIENCE} <<{p in 1..npiece-1} limit[p];
{p in 1..npiece} rate[ad,p]>> X[ad] * Auditoria[ad] * City[ad,c];
maximize TargetAudienceInform: # Inform the maximum number of people from the target audience (persons 25-40 years old) about the release of a new product
sum {ad in ADVERTISEMENT, c in CITY, a in AUDIENCE: a in SET} <<{p in 1..npiece-1} limit[p];
{p in 1..npiece} rate[ad,p]>> X[ad] * Auditoria[ad] * TargetAudience[ad,a] * City[ad,c];
maximize TargetAudienceConversion: # Maximize the total number of conversions (purchases) of the target audience
sum {ad in ADVERTISEMENT, c in CITY, a in AUDIENCE: a in SET} <<{p in 1..npiece-1} limit[p];
{p in 1..npiece} rate[ad,p]>> X[ad] * Auditoria[ad] * TargetAudience[ad,a] * Conversion[ad] * City[ad,c];
### CONSTRAINTS
subject to Budget: # Limit the cost of all advertisements to the allocated budget
sum{ad in ADVERTISEMENT} X[ad] * Cost[ad]<= Money;
subject to Budget_TV: # TV advertising costs must be at least 20% of the allocated budget
sum{ad in ADVERTISEMENT: ad in {'TV: channel#1_time 0PM-5PM', 'TV: channel#1_time 5PM-10PM'}} X[ad] * Cost[ad] >= Money * 0.2;
4. Load data#
%%ampl_eval
data;
param Money = 50000;
param: ADVERTISEMENT: Cost Auditoria Conversion:=
'TV: channel#1_time 0PM-5PM' 1000 18000 0.03
'TV: channel#1_time 5PM-10PM' 1200 25000 0.03
'Magazine A: cover' 200 7000 0.06
'Magazine B: inner page' 220 8000 0.06
'Radio A: time 5PM-10PM' 200 11000 0.05
'Radio B: time 5PM-10PM' 250 15000 0.05
'Subway: red line' 250 15000 0.04
'WebSite1' 500 10000 0.15
'WebSite2' 400 7000 0.14
'Billboard: 1place per week' 400 3000 0.03 ;
set AUDIENCE = '14-17', '17-25', '25-40', '40-60', '>60';
param TargetAudience: '14-17' '17-25' '25-40' '40-60' '>60':=
'TV: channel#1_time 0PM-5PM' 0.07 0.25 0.25 0.27 0.16
'TV: channel#1_time 5PM-10PM' 0.05 0.18 0.32 0.30 0.15
'Magazine A: cover' 0.01 0.05 0.35 0.45 0.14
'Magazine B: inner page' 0.05 0.18 0.32 0.30 0.15
'Radio A: time 5PM-10PM' 0.15 0.32 0.18 0.30 0.05
'Radio B: time 5PM-10PM' 0.14 0.45 0.35 0.05 0.01
'Subway: red line' 0.16 0.27 0.25 0.25 0.07
'WebSite1' 0.05 0.18 0.32 0.30 0.15
'WebSite2' 0.15 0.32 0.18 0.30 0.05
'Billboard: 1place per week' 0.05 0.18 0.32 0.30 0.15 ;
set SET='25-40';
set CITY = City1, City2;
param City: City1 City2:=
'TV: channel#1_time 0PM-5PM' 0.6 0.4
'TV: channel#1_time 5PM-10PM' 0.7 0.3
'Magazine A: cover' 0 1
'Magazine B: inner page' 0.8 0.2
'Radio A: time 5PM-10PM' 0.8 0.2
'Radio B: time 5PM-10PM' 0.2 0.8
'Subway: red line' 0 1
'WebSite1' 0.75 0.25
'WebSite2' 0.8 0.2
'Billboard: 1place per week' 0 1 ;
param npiece default 3;
param rate: 1 2 3:=
'TV: channel#1_time 0PM-5PM' 1 0.9 0.6
'TV: channel#1_time 5PM-10PM' 1 0.9 0.6
'Magazine A: cover' 1 0.95 0.8
'Magazine B: inner page' 1 0.95 0.8
'Radio A: time 5PM-10PM' 1 0.80 0.6
'Radio B: time 5PM-10PM' 1 0.80 0.6
'Subway: red line' 1 0.95 0.6
'WebSite1' 1 0.9 0.6
'WebSite2' 1 0.9 0.6
'Billboard: 1place per week' 1 0.9 0.8 ;
param limit:=
1 10
2 20;
5. Solve problem#
Use %%ampl_eval to evaluate AMPL commands and declarations
%%ampl_eval
option solver cbc; # Choosing a solver
# Defining Output Settings
option show_stats 1; # (1) Show statistical information about the size of the problem. Default 0 (statistics are not displayed)
option display_1col 0; # Data Display Settings
option omit_zero_rows 1; # Hide rows with 0 values. Default (0)
# Selecting an Objective Function (choose one of)
#objective TotalAudienceInform; # goal 1
#objective TargetAudienceInform; # goal 2
objective TargetAudienceConversion; # goal 3
solve; # Solve the model (Objective function TotalAudienceInform)
Substitution eliminates 10 variables.
10 piecewise-linear terms replaced by 30 variables and 10 constraints.
Adjusted problem:
30 variables, all linear
2 constraints, all linear; 36 nonzeros
2 inequality constraints
1 linear objective; 30 nonzeros.
cbc 2.10.10:cbc 2.10.10: optimal solution; objective 32164.7
0 simplex iterations
6. Display the solution#
Use %%ampl_eval
%%ampl_eval
display X, # Show the value of the variables for the resulting solution
{ad in ADVERTISEMENT} X[ad] * Cost[ad], # Show the budget spent on each type of advertising
{c in CITY, ad in ADVERTISEMENT, a in AUDIENCE} X[ad] * Auditoria[ad] * TargetAudience[ad,a] * City[ad,c], # Number of views
sum {c in CITY, ad in ADVERTISEMENT, a in AUDIENCE} X[ad] * Auditoria[ad] * TargetAudience[ad,a] * City[ad,c], # Total number of views
{c in CITY, ad in ADVERTISEMENT, a in AUDIENCE} X[ad] * Auditoria[ad] * TargetAudience[ad,a] * Conversion[ad] * City[ad,c], # Number of conversions
sum {c in CITY, ad in ADVERTISEMENT, a in AUDIENCE} X[ad] * Auditoria[ad] * TargetAudience[ad,a] * Conversion[ad] * City[ad,c]; # Total number of conversions
: X X[ad]*Cost[ad] :=
'Magazine A: cover' 20 4000
'Magazine B: inner page' 20 4400
'Radio B: time 5PM-10PM' 86.4 21600
'TV: channel#1_time 5PM-10PM' 8.33333 10000
WebSite1 20 10000
;
X[ad]*Auditoria[ad]*TargetAudience[ad,a]*City[ad,c] [City1,*,*]
: 14-17 17-25 25-40 40-60 '>60' :=
'Magazine B: inner page' 6400 23040 40960 38400 19200
'Radio B: time 5PM-10PM' 36288 116640 90720 12960 2592
'TV: channel#1_time 5PM-10PM' 7291.67 26250 46666.7 43750 21875
WebSite1 7500 27000 48000 45000 22500
[City2,*,*]
: 14-17 17-25 25-40 40-60 '>60' :=
'Magazine A: cover' 1400 7000 49000 63000 19600
'Magazine B: inner page' 1600 5760 10240 9600 4800
'Radio B: time 5PM-10PM' 145152 466560 362880 51840 10368
'TV: channel#1_time 5PM-10PM' 3125 11250 20000 18750 9375
WebSite1 2500 9000 16000 15000 7500
;
sum{c in CITY, ad in ADVERTISEMENT, a in AUDIENCE} X[ad]*Auditoria[ad]*
TargetAudience[ad,a]*City[ad,c] = 2004330
X[ad]*Auditoria[ad]*TargetAudience[ad,a]*Conversion[ad]*City[ad,c] [City1,*,*]
: 14-17 17-25 25-40 40-60 '>60' :=
'Magazine B: inner page' 384 1382.4 2457.6 2304 1152
'Radio B: time 5PM-10PM' 1814.4 5832 4536 648 129.6
'TV: channel#1_time 5PM-10PM' 218.75 787.5 1400 1312.5 656.25
WebSite1 1125 4050 7200 6750 3375
[City2,*,*]
: 14-17 17-25 25-40 40-60 '>60' :=
'Magazine A: cover' 84 420 2940 3780 1176
'Magazine B: inner page' 96 345.6 614.4 576 288
'Radio B: time 5PM-10PM' 7257.6 23328 18144 2592 518.4
'TV: channel#1_time 5PM-10PM' 93.75 337.5 600 562.5 281.25
WebSite1 375 1350 2400 2250 1125
;
sum{c in CITY, ad in ADVERTISEMENT, a in AUDIENCE} X[ad]*Auditoria[ad]*
TargetAudience[ad,a]*Conversion[ad]*City[ad,c] = 119050
7. Retrieve solution as a pandas dataframe
round(
ampl.var["X"].get_values().to_pandas(),
2)
X.val | |
---|---|
Billboard: 1place per week | 0.00 |
Magazine A: cover | 20.00 |
Magazine B: inner page | 20.00 |
Radio A: time 5PM-10PM | 0.00 |
Radio B: time 5PM-10PM | 86.40 |
Subway: red line | 0.00 |
TV: channel#1_time 0PM-5PM | 0.00 |
TV: channel#1_time 5PM-10PM | 8.33 |
WebSite1 | 20.00 |
WebSite2 | 0.00 |