Replace hardcoded Keboola-specific metrics card in Data Catalog with dynamic Jinja template that renders whatever metric YAMLs exist in docs/metrics/. Add 10 sample e-commerce metric definitions across 4 categories (revenue, customers, marketing, support) that align with the sample data generator tables. Key changes: - MetricParser: new category colors + dynamic sql_* field discovery - _load_metrics_data(): scans docs/metrics/*/*.yml with prod fallback - catalog.html: 240 lines hardcoded HTML -> 35 lines Jinja loop - metric_modal.js: regex-based category class removal, new categories - 21 tests validating YAML schema, parser, and loader
53 lines
1.7 KiB
YAML
53 lines
1.7 KiB
YAML
- name: cost_per_acquisition
|
|
display_name: Cost per Acquisition
|
|
category: marketing
|
|
type: ratio
|
|
unit: USD
|
|
grain: monthly
|
|
time_column: start_date
|
|
table: campaigns
|
|
tables:
|
|
- campaigns
|
|
- customers
|
|
expression: "SUM(spend) / NULLIF(COUNT(DISTINCT new_customer_id), 0)"
|
|
description: "Average cost to acquire one new customer through marketing campaigns. Compares total campaign spend to the number of new customer registrations attributed to those campaigns."
|
|
dimensions:
|
|
- campaign_type
|
|
- channel
|
|
- region
|
|
notes:
|
|
- "Only counts first-time customers (no repeat purchasers)"
|
|
- "Joins campaigns to customers via attribution tracking"
|
|
- "CPA below customer lifetime value indicates sustainable growth"
|
|
synonyms:
|
|
- cpa
|
|
- customer_acquisition_cost
|
|
- cac
|
|
sql: |
|
|
SELECT
|
|
DATE_TRUNC('month', c.start_date) AS month,
|
|
SUM(c.spend) AS total_spend,
|
|
COUNT(DISTINCT cust.customer_id) AS new_customers,
|
|
ROUND(
|
|
SUM(c.spend) / NULLIF(COUNT(DISTINCT cust.customer_id), 0), 2
|
|
) AS cost_per_acquisition
|
|
FROM campaigns c
|
|
LEFT JOIN customers cust
|
|
ON cust.attribution_campaign = c.campaign_id
|
|
AND cust.is_first_purchase = true
|
|
GROUP BY 1
|
|
ORDER BY 1
|
|
sql_by_channel: |
|
|
SELECT
|
|
c.channel,
|
|
SUM(c.spend) AS total_spend,
|
|
COUNT(DISTINCT cust.customer_id) AS new_customers,
|
|
ROUND(
|
|
SUM(c.spend) / NULLIF(COUNT(DISTINCT cust.customer_id), 0), 2
|
|
) AS cpa
|
|
FROM campaigns c
|
|
LEFT JOIN customers cust
|
|
ON cust.attribution_campaign = c.campaign_id
|
|
AND cust.is_first_purchase = true
|
|
GROUP BY 1
|
|
ORDER BY 4
|