How to Build a Stripe Revenue Dashboard
Forward Stripe webhook events to GraphJSON and build a live revenue dashboard: MRR, new subscriptions, failed payments and more.
Stripe's own dashboard is built for finance. But if you want revenue graphs next to your product metrics, alerts when payments fail, or raw SQL over your payment events, you need your Stripe data somewhere you can actually play with it.
GraphJSON has a one-click Stripe integration that does exactly that: every Stripe event streams into GraphJSON as JSON, ready to graph.
Step 1: Connect Stripe#
From the Stripe integration page in your GraphJSON dashboard, connect your Stripe account via OAuth, then create a webhook and pick the collection events should land in. That's the entire setup - GraphJSON registers a webhook endpoint with Stripe and every event starts flowing in: charge.succeeded, customer.subscription.created, invoice.payment_failed, refunds, disputes, all of it.
Because events arrive as raw Stripe JSON, you keep everything - amounts, currencies, customer ids, subscription ids - not just the fields someone decided you'd need.
Step 2: Build your graphs#
Open the visualizer and build the metrics that matter:
- Revenue over time - filter to
type = charge.succeededand Sum theamountfield. Stripe amounts are in cents, so divide by 100 in your head (or in SQL) when reading totals. - New subscriptions - count of
customer.subscription.createdevents, compared against last period for the trend arrow. - Churn signal - count of
customer.subscription.deletedover time. - Failed payments - watch
invoice.payment_failedand set an alert so you hear about spikes before your customers tweet about them.
Pin the graphs to a dashboard and you have a live revenue page that updates as charges happen.
Step 3: Go deeper with SQL#
The visualizer covers most needs, but everything is also queryable with ClickHouse SQL in a notebook. For example, a quick look at what your Stripe event stream actually contains:
SELECT JSONExtractString(json, 'type') AS event_type, count() AS total
FROM stripe
GROUP BY event_type
ORDER BY total DESC
LIMIT 20
Since Stripe fields like type are top-level JSON keys, they're directly filterable - and GraphJSON flattens nested payloads by default, so deeper fields like data.object.amount show up as typeahead suggestions in the visualizer too.
Take it further#
Two natural next steps: embed the revenue graphs into an internal admin page, or—if you're feeling open-startup brave—publish selected metrics on a public /open metrics page. Treat revenue embeds as sensitive bearer capabilities and keep the underlying billing system authoritative.

Written by JR
Founder and builder of GraphJSON.