agnes-the-ai-analyst/docs/metrics/customers/repeat_purchase_rate.yml
Petr 5a84473213 Add dynamic Business Metrics with sample e-commerce definitions
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
2026-03-10 22:38:44 +01:00

66 lines
2.1 KiB
YAML

- name: repeat_purchase_rate
display_name: Repeat Purchase Rate
category: customers
type: ratio
unit: "%"
grain: monthly
time_column: order_date
table: orders
tables:
- orders
- customers
expression: "COUNT(DISTINCT CASE WHEN order_number > 1 THEN customer_id END) / COUNT(DISTINCT customer_id)"
description: "Percentage of customers who made more than one purchase. Key loyalty and retention indicator. Higher rates signal strong product-market fit and customer satisfaction."
dimensions:
- customer_segment
- acquisition_channel
- product_category
notes:
- "Calculated over a rolling 12-month window by default"
- "Joins orders to customers via customer_id"
- "Order numbering is based on chronological order per customer"
- "Excludes cancelled and fully refunded orders"
synonyms:
- retention_rate
- repurchase_rate
- customer_loyalty_rate
sql: |
WITH customer_orders AS (
SELECT
customer_id,
COUNT(*) AS order_count
FROM orders
WHERE status = 'completed'
AND order_date >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY 1
)
SELECT
ROUND(
COUNT(CASE WHEN order_count > 1 THEN 1 END) * 100.0
/ COUNT(*), 2
) AS repeat_purchase_rate_pct,
COUNT(*) AS total_customers,
COUNT(CASE WHEN order_count > 1 THEN 1 END) AS repeat_customers
FROM customer_orders
sql_by_channel: |
WITH customer_orders AS (
SELECT
o.customer_id,
c.acquisition_channel,
COUNT(*) AS order_count
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.status = 'completed'
AND o.order_date >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY 1, 2
)
SELECT
acquisition_channel,
ROUND(
COUNT(CASE WHEN order_count > 1 THEN 1 END) * 100.0
/ COUNT(*), 2
) AS repeat_rate_pct,
COUNT(*) AS total_customers
FROM customer_orders
GROUP BY 1
ORDER BY 2 DESC