Data — Analytics & Intelligence
Measure what matters. Every metric should drive a decision. If it doesn't, stop tracking it.
Metric Hierarchy
| Level |
Metric |
Cadence |
| North Star |
1 metric that defines success (e.g., WAU, MRR) |
Weekly |
| Health |
3-5 metrics that predict north star (retention, activation, NPS) |
Weekly |
| Feature |
Per-feature usage, conversion, time-to-value |
Per release |
| Debug |
Granular events for troubleshooting |
On-demand |
Rules:
- North star is singular. Two north stars = zero north stars.
- Vanity metrics (page views, total signups) are not health metrics.
- Every feature ships with tracking. No "we'll add analytics later."
SQL Patterns
Cohort Retention
SELECT
DATE_TRUNC('week', u.created_at) AS cohort_week,
DATE_TRUNC('week', e.created_at) AS activity_week,
COUNT(DISTINCT e.user_id) AS active_users
FROM users u
JOIN events e ON e.user_id = u.id
GROUP BY 1, 2
ORDER BY 1, 2;
Funnel Analysis
WITH steps AS (
SELECT user_id,
MAX(CASE WHEN event = 'signup' THEN 1 END) AS step_1,
MAX(CASE WHEN event = 'onboard_complete' THEN 1 END) AS step_2,
MAX(CASE WHEN event = 'first_action' THEN 1 END) AS step_3,
MAX(CASE WHEN event = 'paid' THEN 1 END) AS step_4
FROM events
WHERE created_at > NOW() - INTERVAL '30 days'
GROUP BY user_id
)
SELECT
COUNT(*) AS total,
SUM(step_1) AS signup,
SUM(step_2) AS onboarded,
SUM(step_3) AS activated,
SUM(step_4) AS converted
FROM steps;
Rolling Averages
SELECT
date,
value,
AVG(value) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS rolling_7d
FROM daily_metrics;
Event Tracking Design
Every event needs:
| Field |
Example |
event_name |
button_clicked, page_viewed, feature_used |
user_id |
Authenticated user |
anonymous_id |
Pre-auth (cookie/device) |
timestamp |
ISO 8601, UTC always |
properties |
{ page: "/pricing", plan: "pro" } |
Naming convention: noun_verb — form_submitted, file_uploaded, subscription_cancelled
Never: click, event1, trackThis, misc
Dashboard Rules
- One question per dashboard. "How is acquisition?" not "Everything."
- Top-left = most important metric. Eye lands there first.
- Comparison always. This week vs last week. This month vs last month.
- No pie charts. Use bar charts. Humans can't compare angles.
- Annotate changes. "Launched feature X" on the timeline.
Data Pipeline Defaults
| Layer |
Tool |
Purpose |
| Collection |
PostHog, Segment, or custom |
Event ingestion |
| Storage |
Postgres or BigQuery |
Queryable warehouse |
| Transform |
dbt or SQL views |
Business logic layer |
| Visualization |
Metabase, Grafana, or PostHog |
Dashboards |
Keep it simple. You don't need Kafka until you have 10M events/day.
1---2name: data3description: (forwward) Designs analytics systems, writes SQL queries, plans event tracking, and builds dashboards for product and user metrics. Triggers on SQL, analytics, dashboards, tracking, data pipelines, or user behavior analysis.4---56# Data — Analytics & Intelligence78Measure what matters. Every metric should drive a decision. If it doesn't, stop tracking it.910## Metric Hierarchy1112| Level | Metric | Cadence |13|-------|--------|---------|14| North Star | 1 metric that defines success (e.g., WAU, MRR) | Weekly |15| Health | 3-5 metrics that predict north star (retention, activation, NPS) | Weekly |16| Feature | Per-feature usage, conversion, time-to-value | Per release |17| Debug | Granular events for troubleshooting | On-demand |1819**Rules:**20- North star is singular. Two north stars = zero north stars.21- Vanity metrics (page views, total signups) are not health metrics.22- Every feature ships with tracking. No "we'll add analytics later."2324## SQL Patterns2526### Cohort Retention27```sql28SELECT29 DATE_TRUNC('week', u.created_at) AS cohort_week,30 DATE_TRUNC('week', e.created_at) AS activity_week,31 COUNT(DISTINCT e.user_id) AS active_users32FROM users u33JOIN events e ON e.user_id = u.id34GROUP BY 1, 235ORDER BY 1, 2;36```3738### Funnel Analysis39```sql40WITH steps AS (41 SELECT user_id,42 MAX(CASE WHEN event = 'signup' THEN 1 END) AS step_1,43 MAX(CASE WHEN event = 'onboard_complete' THEN 1 END) AS step_2,44 MAX(CASE WHEN event = 'first_action' THEN 1 END) AS step_3,45 MAX(CASE WHEN event = 'paid' THEN 1 END) AS step_446 FROM events47 WHERE created_at > NOW() - INTERVAL '30 days'48 GROUP BY user_id49)50SELECT51 COUNT(*) AS total,52 SUM(step_1) AS signup,53 SUM(step_2) AS onboarded,54 SUM(step_3) AS activated,55 SUM(step_4) AS converted56FROM steps;57```5859### Rolling Averages60```sql61SELECT62 date,63 value,64 AVG(value) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS rolling_7d65FROM daily_metrics;66```6768## Event Tracking Design6970Every event needs:7172| Field | Example |73|-------|---------|74| `event_name` | `button_clicked`, `page_viewed`, `feature_used` |75| `user_id` | Authenticated user |76| `anonymous_id` | Pre-auth (cookie/device) |77| `timestamp` | ISO 8601, UTC always |78| `properties` | `{ page: "/pricing", plan: "pro" }` |7980**Naming convention:** `noun_verb` — `form_submitted`, `file_uploaded`, `subscription_cancelled`8182**Never:** `click`, `event1`, `trackThis`, `misc`8384## Dashboard Rules8586- **One question per dashboard.** "How is acquisition?" not "Everything."87- **Top-left = most important metric.** Eye lands there first.88- **Comparison always.** This week vs last week. This month vs last month.89- **No pie charts.** Use bar charts. Humans can't compare angles.90- **Annotate changes.** "Launched feature X" on the timeline.9192## Data Pipeline Defaults9394| Layer | Tool | Purpose |95|-------|------|---------|96| Collection | PostHog, Segment, or custom | Event ingestion |97| Storage | Postgres or BigQuery | Queryable warehouse |98| Transform | dbt or SQL views | Business logic layer |99| Visualization | Metabase, Grafana, or PostHog | Dashboards |100101Keep it simple. You don't need Kafka until you have 10M events/day.