Dashboards

Mobile App KPI Dashboard: The Numbers App Founders Actually Watch

6 min read

A mobile app KPI dashboard should show active users, retention, trial-to-paid conversion, active subscriptions, MRR and revenue, in that order of urgency for most subscription apps. There are dozens of other app metrics worth knowing about; only five or six deserve a permanent screen. This page lists the KPIs that matter, says which ones to put on the dashboard, and builds it live from RevenueCat and your own backend, so you can check it from your phone or an office TV.

The mobile app KPIs worth knowing

Grouped by the question each one answers:

Is anyone using it?

  • DAU / MAU. Daily and monthly active users. Define "active" as doing the core action, not opening the app.
  • Stickiness. DAU ÷ MAU. The share of monthly users who show up on a given day. A habit app wants this high; a tax app doesn't care.
  • Session length and sessions per user. Useful for content apps, misleading for utility apps where faster is better.

Do they come back?

  • D1, D7 and D30 retention. The share of a day's new users still active one, seven and thirty days later. The single best measure of whether the product works.
  • Churn. For subscriptions: subscribers lost in a period ÷ subscribers at its start.

Do they pay?

  • Trial starts and trial-to-paid conversion. Where pricing and paywall changes show up first.
  • Active subscriptions. Paying subscriptions right now.
  • MRR. Subscription revenue normalised to a month.
  • Revenue. Everything, including one-off purchases, over a fixed window such as 28 days.
  • ARPU / ARPPU. Revenue per user, and per paying user.

Is it healthy?

  • Crash-free sessions. From your crash reporter.
  • App Store and Google Play rating. Slow-moving, but a drop is worth knowing about the day it starts.

Is acquisition working?

  • Installs, conversion from store page to install, and cost per install. Important if you buy users; mostly noise if you don't.

Which ones go on the dashboard

A dashboard is for what you check daily. For a subscription app before scale, that's six tiles:

TileWidgetWhy
Active users (DAU)KPI with changeUsage, at a glance
D7 retentionKPIThe product-health number
Trial conversionKPIPricing and paywall health
Active subscriptionsKPIPaying users, right now
MRRKPI with goal barRevenue against the next milestone
Revenue, last 28 daysLine chartThe trend behind MRR

Keep the rest in your analytics and subscription tools, where you can slice them.

How the dashboard works

dashboardbase doesn't connect to RevenueCat or your analytics tools directly. Each widget calls an endpoint in your own backend, and the endpoint returns JSON in a fixed shape. That means your RevenueCat secret key stays on your server, and you can mix sources freely: subscriptions from RevenueCat, active users from your own database, one dashboard.

The DAU tile returns this:

response.json dashboardbase.com/s/your-company
{
  "title": "Daily active users",
  "actions": [
    {
      "title": "View Details",
      "type": "link",
      "url": "https://example.com/dau-details"
    }
  ],
  "data": {
    "header": {
      "title": "2,543",
      "subtitle": "vs last month",
      "badge": {
        "text": "+12%",
        "icon": "ArrowUp",
        "color": "Success"
      }
    }
  }
}

Subscriptions from RevenueCat **

RevenueCat's REST API v2 has an overview endpoint that returns the same headline numbers as its dashboard: a metrics array of objects with an id and a value. One call gives you active subscriptions, active trials, MRR and more.**

const PROJECT_ID = process.env.REVENUECAT_PROJECT_ID
const RC_HEADERS = { Authorization: `Bearer ${process.env.REVENUECAT_SECRET}` }

async function overview() {
  const response = await fetch(
    `https://api.revenuecat.com/v2/projects/${PROJECT_ID}/metrics/overview`,
    { headers: RC_HEADERS }
  )
  if (!response.ok) throw new Error(`RevenueCat responded ${response.status}`)
  const { metrics } = await response.json()
  return (id) => metrics.find((m) => m.id === id)?.value ?? 0
}

app.get('/dashboard/app/active-subscriptions', async (req, res) => {
  const metric = await overview()
  const subscriptions = metric('active_subscriptions')
  const trials = metric('active_trials')

  res.json({
    title: 'Active subscriptions',
    actions: [{ title: 'View Details', type: 'link', url: 'https://app.revenuecat.com' }],
    data: {
      header: {
        title: subscriptions.toLocaleString('en-US'),
        subtitle: 'Paying right now',
        badge: { text: `${trials.toLocaleString('en-US')} in trial`, color: 'Blue' },
      },
    },
  })
})

