Marketing¶
A digital-marketing performance warehouse spanning paid, organic, and email channels. Campaigns run across channels and target audience segments. Spend gets a CDC audit (attribution restated as conversion windows close). A subset of awareness campaigns is on an A/B treatment targeted at conversion rate specifically (per-metric lift). Seasonality follows the Q4 holiday window.
What it produces¶
| Table | Type | Grain | Rows (default) | Notes |
|---|---|---|---|---|
dim_date |
dim | per_period | 24 | 24 monthly periods, Jan 2023 – Dec 2024 |
dim_campaign |
dim | per_entity (+ SCD2) | 95–285 | 95 campaigns, expanded by SCD2 campaign-phase moves |
dim_audience |
dim | per_reference | 6 | lookalike, prospecting, retargeting, ... |
dim_creative_format |
dim | per_reference | 6 | video, static_image, carousel, story, native, collection |
fct_campaign_performance |
fact | per_entity_per_period (CDC) | 2,280 | spend, impressions, CTR, creative quality |
fct_funnel |
fact | per_entity_per_period | 2,280 | conversion, bounce, leads + funnel-stage bucket |
fct_revenue |
fact | per_entity_per_period | 2,280 | revenue, ROI |
evt_click |
event | variable (proportional) | ~18,000 | scaled 8× click_through_rate |
evt_campaign_pause |
event | variable (threshold) | 10–40 | conversion_rate below 0.1 for 3 consecutive periods |
95 entities across seven segments: awareness_builder (15, half in a
per-metric treatment cohort), paid_burst (18), seasonal_promo (20),
delayed_breakthrough (12), viral_compound (10), end_of_life (10),
retarget_revival (10).
Features exercised¶
- Per-metric treatment —
awareness_buildersegment 50/50 split. Treatment arm runs a new audience-targeting model at period 8 withtarget_metric: conversion_rate. Only conversion_rate shifts; every other metric stays byte-identical to control draws. - Seasonality — Q4 holiday lift Nov–Dec (+0.45), summer slowdown Jun–Aug (-0.10), post-holiday January dip (-0.25). Larger holiday lift than other templates — marketing is the most seasonally amplified domain.
- Causal lag —
leads_generatedfollowsimpressionswith delay 1. - Correlations —
click_through_rate driven_by impressions,conversion_rate driven_by click_through_rate,bounce_rate opposes conversion_rate, plus explicitrevenue 0.62 conversion_rate,roi 0.48 revenue,leads_generated related click_through_rate. This produces a coherent funnel — impressions move CTR moves conversions moves revenue. - SCD2 —
campaign_phaseondim_campaigntrackingrevenuewith thresholds[0.30, 0.70](seed / scale / mature). - CDC —
fct_campaign_performancecarries audit columns for attribution-window-close spend restatements. - Bucket column —
funnel_stageonfct_funnelwith four bands:cold/warming/engaged/converted. - Pool-driven event reason —
evt_campaign_pause.reasonis apool.pause_reasoncolumn, so each campaign's pause reasons stay consistent with its segment's pool. - Multi-phase archetypes —
growth > spike_then_crash @ 12,flat > growth @ 10,decline > flat > growth @ 6 @ 16. - Lifecycle stages —
launch/ramping/performing/winningonconversion_rate. - Quality injection — null injection on ad_spend (4%), late arrivals on clicks (3%), duplicate rows on funnel (1%).
- Events — one proportional (
evt_click) and one threshold (evt_campaign_pause, withbelowrather thanabove).
Use it¶
Common customizations¶
Strengthen the Q4 seasonal lift¶
Default Q4 strength is +0.45. To model a Black-Friday-heavy retailer:
Use time-varying correlations instead of a static funnel¶
Default has constant connections across the window. To model a funnel
that decouples after a tracking change at period 12:
config = create(
# ... metrics, segments, etc. unchanged ...
connections=[
"conversion_rate driven_by click_through_rate",
"revenue 0.62 conversion_rate",
],
connection_phases=[
{
"start_period": 0,
"end_period": 11,
"connections": ["conversion_rate driven_by click_through_rate"],
},
{
"start_period": 12,
"end_period": 23,
"connections": ["conversion_rate hints_at click_through_rate"],
},
],
)
Add a holdout for an ROI prediction model¶
Holdout combines cleanly with the template's quality issues — corrupted
rows are sliced by date_key so both train and holdout carry their
share of injections. You don't need to drop the quality block first:
Where it shines¶
- ATE recovery exercises — the per-metric treatment on
awareness_builderis the cleanest teaching surface for "did your inference correctly identify which metric was treated?" The manifest'streatment_cohortsrecords the answer. - Funnel-decay decomposition — the
seasonal_decompositionandregression_pairs_globalmanifest sections let students recover per-pair OLS coefficients against the engine's ground truth. - Marketing-mix modeling teaching —
causal_lagplusdecay_windowonleads_generatedreproduces adstock-style dynamics; the capability ships out of the box (see Connecting metrics to extend the template).