6 min read

How to Visualize Expansion Revenue in Stripe

Expansion revenue—money from existing customers upgrading, adding seats, or moving to higher tiers—is often scattered across your subscription data. Stripe tracks every change, but pulling expansion metrics requires querying subscription history and comparing billing amounts. We'll show you how to extract this data and build a clear picture of your growth from within.

Extract Expansion Events from Stripe

Start by capturing subscription changes. You'll compare previous and current billing amounts to identify expansion.

Fetch active subscriptions and their current billing amounts

Use the Subscriptions API to list all active subscriptions. Extract the current unit_amount from each subscription's line items—this is your baseline.

javascript
const stripe = require('stripe')('sk_test_...');

const subscriptions = await stripe.subscriptions.list({
  limit: 100,
  status: 'active'
});

subscriptions.data.forEach(sub => {
  const currentAmount = sub.items.data[0].price.unit_amount / 100; // Convert cents to dollars
  console.log(`Subscription ${sub.id}: $${currentAmount}/month`);
});
List all active subscriptions and their current monthly billing amounts

Listen for subscription updates via webhooks

Instead of polling, listen for customer.subscription.updated events. Stripe includes previous_attributes in the event payload, so you can immediately detect when a billing amount increased and calculate the expansion amount.

javascript
const handleWebhook = (event) => {
  if (event.type === 'customer.subscription.updated') {
    const current = event.data.object;
    const previous = event.data.previous_attributes;
    
    if (previous.items) {
      const oldAmount = previous.items[0].price?.unit_amount || 0;
      const newAmount = current.items.data[0].price.unit_amount;
      
      if (newAmount > oldAmount) {
        const expansion = (newAmount - oldAmount) / 100;
        console.log(`Expansion detected: +$${expansion}`);
        // Store in your database for later aggregation
      }
    }
  }
};
Detect billing increases from subscription update events

Distinguish expansion from new logo and churn

Only count increases from existing subscriptions as expansion. Use the subscription's customer ID and created timestamp to exclude brand-new subscriptions (new logo) and canceled ones (churn). Filter for subscriptions older than 30 days to avoid counting initial onboarding fee increases.

javascript
const thirtyDaysAgo = Math.floor(Date.now() / 1000) - (30 * 24 * 60 * 60);
const qualifyingSubscriptions = subscriptions.data.filter(sub => {
  return sub.created < thirtyDaysAgo && sub.status === 'active';
});

// Now compare billing amounts for these subscriptions to prior month
const expansionRevenue = qualifyingSubscriptions.reduce((total, sub) => {
  const currentAmount = sub.items.data[0].price.unit_amount / 100;
  const priorAmount = getPriorMonthAmount(sub.id); // Fetch from your records
  const expansion = Math.max(0, currentAmount - priorAmount);
  return total + expansion;
}, 0);

console.log(`Expansion revenue: $${expansionRevenue}`);
Calculate expansion for mature subscriptions only
Watch out: Stripe's previous_attributes only includes fields that changed. If quantity increased but price stayed flat, check the quantity field instead of unit_amount. Also, prorated charges appear on invoices, not subscriptions, so query invoices if you need exact dollar amounts customers were billed.

Calculate Expansion Metrics

Turn raw expansion amounts into actionable metrics that show growth trends.

Group expansion by month

Aggregate expansion events by calendar month or billing cycle. Store this in your database or a simple JSON structure so you can trend it over time.

javascript
// Group expansion events by month
const expansionByMonth = {};

expansionEvents.forEach(event => {
  const month = new Date(event.timestamp * 1000).toISOString().split('T')[0].substring(0, 7); // YYYY-MM
  if (!expansionByMonth[month]) {
    expansionByMonth[month] = 0;
  }
  expansionByMonth[month] += event.expansion_amount; // Already in dollars
});

console.log(expansionByMonth);
// Output: { '2025-01': 3200, '2025-02': 4500, '2025-03': 5100 }
Sum expansion revenue by month

Calculate expansion rate (expansion MRR ÷ prior month MRR)

Expansion rate shows what percentage of last month's recurring revenue came from existing customers. Divide this month's expansion by last month's total MRR. A 10% expansion rate means you added $10 of recurring revenue for every $100 of existing MRR.

javascript
function calculateExpansionRate(currentMonthExpansion, priorMonthMRR) {
  return (currentMonthExpansion / priorMonthMRR) * 100;
}

const march2025Expansion = 5100;  // From aggregation above
const february2025MRR = 48000;    // $48k MRR at start of March
const rate = calculateExpansionRate(march2025Expansion, february2025MRR);
console.log(`March expansion rate: ${rate.toFixed(2)}%`); // Output: 10.63%
Expansion rate as a percentage of prior month MRR
Tip: Align your expansion calculation to your billing cycle, not calendar months. If you bill on the 15th, group expansion from the 15th of one month to the 14th of the next, not Jan 1 to Jan 31.

Visualize Expansion Over Time

Build a simple chart to spot trends and communicate growth to stakeholders.

Format data for charting

Convert your monthly expansion data into an array that a charting library can consume. Include the month label and the dollar amount.

javascript
const chartData = Object.entries(expansionByMonth).map(([month, amount]) => ({
  month,
  expansion: amount,
  formattedAmount: `$${(amount / 1000).toFixed(1)}k` // For display
}));

console.log(chartData);
// Output: [
//   { month: '2025-01', expansion: 3200, formattedAmount: '$3.2k' },
//   { month: '2025-02', expansion: 4500, formattedAmount: '$4.5k' },
//   { month: '2025-03', expansion: 5100, formattedAmount: '$5.1k' }
// ]
Format expansion data for a charting library

Render a bar or line chart

Use Chart.js, Recharts, or any charting library to display expansion revenue as a bar or line chart. A bar chart is clearer for month-over-month comparisons; a line chart is better for spotting trends.

javascript
// Example with Chart.js
const ctx = document.getElementById('expansionChart').getContext('2d');
const chart = new Chart(ctx, {
  type: 'bar',
  data: {
    labels: chartData.map(d => d.month),
    datasets: [{
      label: 'Expansion Revenue (USD)',
      data: chartData.map(d => d.expansion),
      backgroundColor: '#171717',
      borderRadius: 4
    }]
  },
  options: {
    responsive: true,
    plugins: {
      title: { display: true, text: 'Monthly Expansion Revenue' },
      legend: { display: false }
    },
    scales: {
      y: { beginAtZero: true }
    }
  }
});

module.exports = chart;
Render a bar chart of expansion revenue by month
Tip: If you also want to show expansion rate on the same chart, add a second dataset with a secondary y-axis. This lets you spot whether expansion is growing faster or slower relative to your overall revenue.

Common Pitfalls

  • Confusing expansion revenue with upsell or net revenue. Expansion is only from existing customers increasing their spend—don't include new logo revenue or revenue from add-on features sold separately.
  • Forgetting that Stripe timestamps are Unix epoch in seconds, not milliseconds. Convert with new Date(event.created * 1000) before grouping by date.
  • Not filtering out one-time charges or prorated amounts. Subscription unit_amount is the recurring monthly charge; one-time setup fees or mid-cycle prorations live on invoices, not subscriptions.
  • Double-counting downgrades. Filter for increases only (newAmount > oldAmount) so a customer dropping from $500 to $300 doesn't offset another customer's upgrade.

Wrapping Up

Expansion revenue is your fastest-growing, most profitable revenue stream—it costs less to land than new customers and signals product stickiness. By pulling subscription changes from Stripe, calculating monthly expansion metrics, and visualizing the trend, you'll identify which customer segments and niches are expanding fastest. 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