For a trend, the revenue endpoint takes a date range, so you can compare the last 28 days with the 28 before:**

async function revenue(start, end) {
  const params = new URLSearchParams({ start_date: start, end_date: end })
  const response = await fetch(
    `https://api.revenuecat.com/v2/projects/${PROJECT_ID}/metrics/revenue?${params}`,
    { headers: RC_HEADERS }
  )
  if (!response.ok) throw new Error(`RevenueCat responded ${response.status}`)
  return (await response.json()).value
}

const day = (offset) => new Date(Date.now() - offset * 86400000).toISOString().slice(0, 10)

app.get('/dashboard/app/revenue', async (req, res) => {
  const current = await revenue(day(28), day(1))
  const previous = await revenue(day(56), day(29))
  const change = previous > 0 ? Math.round(((current - previous) / previous) * 100) : 0

  res.json({
    title: 'Revenue',
    actions: [{ title: 'View Details', type: 'link', url: 'https://app.revenuecat.com' }],
    data: {
      header: {
        title: `$${Math.round(current).toLocaleString('en-US')}`,
        subtitle: 'Last 28 days',
        badge: {
          text: `${change >= 0 ? '+' : ''}${change}%`,
          icon: change >= 0 ? 'ArrowUp' : 'ArrowDown',
          color: change >= 0 ? 'Success' : 'Danger',
        },
      },
    },
  })
})

Yesterday is the end date on purpose: RevenueCat notes that the most recent day can be partial.** Its Charts & Metrics endpoints share a default limit of 25 requests per minute per project, so set a refresh interval of a few minutes, or cache the response, rather than refreshing every few seconds.**

For more RevenueCat widgets, our RevenueCat dashboard tutorial goes further. Downloads and proceeds straight from Apple are covered in the App Store Connect dashboard guide.

Active users and retention from your own backend

DAU and retention usually live in your own events table or analytics warehouse, not in RevenueCat. The endpoint pattern is the same: query, then return the contract. Protect every endpoint with the workspace secret that dashboardbase sends on each request:

const SECRET = process.env.DASHBOARDBASE_ENDPOINT_SECRET

// Fail at boot rather than serving app data unprotected.
if (!SECRET) throw new Error('DASHBOARDBASE_ENDPOINT_SECRET is not set')

app.use('/dashboard', (req, res, next) => {
  if (req.get('x-dashboardbase-secret') !== SECRET) {
    return res.status(401).json({ error: 'unauthorized' })
  }
  next()
})

Put that middleware before the routes above. When you test a datasource, dashboardbase makes one extra request with every credential stripped and tells you whether the endpoint really refused it.

Check each response in the public endpoint validator before wiring it up, no account needed. If you'd rather not write the handlers yourself, the free Skill teaches Claude Code or Cursor the full widget contract.

Watching it from your phone

For an app founder, the natural home for this dashboard is a phone (what a good KPI app does). dashboardbase has native iOS and Android apps, and any endpoint can return an alert object, say when trial conversion drops below a line you choose, which arrives as a push notification. The team's version can run on an office TV, paired by code without a laptop logged in.

When you don't need this

  • RevenueCat's own dashboard is enough if subscriptions are all you watch and you're happy opening it in a browser.
  • Your analytics tool covers usage if nobody needs DAU and revenue side by side.

The case for a dashboard like this is the combination: subscription numbers and product numbers in one place, on your phone, with alerts you define. Plans start at $9.99/month for 3 seats, with a 14-day free trial.

FAQ

What are the most important mobile app KPIs? Active users, D7 retention, trial-to-paid conversion, active subscriptions, MRR and revenue, for most subscription apps.

What's a good D7 retention? It varies too much by category to give one number. Track your own trend and compare cohorts after each release.

Can I build a mobile app KPI dashboard from RevenueCat? Yes. Its REST API v2 overview and revenue endpoints return the headline numbers; an endpoint in your backend turns them into widgets.**

About the third-party code **

The RevenueCat examples on this page were written against RevenueCat's public REST API v2 documentation as of 6 October 2026. Third-party APIs change: endpoints, field names and rate limits can be renamed or retired after we publish. Treat this code as inspiration and a starting point, and check it against RevenueCat's current API reference before you rely on it.

Sources

Your first dashboard in ten minutes.

Return JSON from an endpoint you already own. We handle the charts, hosting, sharing and the mobile app — free for 14 days.