SaaS Metrics Dashboard Template

A subscription layout that assembles itself from your own billing export. Bring one row per customer carrying a signup date, a plan name, a country, a monthly recurring revenue figure, a seat count, a status and a support ticket count. Drop it and MRR, ARPA, plan mix, cohort and churn panels appear. There is nothing to fill in.

Load the template with sample data

The sample is the fastest way to see whether this layout fits before you go and find your own export. A subscription book across four plans, already normalized to monthly.

Download the sample CSV

The column contract

Eight columns, one row per customer. The single most important line in this table is mrr, and specifically the word monthly in it. Everything else is arrangement; that one is arithmetic.

Column What it holds Role Required What breaks without it
customer_id A stable account key, like CUS-4000 Identifier Required Logo counts become row counts, so a customer on two subscriptions is counted twice in every headline.
signup_date The day the account started paying Date Required Every cohort view goes. Without it the book is a pile with no history, so you cannot see whether newer customers are worth more than older ones.
plan Tier name, like Growth or Enterprise Category Required The plan mix disappears, and with it the answer to which tier is actually carrying the business.
country Billing market Category Optional No geographic revenue split, which is the panel that tells you where a local pricing experiment would pay off.
mrr Monthly recurring revenue for that account Currency Required There is no dashboard. Every headline, every mix panel and every cohort chart is a sum of this column.
seats Licensed users on the account Count Optional Revenue per seat cannot be computed, so discounting stays invisible behind a healthy-looking total.
status active, trial, churned Category Required Churned revenue is counted as live revenue, which inflates the headline by exactly the amount you have lost.
tickets Support requests raised by that account Count Optional You lose the cost-to-serve panels, and the tier that eats support without paying for it stays hidden.

What you get

  • A KPI strip. Active customers, total MRR, implied ARR, ARPA and average seats. ARR is simply MRR times twelve, stated as an implication rather than as a measured number, because that is what it is.
  • MRR by plan. Revenue per tier, largest first. Nearly every SaaS business finds one tier holds most of the money and a different one holds most of the customers.
  • Customers by plan. The count version of the same split, deliberately its own panel so the gap between the two is visible.
  • Signups over time. New accounts per month from the signup date, which is your acquisition rhythm without any attribution attached.
  • MRR by signup cohort. How much revenue each intake month is still contributing. A cohort that arrived big and shrank is visible here without a full retention grid.
  • Status split. Active against trial against churned, weighted by revenue rather than by logo count, so a churned enterprise account does not look like a churned trial.
  • MRR distribution. A histogram of account values. The long right tail is your concentration risk drawn to scale.
  • Seats against MRR. A scatter with the correlation reported. Points well below the trend are accounts paying less per seat than the plan says they should.
  • Tickets by plan. Support load per tier, which is the closest thing to a cost-to-serve panel a billing export can produce.

i. Bring these columns

Pull a subscription list from your billing system, get it to one row per customer, and normalize the money. Renaming headers is trivial. Normalizing MRR is the actual work, and doing it once properly in the export is far better than remembering to mentally divide by twelve every time you look at a chart.

Keep churned accounts in the file with their last MRR intact. Deleting them makes the headline look better and makes the dashboard useless.

ii. Drop the file

Open the dashboard view and drop the CSV. Roles come from the values. mrr holding decimal amounts is money and formats as money everywhere, including in exported chart data. seats is a plain count so it sums and averages. signup_date becomes the time axis with a grain picked from the span, so a two-year book buckets into months rather than producing seven hundred ticks.

None of it is uploaded. For a file that lists every customer you have and exactly what each one pays, that is not a nice-to-have.

iii. Adjust what you need

Switch ARPA from mean to median when one enterprise deal is dragging the average past every real account. Change the cohort grain from months to quarters for a board pack. Filter to active status when you want the live book rather than the whole history, then take the same panels again for comparison.

Export PNG for a slide, SVG when the chart needs to survive a designer, and the aggregated CSV whenever a number is going to be quoted, because investors ask where a figure came from and a chart-data export answers that in one file.

Getting your export into this shape

Billing systems do not export MRR. They export subscriptions, and a subscription has an amount and an interval. Stripe's subscription export gives you Amount, Interval and Interval Count, plus a quantity that usually stands in for seats. Chargebee exports plan unit price with a billing period and a billing period unit. Paddle and Recurly do their own versions of the same thing. In every case the amount is per billing cycle, and cycles differ across rows.

So the first job is one calculated column. Annual amounts divide by twelve. Quarterly divide by three. Semiannual divide by six. Weekly multiply by 52 and divide by 12, which is about 4.33. Monthly passes through. Write the result into mrr and, if it helps you sleep, keep the original amount and interval as extra columns so anyone can check the conversion. Do not leave the raw billing amount in a column called MRR, which is the single most common way a SaaS report ends up overstating revenue by an order of magnitude.

Why it matters more than it sounds: annual plans are usually your largest accounts, so the error is not evenly distributed. Leaving them unnormalized does not inflate everything by the same factor; it inflates the enterprise tier by twelve and leaves the rest alone, which makes the plan mix panel confidently wrong about where your revenue comes from.

