Adstoc Analysis in R
Parag Verma
26th June, 2022
Introduction
Whenever you see an ad on youtube about lets say protein powder, then the effect of that exposure stays with you for some time. Knowingly/Unknowingly, that ad/exposure influences your purchase at some later point in time. This effect which extends several periods after the original exposure is called Adstock. Exposure to an advertisement(or an event) builds awareness in consumers resulting in sales. This awareness is higher if the exposure has been recent and lower if it has been in some distant past.This is the decay effect of adstock and this decay eventually reduces to its base level.
To understand implementation in R, we will look at how we can apply adstock transformation for a simple case
package.name<-c("dplyr","data.table","stats","ggplot2")
for(i in package.name){
if(!require(i,character.only = T)){
install.packages(i)
}
library(i,character.only = T)
}
Step 1: Creating a Simple Illustration
We are creating a dummy data frame with details of daily Sales for 100 products
test.df<-data.frame(Week_Num=c("Week1","Week2","Week3","Week4","Week5","Week6","Week7","Week8"),
Ad_Units=c(1,0,0,0,0,0,0,0))
test.df
Week_Num Ad_Units
1 Week1 1
2 Week2 0
3 Week3 0
4 Week4 0
5 Week5 0
6 Week6 0
7 Week7 0
8 Week8 0
x represents a measure of TV exposure ads. We will now apply adstock transformation to it.
Step 2: Defining the adstock function
Broadly speaking, below are the key considerations while analyzing adstock:
- Carryover Effect
- Exposure in the past influences purchase in future
- Effect of exposure decays with time
- Shape Effect
- Effect of exposure on sales depends upon law of diminishing return
- Changing level of exposure causes changes in sales
Carryover Effects
Let us represent sales at time t as \(y_{t}\) which is influenced by the effect of an ad exposure \(x_{t}\).
\[ \tag{1} y_t = \beta_0 + \beta_1 x_t + \varepsilon_t \] \(\beta_0\) is a constant base value.The above equation incorporates point 1 in the Carryover effect. To include point 2 from carryover effect, lets add one more equation
\[ \tag{2} y_t = \beta_0 + \beta_1 s_t + \varepsilon_t \\ \]
where \(s_t\) represents the effect of:
- current exposure \(x_t\)
- And all previous exposure.\(s_{t-1}\)
It can be mathematically represented as
\[ \tag{3} s_t = x_t + \lambda s_{t-1} \] Lets look at how we can incorporate shape effects into the equation.
Shape Effects
To add shape effects, lets rewrite the above equations as follows \[ \tag{4} y_t = \beta_0 + \beta_1 x_t + \lambda \beta_1 s_{t-1} + \varepsilon_t \] Also the effect of ad exposure decrease/decays with time.So eventually at time t = \(\infty\), effect of the ad exposure reduces to 0. To mimic this decay, an ideal candidate is the logistic function.Hence \(x_t\) is replaced by \(1/1+ e^{-\alpha x_t}\) in the expression for \(s_t\) as shown below.
\[ \tag{5} s_t = \frac{1}{1+ e^{-\alpha x_t}} + \lambda s_{t-1} \]
Again summarising the terms for conslidation.
\(s_{t}\) is effect of current ad exposure at time t and all the ad exposure prior to t
\(s_{t-1}\) is the effect of ad exposure at time t-1
\(x_{t}\) is the level ad exposure at time t
We can see that the above equation (5) is non -linear in \(\lambda\) and \(\alpha\) .\(\lambda\) equal to 0.25 and \(\alpha\) equal to 2 makes the relationship linear and hence we would be using it for our problem.
Step 3: Defining Adstock Function
Lets define the adstock function using filter function from the stats library
adstockTransform <- function(x){
stats::filter( 1/(1+exp(-2*x)), 0.25, method = "recursive")
}
- First part of the argument is an expression in x.It is normally a time series
- Filter coefficient for Auto regressive (AR) or Moving Average Term
- Method = “recursive” indicates that an auto regressive (AR) term is used
Step 4: Applying Adstock Variable
test.df2<-test.df%>%
mutate(Ad_Units_Adstock=adstockTransform(Ad_Units))
test.df2
Week_Num Ad_Units Ad_Units_Adstock
1 Week1 1 0.8807971
2 Week2 0 0.7201993
3 Week3 0 0.6800498
4 Week4 0 0.6700125
5 Week5 0 0.6675031
6 Week6 0 0.6668758
7 Week7 0 0.6667189
8 Week8 0 0.6666797
test.df2$Ad_Units_Adstock<-as.numeric(test.df2$Ad_Units_Adstock)
ggplot(data=test.df2, aes(x=Week_Num, y=Ad_Units_Adstock,group=1)) +
geom_line(linetype = "dashed")+
geom_point(color="red")
We can see that the ad unit of 1 introduced in Week1 decays over a period of 8 weeks and eventually reaches a stable value.Hence using adstock transformation we have introduced the carryover and shape effects into the calculation.
In the next blog, we will implement a market mix model using the concepts discussed in this blog.