Build a Marketing Attribution Engine with DuckDB: From Multi-Channel Data to SaaS Monetization
The Problem: The “Black Box” of Marketing Data
Your company runs ads on Google, Facebook, TikTok, SEO, and email campaigns simultaneously. Every conversion comes from a combination of multiple touchpoints—but who gets the credit?
Traditional solutions fall into three categories:
- Excel manual matching: 30+ minutes for 100K rows, and error-prone
- Professional attribution tools (Northbeam, Triple Whale): $500-$2,000/month, and data must be exported to external platforms
- Custom-built pipelines: Requires Spark + Airflow + dedicated engineers, 3+ months to deploy
DuckDB offers a completely different approach—doing on a single laptop what previously required a big data platform for attribution analysis.
Data Structure: Reconstructing the User Journey
The first step in attribution analysis is stitching scattered cross-channel user behaviors into a coherent journey. Assume you have the following raw data:
-- Create sample data (simulating multi-channel clicks and conversions)
CREATE TABLE ad_clicks AS
SELECT * FROM (VALUES
('U001', '2026-08-01 08:00:00', 'google', 'cpc', 12.50),
('U001', '2026-08-01 09:30:00', 'facebook', 'cpm', 0.00),
('U001', '2026-08-02 10:00:00', 'tiktok', 'cpv', 0.50),
('U002', '2026-08-01 11:00:00', 'google', 'cpc', 15.00),
('U002', '2026-08-03 14:00:00', 'seo', 'org', 0.00),
('U003', '2026-08-01 07:00:00', 'email', 'flat',0.00),
('U003', '2026-08-01 07:15:00', 'google', 'cpc', 8.00),
('U003', '2026-08-02 09:00:00', 'facebook', 'cpm', 0.00),
('U004', '2026-08-01 16:00:00', 'tiktok', 'cpv', 0.30),
('U004', '2026-08-02 12:00:00', 'google', 'cpc', 11.00),
('U005', '2026-08-01 20:00:00', 'seo', 'org', 0.00)
) AS t(user_id, timestamp, channel, cost_type, cost);
CREATE TABLE conversions AS
SELECT * FROM (VALUES
('U001', '2026-08-02 15:00:00', 299.00),
('U003', '2026-08-02 18:00:00', 149.00),
('U004', '2026-08-03 10:00:00', 499.00)
) AS t(user_id, convert_time, revenue);
Core Technique 1: LATERAL JOIN for Time-Windowed Journeys
The key to attribution analysis is—for each conversion, find all channels the user touched within a time window (e.g., 7 days). DuckDB’s LATERAL JOIN + UNNEST is the perfect tool:
-- Build complete user journey timeline for each conversion
WITH conversion_journey AS (
SELECT
c.user_id,
c.convert_time,
c.revenue,
-- Get all touchpoints within 7 days before conversion
ARRAY_AGG(
ROW(ac.channel, ac.timestamp, ac.cost)
ORDER BY ac.timestamp ASC
) FILTER (
WHERE ac.timestamp BETWEEN c.convert_time - INTERVAL '7' DAY
AND c.convert_time
) AS journey
FROM conversions c
LEFT JOIN ad_clicks ac ON ac.user_id = c.user_id
GROUP BY c.user_id, c.convert_time, c.revenue
)
SELECT * FROM conversion_journey;
The result shows each user’s complete touchpoint sequence—the foundation for any attribution model.
Core Technique 2: Three Main Attribution Models
Last Touch Attribution
The simplest and most common—gives all credit to the last touchpoint.
-- Last Touch Attribution
SELECT
channel,
COUNT(*) AS conversions,
SUM(revenue) AS total_revenue,
SUM(revenue) / COUNT(*) AS avg_order_value
FROM (
SELECT
c.user_id,
c.revenue,
-- Take the most recent touchpoint in the journey
(journey[ARRAY_LENGTH(journey)]).channel AS last_channel
FROM conversion_journey c
) t
GROUP BY channel
ORDER BY total_revenue DESC;
First Touch Attribution
Credit goes to the channel that first introduced the user to the brand.
-- First Touch Attribution
SELECT
channel,
COUNT(*) AS conversions,
SUM(revenue) AS total_revenue
FROM (
SELECT
c.user_id,
c.revenue,
(journey[1]).channel AS first_channel
FROM conversion_journey c
) t
GROUP BY channel
ORDER BY total_revenue DESC;
Linear Attribution
Equal credit to every touchpoint—fair but conservative.
-- Linear Attribution: split revenue evenly across touchpoints
SELECT
jt.channel,
COUNT(*) AS touchpoints,
SUM(jt.revenue / jt.journey_size) AS attributed_revenue
FROM (
SELECT
c.user_id,
c.revenue,
ARRAY_LENGTH(c.journey) AS journey_size,
UNNEST(c.journey) WITH ORDINALITY AS jt(journey_item, position)
FROM conversion_journey c
) t
LATERAL (SELECT (t.jt.journey_item).channel) AS channel_info
GROUP BY jt.channel
ORDER BY attributed_revenue DESC;
Time Decay Attribution (Most Advanced)
Touchpoints closer to the conversion get higher weight—this is the most sophisticated model.
-- Time Decay Attribution (exponential decay, half-life of 3 days)
SELECT
jt.channel,
SUM(
c.revenue * EXP(-0.231 * (c.convert_time - jt.ts)::DOUBLE)
) AS weighted_revenue
FROM conversion_journey c
LATERAL (
SELECT
(item).channel AS channel,
(item).timestamp AS ts,
(item).cost AS cost
FROM UNNEST(c.journey) AS item
) jt
GROUP BY jt.channel
ORDER BY weighted_revenue DESC;
Core Technique 3: Cohort Analysis for Long-Term Value
Attribution isn’t just about single conversions—it’s about understanding the long-term value of users acquired through different channels:
-- Cohort analysis by first-touch channel
WITH first_touch AS (
SELECT
user_id,
MIN(timestamp) AS first_touch_time,
channel AS first_channel
FROM ad_clicks
GROUP BY user_id, channel
),
cohort_data AS (
SELECT
ft.first_channel,
DATE_TRUNC('week', ft.first_touch_time) AS cohort_week,
COUNT(DISTINCT c.user_id) AS users,
SUM(c.revenue) AS total_revenue,
AVG(c.revenue) AS avg_revenue_per_user
FROM first_touch ft
JOIN conversions c ON c.user_id = ft.user_id
GROUP BY ft.first_channel, DATE_TRUNC('week', ft.first_touch_time)
)
SELECT * FROM cohort_data
ORDER BY cohort_week, total_revenue DESC;
Performance Comparison: DuckDB vs Traditional Solutions
| Metric | Excel/VLOOKUP | Spark + Python | DuckDB |
|---|---|---|---|
| 1M row attribution query | 20+ min (often crashes) | Needs cluster setup | < 2 seconds |
| Memory usage | GB-level (Excel limit) | Several GB | ~50 MB |
| Deployment cost | Free | $200+/month (cloud) | Free |
| Learning curve | Simple but error-prone | Complex | SQL-only |
| Embeddability | None | Requires integration framework | Native embedding |
💡 Key Insight: DuckDB’s columnar storage + vectorized execution engine makes it 5-10x faster than Pandas for attribution analysis’s heavy aggregation and window functions, while reducing code volume by 60%.
Complete Runnable Code (Python + DuckDB)
import duckdb
import pandas as pd
# Connect to in-memory database (zero configuration)
con = duckdb.connect(":memory:")
# 1. Create sample data
con.execute("""
CREATE TABLE ad_clicks AS
SELECT * FROM read_csv_auto('ad_clicks.csv');
CREATE TABLE conversions AS
SELECT * FROM read_csv_auto('conversions.csv');
""")
# 2. Run attribution analysis
result = con.execute("""
WITH conversion_journey AS (
SELECT
c.user_id,
c.convert_time,
c.revenue,
ARRAY_AGG(
ROW(ac.channel, ac.timestamp, ac.cost)
ORDER BY ac.timestamp ASC
) FILTER (
WHERE ac.timestamp BETWEEN c.convert_time - INTERVAL '7' DAY
AND c.convert_time
) AS journey
FROM conversions c
LEFT JOIN ad_clicks ac ON ac.user_id = c.user_id
GROUP BY c.user_id, c.convert_time, c.revenue
)
SELECT
jt.channel,
COUNT(*) AS touchpoints,
SUM(c.revenue / ARRAY_LENGTH(c.journey)) AS linear_attribution
FROM conversion_journey c
LATERAL (SELECT (item).channel FROM UNNEST(c.journey) AS item) jt
GROUP BY jt.channel
ORDER BY linear_attribution DESC
""").fetchdf()
print(result)
From Analysis Tool to SaaS Product: Monetization Paths
This is the most critical part—turning this technology into revenue.
Path A: Marketing Attribution SaaS (Recommended)
Wrap the DuckDB attribution engine into a web app for small e-commerce businesses and marketing agencies:
Product Architecture:
┌─────────────────────────────────────────┐
│ SaaS Platform (Streamlit / FastAPI) │
│ ┌───────────┐ ┌───────────┐ │
│ │ Data Upload │ │ Attribution │ │
│ │ CSV/API │ │ Model Select│ │
│ └─────┬─────┘ └─────┬─────┘ │
│ └───────┬───────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ DuckDB Engine │ │
│ │ LATERAL JOIN │ │
│ │ Window Functions│ │
│ └────────┬────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Visual Reports │ │
│ │ Export / Schedule│ │
│ └─────────────────┘ │
└─────────────────────────────────────────┘
Pricing Strategy:
- Free tier: 10K records/month, 5 users
- Professional: $49/month/business, unlimited records, API access
- Enterprise: $199/month, multi-tenant + custom attribution models
Revenue Projection:
- 50 paying customers × $49 = $2,450/month
- 10 enterprise clients × $199 = $1,990/month
- Total: ~$4,440/month
Path B: Project-Based Attribution Consulting
Offer one-time attribution analysis services for e-commerce businesses:
- Single project fee: $1,000-$3,000
- Maintenance: $300/month
- 3-5 projects per month = $5,000+/month
Path C: Embedded Analytics API
Wrap the DuckDB attribution engine as a REST API:
- Pay-per-call pricing: $0.005/call
- 10,000 calls/day = $150/day = $4,500/month
Why DuckDB Instead of Other Solutions?
| Dimension | DuckDB | Spark | Python + Pandas | Commercial Tools |
|---|---|---|---|---|
| Deployment complexity | Zero dependencies | Needs cluster | Moderate | None needed |
| Query performance | Columnar vectorized | Distributed | Memory-limited | Depends on volume |
| Model flexibility | Fully custom SQL | Programmable but complex | Programmable but slow | Fixed models |
| Embeddability | Native embedding | Requires REST service | Needs wrapping | Via API |
| Cost | Free open-source | $200+/month | Free | $500+/month |
| Learning curve | SQL | PySpark | Python | Low |
Monetization Summary
- Fastest path: Build a free attribution analysis tool with Streamlit, promote through Google Ads/Facebook marketing communities, collect emails, then convert to paying users
- Differentiation: Commercial tools are expensive with fixed models; DuckDB enables custom attribution models (e.g., hybrid models combining business rules)
- Technical moat: Package attribution SQL as a DuckDB extension or Python package for reusable technical assets
- Expansion path: Attribution → LTV prediction → Budget allocation optimization, progressively building a complete marketing intelligence platform
📌 Call to Action: Run your first attribution analysis with DuckDB today. Prepare two CSV files (click records + conversion records), run the SQL above, and see how different attribution models change your channel budget recommendations—that’s your first sellable analysis report.
