6 min read

How to Track ARPU in Stripe

ARPU (Average Revenue Per User) is one of the most critical SaaS metrics — it tells you how much revenue each customer generates. In Stripe, your billing data is already there; you just need to query it right. We'll walk through pulling customer and revenue data, then calculating ARPU so you can track how your monetization is trending.

Pull Customers and Revenue Data

Start by fetching your customers and their revenue for a specific time period. You'll use Stripe's API to list customers, then their associated invoices.

Fetch all customers from your Stripe account

Use the Customers API endpoint to retrieve your customer list. You can paginate through results using the limit parameter (max 100 per request) and starting_after for pagination.

javascript
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);

const customers = await stripe.customers.list({
  limit: 100
});

console.log(`Found ${customers.data.length} customers`);
// Use customers.data[0].id for the next step
List all customers from your Stripe account

Sum revenue for each customer in your time period

For each customer, fetch their invoices using the Invoices API filtered by creation date. Sum the amount_paid field for invoices with status: 'paid' only. This gives you the revenue per customer.

javascript
const startDate = Math.floor(new Date('2024-01-01').getTime() / 1000);
const endDate = Math.floor(new Date('2024-03-31').getTime() / 1000);

let totalRevenue = 0;
const customerRevenue = {};

for (const customer of customers.data) {
  const invoices = await stripe.invoices.list({
    customer: customer.id,
    created: {
      gte: startDate,
      lte: endDate
    },
    status: 'paid'
  });

  const customerTotal = invoices.data.reduce(
    (sum, inv) => sum + inv.amount_paid,
    0
  ) / 100; // Convert cents to dollars

  customerRevenue[customer.id] = customerTotal;
  totalRevenue += customerTotal;
}

console.log(`Total revenue: $${totalRevenue}`);
console.log('Revenue by customer:', customerRevenue);
Sum invoice amounts per customer for the time period
Watch out: Stripe returns all amounts in cents, so 100 = $1. Always divide by 100 when displaying currency. Also, filtering by status: 'paid' is critical — unpaid or draft invoices skew your numbers.

Calculate ARPU and Understand the Metric

Divide total revenue by customer count

ARPU is simply total revenue divided by the number of customers. This is your baseline. Most teams track ARPU monthly or quarterly to spot growth trends.

javascript
const activeCustomerCount = Object.keys(customerRevenue).length;
const arpu = totalRevenue / activeCustomerCount;

console.log(`ARPU for Q1 2024: $${arpu.toFixed(2)}`);
console.log(`Breakdown: ${activeCustomerCount} customers, $${totalRevenue} revenue`);

// Store this in your analytics tool or database
const metric = {
  period: 'Q1 2024',
  arpu: parseFloat(arpu.toFixed(2)),
  active_customers: activeCustomerCount,
  total_revenue: totalRevenue,
  calculated_at: new Date().toISOString()
};

console.log(JSON.stringify(metric));
Calculate ARPU and format for storage

Account for refunds and paying-only customers

Decide upfront: is ARPU across all customers or only paying ones? For net revenue, subtract credit notes and refunds. Use stripe.creditNotes.list() to fetch refunded amounts and deduct them from total revenue.

javascript
// Option A: ARPU for paying customers only (exclude $0 revenue)
const payingCustomers = Object.values(customerRevenue).filter(rev => rev > 0);
const arpuPayingOnly = totalRevenue / payingCustomers.length;
console.log(`ARPU (paying customers): $${arpuPayingOnly.toFixed(2)}`);

// Option B: Subtract refunds for net revenue
let netRevenue = totalRevenue;

for (const customer of customers.data) {
  const creditNotes = await stripe.creditNotes.list({
    customer: customer.id,
    created: { gte: startDate, lte: endDate }
  });

  const refunded = creditNotes.data.reduce(
    (sum, note) => sum + note.amount,
    0
  ) / 100;

  netRevenue -= refunded;
}

const arpuNet = netRevenue / activeCustomerCount;
console.log(`ARPU (net of refunds): $${arpuNet.toFixed(2)}`);

// Choose the definition that matches your business model
Adjust ARPU for refunds and non-paying customers
Tip: Cohort ARPU by customer signup date — group customers by the month they joined. This reveals whether newer customers are worth more or less than older cohorts, which is crucial for growth analysis.

Automate ARPU Calculation

Run this on a schedule with a serverless function

Use a cloud function (AWS Lambda, Vercel Cron, or Google Cloud Functions) to calculate ARPU daily or weekly. Store results in a database so you can chart ARPU over time and spot trends.

javascript
// Example: Vercel Cron Job at /api/cron/calculate-arpu.js
export default async function handler(req, res) {
  // Verify the cron secret to prevent unauthorized calls
  if (req.headers['authorization'] !== `Bearer ${process.env.CRON_SECRET}`) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
  const now = new Date();
  const startDate = Math.floor(new Date(now.getFullYear(), now.getMonth(), 1).getTime() / 1000);
  const endDate = Math.floor(now.getTime() / 1000);

  // Insert ARPU calculation logic from above here
  // Then POST results to your metrics database

  const result = { arpu: 125.50, period: `${now.toLocaleString('en-US', { month: 'short' })} ${now.getFullYear()}` };

  await fetch('https://your-api.com/metrics/arpu', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.API_KEY}` },
    body: JSON.stringify(result)
  });

  res.status(200).json({ success: true, arpu: result.arpu });
}
Scheduled function to calculate ARPU automatically

Common Pitfalls

  • Stripe amounts are in cents — forgetting to divide by 100 makes your ARPU 100x too high
  • Including unpaid invoices — always filter by status: 'paid' or you're counting revenue that never landed
  • Not deciding whether ARPU includes non-paying customers — this changes your metric significantly and confuses trend analysis
  • Ignoring refunds and credit notes — net ARPU should subtract refunded amounts, not report gross charges

Wrapping Up

Now you can pull ARPU directly from your Stripe data and track it over time. The key is understanding your customer base's revenue distribution — some customers pay 10x more than others, and ARPU smooths that into one actionable number. If you want to track this automatically across tools, Product Analyst can help.

Track these metrics automatically

Product Analyst connects to your stack and surfaces the insights that matter.

Try Product Analyst — Free