Next, quantity and seats. Stripe's quantity is per subscription item, and an account with three items has three rows. Sum the amounts and sum the quantities into one row per customer before you export. While you are there, collapse multiple subscriptions on one account, because a customer with a base plan and an add-on is one logo and two rows, and logo counts matter for churn.

Then currency. Multi-currency books export the charge currency alongside the amount, and summing across them silently produces nonsense. Convert to a single reporting currency at whatever rate your finance team already uses, and put the rate date in the filename so the number is reproducible next quarter.

On status, map your billing system's vocabulary down to three or four values. Stripe alone has active, trialing, past_due, canceled, unpaid, incomplete and paused. Seven statuses produce a seven-slice panel nobody can read. I collapse to active, trial and churned, and treat past_due as active until it actually cancels, because that is how it behaves.

Last, the ticket count. That comes from your helpdesk rather than your billing system, so it needs a join on an account key both systems share. If they do not share one, skip the column. A partially populated ticket count is worse than none, because the blanks will look like quiet, happy customers.

What this template will not do

  • No MRR waterfall. New, expansion, contraction, churn and reactivation need a row per customer per month. A snapshot cannot decompose a movement it never saw.
  • No net revenue retention. NRR compares a cohort's revenue today against its revenue a year ago, and only one of those numbers is in this file.
  • No LTV or payback. Both need acquisition cost and gross margin, neither of which appears in a billing export.
  • Churn is a share, not a rate. You get the proportion of the book sitting in churned accounts. A monthly churn rate needs a denominator per period, which is a history.
  • No usage or engagement. Seats are licensed, not active. A hundred-seat account with four weekly users looks identical here to one that is fully adopted.
  • It will not merge duplicate accounts. The same company under two customer IDs is two customers, and no dashboard can tell that from a CSV.

Frequently Asked Questions

What exactly is the template, if there is no file?

It is a column contract. The layout already exists inside the dashboard builder; what it waits for is a file carrying customer_id, signup_date, plan, country, mrr, seats, status and tickets. When those columns show up, the MRR panels, the plan mix, the seat distribution and the churn split all assemble around them. You never fill anything in, and there is no copy of a workbook to maintain when you launch a new plan.

Why must MRR be normalized to one period?

Because the column is summed, and a sum only means something when every row is in the same unit of time. An annual contract billed at 18000 sitting in the same column as a monthly plan at 150 will contribute a hundred and twenty times its true monthly weight. Divide annual amounts by twelve, quarterly by three, and multiply weekly by roughly 4.33. Write the result into mrr and leave the raw billing amount in a separate column if you still want it. Every headline on the page depends on this one conversion being done.

Should MRR include or exclude discounts and tax?

Exclude tax, include discounts. What you want in the column is the recurring revenue you actually recognize each month from that customer, after any negotiated discount and before sales tax or VAT, which is money you collect for a government rather than money you earn. One-time setup fees, professional services and usage overages do not belong in it either. If you want them, put them in their own column and let the dashboard chart them separately.

Is this a snapshot or a history?

A snapshot, with signup_date giving it a cohort dimension. Each row is a customer as they stand today, carrying the month they arrived. That is enough to show MRR by signup cohort, the plan mix, and how much revenue sits in churned accounts. It is not enough for a proper MRR waterfall, since new, expansion, contraction and churn movements need a row per customer per month. That is a much larger file and a different layout.

How should churned customers be represented?

As rows with status set to churned and their last known MRR still in the mrr column. That gives you the churn share panel and the amount of revenue that has left, which is the number worth staring at. If you zero out the MRR on churned rows instead, the split becomes a count of logos and you lose the value dimension, so a churned enterprise account and a churned trial look identical.

What does the seats column add?

Price realization. MRR divided by seats is revenue per seat, and comparing that across plans is how you discover that the enterprise tier is being sold at growth-tier economics because of volume discounting. The seat distribution also shows where your accounts actually cluster, which is usually not where the pricing page assumes. Without seats you still get every revenue panel, just no way to tell a big account from a well-priced one.

Why is a support ticket count in a revenue contract?

Because cost to serve belongs next to revenue and almost never appears there. Tickets per customer plotted against MRR shows you which plan tier consumes the most support per dollar, and it is frequently the cheapest one. It is optional. If you do not have a per-customer ticket count, leave the column out rather than filling it with zeros, since zeros will read as genuinely quiet accounts.

Can I use this for annual contracts only?

Yes, as long as you still divide by twelve into the mrr column. An all-annual book is a perfectly normal shape for this template, and the panels behave the same way. Some teams prefer to think in ARR; if that is you, multiply the headline by twelve when you present it, but keep the column monthly so a future mixed-term book does not break the arithmetic silently.

Does my customer list leave the browser?

No. Everything is parsed and aggregated in the tab, with no upload endpoint behind the page and no request carrying your rows. A subscription export is a list of who pays you and how much, which is close to the most sensitive file a small company owns. If you would rather not have account names in it at all, export only the customer IDs; nothing in this layout needs a company name.

Try it on a sample book

Four plans, several markets, already normalized to monthly. Judge the layout before you touch your own billing export.

Load the template with sample data