I have conducted an experiment to test a hypothesis that changing the layout of my website would increase overall user engagement with the website. I therefore assigned 50% of the website visitors to see the "regular" layout (i.e., Control group) whereas the other 50% would see the new layout (i.e., Experiment group).
To measure the user engagement in each group, I chose the week-over-week metric: how many – out of those visiting the website in week i – have re-visited in week i+1.
Therefore, to conclude whether my layout change increases user engagement, my independent variable is Group (Experiment/Control) and dependent variable is $$ \frac{visitor-count-of-those-who-visited-in-both-week-i-AND-week-(i+1)}{visitor-count-of-those-who-visited-in-week-(i)} $$
I let the experiment run for 5 weeks. This means that I have 4 pairs of weeks as my data:
- week 0 -> week 1
- week 1 -> week 2
- week 2 -> week 3
- week 3 -> week 4
My question is – how should I test the difference between Control vs. Experiment groups?
Reproducible Example
Let's consider the following data as the results of my experiment:
pair_of_weeks | group | user_count_week_i | user_count_both_week_i_and_week i+1 |
---|---|---|---|
0->1 | control | 3774 | 3169 |
0->1 | experiment | 3580 | 3031 |
1->2 | control | 4722 | 3661 |
1->2 | experiment | 4526 | 3609 |
2->3 | control | 5099 | 3790 |
2->3 | experiment | 4968 | 3746 |
3->4 | control | 5130 | 3810 |
3->4 | experiment | 4985 | 3792 |
Calculating the Week-Over-Week per each pair_of_weeks
using R:
library(tibble)
library(dplyr)
library(ggplot2)
library(scales)
df <-
tibble::tribble(
~pair_of_weeks, ~group, ~user_count_week_i, ~user_count_both_week_i_and_week_i_plus_one,
"0->1", "control", 3774L, 3169L,
"0->1", "experiment", 3580L, 3031L,
"1->2", "control", 4722L, 3661L,
"1->2", "experiment", 4526L, 3609L,
"2->3", "control", 5099L, 3790L,
"2->3", "experiment", 4968L, 3746L,
"3->4", "control", 5130L, 3810L,
"3->4", "experiment", 4985L, 3792L
)
df |>
mutate(week_over_week_prop = user_count_both_week_i_and_week_i_plus_one / user_count_week_i) |>
mutate(labeling = paste0(percent(week_over_week_prop, 0.1),
"\n",
"(",
comma(user_count_week_i),
"->",
comma(user_count_both_week_i_and_week_i_plus_one),
")"
)
) |>
ggplot(aes(x = pair_of_weeks, y = week_over_week_prop, fill = group)) +
geom_col(position = position_dodge(width = 0.8)) +
geom_text(aes(label = labeling), position = position_dodge(width = 0.8), vjust = -0.1, size = rel(3)) +
expand_limits(y = c(0, 1) )
Now, what if I want to conclude whether the difference between Control vs Experiment groups is "significant"? One way is to examine each pair of weeks:
library(broom)
week_0_1 <- prop.test(x = c(3169, 3031), n = c(3774, 3580)) |> broom::tidy()
week_1_2 <- prop.test(x = c(3661, 3609), n = c(4722, 4526)) |> broom::tidy()
week_2_3 <- prop.test(x = c(3790, 3746), n = c(5099, 4968)) |> broom::tidy()
week_3_4 <- prop.test(x = c(3810, 3792), n = c(5130, 4985)) |> broom::tidy()
bind_rows(week_0_1,
week_1_2,
week_2_3,
week_3_4) |>
tibble::add_column(pair_of_weeks = c("0-1", "1-2", "2-3", "3-4"), .before = 0)
#> # A tibble: 4 × 10
#> pair_of_weeks estimate1 estimate2 statistic p.value parameter conf.low
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 0-1 0.840 0.847 0.620 0.431 1 -0.0239
#> 2 1-2 0.775 0.797 6.57 0.0104 1 -0.0390
#> 3 2-3 0.743 0.754 1.49 0.223 1 -0.0279
#> 4 3-4 0.743 0.761 4.29 0.0384 1 -0.0350
#> # ℹ 3 more variables: conf.high <dbl>, method <chr>, alternative <chr>
If we use the pval of 0.05 as the threshold for "significance", we can see that only pairs of weeks "1-2" and "3-4" are below pval of 0.05.
Therefore I have no decisive conclusion. Is there another way for me to test the results, overall, for the entire span of the experiment (as opposed to breaking down to pairs of weeks)?
Also important to mention that there is a heavy, natural, overlap in the identity of the visitors/users of the webpage, both within and between pairs of weeks.