A/B Testing Analytics with Vizly
After an experiment runs, you need to see whether the new variant actually wins. Vizly covers the standard A/B analysis visuals: variant comparison bars, conversion distributions with boxplots, and funnel steps.
Variant comparison
Compare the headline metric across control and treatment variants. A bar chart with the win rate per variant is the simplest view.
import vizly as vz
vz.set_theme("corporate")
variants = [
{"variant": "Control", "conversion": 3.2},
{"variant": "Variant A", "conversion": 4.1},
{"variant": "Variant B", "conversion": 3.6},
]
chart = vz.bar(variants, x="variant", y="conversion", title="Conversion rate %")
chart.render("ab_test.html")
Conversion distributions
Boxplots show how individual users or sessions converted across variants, revealing spread and outliers, not just averages.
import pandas as pd
import vizly as vz
# One row per session with the variant label and conversion value
sessions = [
{"variant": "Control", "conversion": 0.0},
{"variant": "Control", "conversion": 1.2},
{"variant": "Variant A", "conversion": 2.1},
{"variant": "Variant A", "conversion": 3.4},
{"variant": "Variant A", "conversion": 1.8},
]
df = pd.DataFrame(sessions)
chart = vz.boxplot(df, x="variant", y="conversion", title="Conversion by variant")
Funnel across variants
Compare funnel conversion at each step for control versus treatment.
funnel = [
{"stage": "Visits", "control": 1000, "variant_a": 1020},
{"stage": "Signups", "control": 210, "variant_a": 260},
{"stage": "Paid", "control": 61, "variant_a": 88},
]
chart = vz.line(funnel, x="stage", y=["control", "variant_a"], title="Funnel: control vs variant A")
Lift and confidence
Plot the observed lift per segment to see where the variant wins and where it ties.
segments = [
{"segment": "New users", "lift": 4.2},
{"segment": "Returning", "lift": 1.1},
{"segment": "Mobile", "lift": 6.3},
{"segment": "Desktop", "lift": -0.4},
{"segment": "Free tier", "lift": 2.8},
]
chart = vz.bar(segments, x="segment", y="lift", title="Lift % by segment")
Scatter for correlation
Check whether a secondary metric moved with the primary metric, using a scatter plot.
df_scatter = pd.DataFrame({
"conversion": [3.0, 3.4, 3.8, 4.2, 4.6, 5.0],
"engagement": [12, 14, 15, 17, 19, 22],
})
chart = vz.scatter(df_scatter, x="conversion", y="engagement", title="Conversion vs engagement")
Full experiment dashboard
Compose the experiment results into a single review page.
import pandas as pd
import vizly as vz
vz.set_theme("corporate")
chart = vz.page(
charts=[
vz.bar(variants, x="variant", y="conversion", title="Conversion rate %"),
vz.boxplot(df, x="variant", y="conversion", title="Conversion by variant"),
vz.line(funnel, x="stage", y=["control", "variant_a"], title="Funnel comparison"),
vz.bar(segments, x="segment", y="lift", title="Lift % by segment"),
],
title="Experiment dashboard",
)
chart.render("experiment.html")
Tips
| Tip | Detail |
|---|---|
| Boxplots need raw data | vz.boxplot wants one row per observation, not pre-aggregated stats. |
| Lift charts are bars | Per-segment lift reads best as a bar chart, with negative values visible below zero. |
| Funnels are lines here | When comparing two variants across stages, a multi-series line shows both at once. |
| Pair with SQL | Load experiment data straight from a data warehouse with from_sql. See the SQL recipe. |