Analytics Stack — Self-Hosted
Components
- Supabase — single source of truth (Postgres + Auth + Edge Functions)
- Metabase — self-hosted BI, dashboards, scheduled email reports
- Sync scripts (Python, cron-driven) — pull from each source nightly
Data Sources → Supabase Tables
| Source | Sync Method | Table |
|---|---|---|
| GHL (per sub-account) | Public API + webhook | ghl_contacts, ghl_opportunities, ghl_conversations |
| Signal House | REST pull | sms_events |
| Instantly | API pull | email_events, email_campaigns |
| Stripe | Webhook + backfill | stripe_charges, stripe_subscriptions |
| Plaid | Webhook | bank_transactions, cc_transactions |
| Meta Ads | API pull | meta_ad_insights |
Why Plaid
Feeds Claude with live bank + CC data. Use cases:
- Payroll decisioning ("can I make payroll this Friday?")
- P&L categorization
- Cash runway alerts
- Subscription audit (find forgotten SaaS)
Metabase Dashboards (core set)
- Agency P&L — Stripe MRR vs expenses (Plaid) by month
- Funnel — leads → booked → showed → closed, per client
- SMS Health — delivery %, reply %, opt-out % per sending number
- Ad ROAS — Meta spend vs Stripe revenue by UTM
- Client Scorecard — one page per client, monthly PDF emailed
Not Chosen (and why)
- Looker Studio — query caching is slow, no version control
- Power BI — Windows-centric, bad for remote team
- Segment — $$ + event model doesn't fit the batch SMS world