Aside from the base bid, Google SEM campaign performance can be influenced by contextual signals from the customer. These include but are not limited to: device, location, gender, parental status, household income, etc.
For this post we’ll focus on ad schedule (or intraday) and visualize how time of day and day of week is performing.
Load data
library(tidyverse)
# ANONYMIZED SAMPLE DATA
df <- read_csv("https://raw.githubusercontent.com/Eeysirhc/random_datasets/master/intraday_performance.csv")
Spot check our data
df %>%
sample_n(20)
## # A tibble: 20 x 5
## account day_of_week hour_of_day roas conv_rate
## <chr> <chr> <dbl> <dbl> <dbl>
## 1 Account 3 Tuesday 5 0.509 0.0183
## 2 Account 2 Friday 4 1.11 0.0401
## 3 Account 2 Sunday 11 1.07 0.0309
## 4 Account 3 Saturday 18 1.09 0.0301
## 5 Account 1 Thursday 19 0.303 0.0165
## 6 Account 1 Tuesday 8 0.362 0.0230
## 7 Account 2 Saturday 4 0.722 0.0340
## 8 Account 3 Friday 10 0.653 0.00844
## 9 Account 2 Wednesday 8 0.448 0.0262
## 10 Account 1 Saturday 9 0.858 0.0467
## 11 Account 1 Saturday 18 0.266 0.0136
## 12 Account 1 Saturday 8 0.871 0.0349
## 13 Account 2 Friday 14 0.546 0.0196
## 14 Account 1 Sunday 5 0.0444 0.00889
## 15 Account 3 Wednesday 21 0.530 0.0248
## 16 Account 1 Tuesday 16 0.801 0.0451
## 17 Account 2 Monday 2 0.884 0.0230
## 18 Account 2 Wednesday 19 0.772 0.0275
## 19 Account 3 Monday 21 0.444 0.0367
## 20 Account 1 Tuesday 3 0 0
Clean data
Convert to factors
The day_of_week is a character and time_of_day is a double data type. We need to transform them to factors so they don’t surprise us later.
df_clean <- df %>%
mutate(day_of_week = as.factor(day_of_week),
hour_of_day = as.factor(hour_of_day))
Reorder day of week
If we plot our chart now it won’t be correct because day_of_week will not be arranged properly from Sunday to Saturday format.
levels(df_clean$day_of_week)
## [1] "Friday" "Monday" "Saturday" "Sunday" "Thursday" "Tuesday"
## [7] "Wednesday"
We can quickly refactor with a few lines of code:
df_clean$day_of_week <- factor(df_clean$day_of_week,
levels = c("Saturday", "Friday", "Thursday",
"Wednesday", "Tuesday", "Monday", "Sunday"))
Let’s check to make sure it did what we wanted:
levels(df_clean$day_of_week)
## [1] "Saturday" "Friday" "Thursday" "Wednesday" "Tuesday" "Monday"
## [7] "Sunday"
Plot our results
df_clean %>%
ggplot(aes(hour_of_day, day_of_week, fill = conv_rate)) +
geom_tile(color = 'white') +
scale_fill_gradient2(low = 'grey', mid = 'white', high = 'steelblue') +
labs(y = NULL, x = "Hour of Day", fill = "Conversion Rate") +
theme_minimal()
We can quickly see from this visualization that Tuesday & Wednesdays at midnight the conversion rate is 7% or higher. Conversely, 10AM on Saturday has a conversion rate close to the 0% range.
With this insight we can then amplify or dampen our intraday bid modifiers to improve overall campaign efficiencies.
And for the love of data…
…segment!
df_clean %>%
ggplot(aes(hour_of_day, day_of_week, fill = conv_rate)) +
geom_tile(color = 'white') +
scale_fill_gradient2(low = 'grey', mid = 'white', high = 'steelblue') +
labs(y = NULL, x = "Hour of Day", fill = "Conversion Rate") +
theme_minimal() +
facet_grid(account ~ .)