Case study 03 · Marketing analytics · Tableau + Python

Which marketing dollar actually comes back.

Six months, 93 campaigns, five channels, one budget meeting. Clicks flatter every channel; return does not. This analysis re-ranks the channel mix on revenue per dollar, then settles a copy debate with a properly-read A/B test.

RoleAnalysis, experiment readout
ToolsTableau · Python · SQL
Dataset93 campaigns · Jan to Jun 2026
Live · recomputes in your browser

The channel mix, judged on return.

Filter to a single channel and the spend, return, and efficiency numbers recompute across all 93 campaigns.

Channel
Spend
Revenue
attributed, six months
ROAS
Cost per conversion
Spend vs revenue by month
Revenue compounds while spend stays roughly flat
SpendRevenue
Where the budget goes
Share of six-month spend
Return per dollar by channel
The ranking the budget meeting actually needed
Cost per conversion by channel
Same story from the cost side
The experiment

Two subject lines walk into an inbox.

The welcome email's subject line had defenders on both sides, so we split 49,192 new subscribers and let the data referee. Variant B wins at every stage of the funnel, and the gap is far too large to be luck.

Funnel rates by variant
Open, click, and conversion as a share of sends
The verdict
Two-proportion z-test on conversion
Conversion lift, B over A
z statistic

Ship Variant B
What the data says

Three findings, one recommendation.

01

Email is the quiet compounder.

Lowest spend of any paid channel, highest return per dollar by a wide margin. It never wins the clicks leaderboard, which is exactly why judging channels on clicks was starving the best performer.

02

Display buys impressions, not customers.

Display's return per dollar runs at a fraction of the blended average across all six months. It has a role at the top of the funnel, but at this budget share it is an expensive way to be seen and forgotten.

03

The subject line was worth real money.

Variant B lifted conversion roughly 31% over Variant A, with a z statistic near 4.6. On this list size that is hundreds of extra conversions a year from changing one sentence, which is the cheapest growth lever in the whole report.

Recommendation

Shift a quarter of the Display budget into Email and Paid Search, hold Paid Social steady, and adopt Variant B's concrete, task-led subject line style across the lifecycle program. Re-read the mix quarterly with the same ROAS lens so the ranking stays honest as volumes shift.

The Tableau + Python build

Same analysis, production tooling.

Tableau carries the channel dashboard with a channel parameter driving every sheet. Python owns the experiment readout, because a significance test belongs in code you can re-run, not a screenshot.

The experiment readout, in Python
import numpy as np
from scipy import stats

# conversions / sends per variant
a = np.array([512, 24612])
b = np.array([668, 24580])

p1, p2 = a[0]/a[1], b[0]/b[1]
p  = (a[0]+b[0]) / (a[1]+b[1])
se = np.sqrt(p*(1-p) * (1/a[1] + 1/b[1]))
z  = (p2 - p1) / se
pval = 2 * (1 - stats.norm.cdf(abs(z)))

# z = 4.63, p < 0.001 -> ship Variant B
The SQL behind the channel view
-- channel efficiency, the ranking chart
SELECT
    channel,
    SUM(spend_usd)               AS spend,
    SUM(revenue_usd)             AS revenue,
    SUM(revenue_usd)
        / NULLIF(SUM(spend_usd), 0) AS roas,
    SUM(spend_usd)
        / NULLIF(SUM(conversions), 0) AS cpa
FROM campaign_performance
GROUP BY channel
ORDER BY roas DESC;
← Prev · Card fraud monitoring All case studies