Let's refine the design of the experiment: in a typical ab test, the
experiment is randomized by user, this means that the group to which the user belongs does not change during the overall experiment. Randomize by visit is possible, but not commonly used: this means giving the same user inconsistent treatment, and may violate the Stable Unit Treatment Value Assumption (SUTVA). The following discussion will be based on the first design.
Here is a toy data:
user_cnt <- 100
## each user can go through the "flow" many number of times
visit_oer_user <- rpois(user_cnt, 10)
## each each have unequal probability to convert
user_conversion_rate <- runif(user_cnt, 0.0, 0.1)
visit_cnt <- sum(visit_oer_user)
## multiple visit of a user have equal probability to convert
visit_conversion_rate <- rep(user_conversion_rate, visit_oer_user)
visit_id <- seq(1, visit_cnt)
user_id <- rep(1:user_cnt, visit_oer_user)
## randomized by user, not visit
user_group <- sample(0:1, user_cnt, replace = TRUE)
visit_group <- rep(user_group, visit_oer_user)
y <- rbinom(visit_cnt, 1, visit_conversion_rate)
df <- tibble(
visit_id,
user_id,
trt = visit_group,
y
)
df
Both options are common used but represent different meanings: conversion-by-visit vs conversion-by-user. If you choose the first option(conversion-by-visit), you need to use more nuanced analyses methods such as bootstrap, delta method or cluster robust standard errors, for violates the assumption of iid. An example in R would like this:
library(sandwich)
library(lmtest)
ols_mod <- lm(y ~ trt, df)
cluster_mod <- coeftest(ols_mod, vcov = vcovCL, cluster = ~user_id)
cluster_mod
t test of coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.097561 0.034858 2.7988 0.005631 **
trt -0.047561 0.039602 -1.2010 0.231182
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
by the second option(conversion-by-user) is easier: aggregate data to user level, apply t test or linear regression.
df_user <- df %>%
group_by(user_id, trt) %>%
summarise(
y = max(y),
.groups = 'drop'
)
ols <- lm(y ~ trt, df)
summary(ols)
Call:
lm(formula = y ~ trt, data = df)
Residuals:
Min 1Q Median 3Q Max
-0.09756 -0.09756 -0.05000 -0.05000 0.95000
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 0.09756 0.02807 3.476 0.000624 ***
trt -0.04756 0.03642 -1.306 0.193031
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.2542 on 200 degrees of freedom
Multiple R-squared: 0.008457, Adjusted R-squared: 0.003499
F-statistic: 1.706 on 1 and 200 DF, p-value: 0.193
references:
Deng, A., Lu, J., & Qin, W. (2021). The equivalence of the Delta method and the cluster-robust variance estimator for the analysis of clustered randomized experiments. arXiv preprint arXiv:2105.14705.
Deng, A., Lu, J., & Litz, J. (2017, February). Trustworthy analysis of online a/b tests: Pitfalls, challenges and solutions. In Proceedings of the Tenth ACM International Conference on Web Search and Data Mining (pp. 641-649).