ds@mcpanalytics.aiEmail your data and your question and get an answer about your own data, with the method shown.Email your data and question. Get an answer.

Stripe Revenue Overview: Monitoring & Reporting

Updated October 2026

Category: Stripe Analytics | Reading Time: 10 minutes

Introduction to Revenue Overview in Stripe

This tutorial produces four outputs from your Stripe data: total revenue, processing fees and net revenue, payment success rate, and monthly revenue trend. The Dashboard shows the first two; the Python steps compute all four from the Stripe API. Understanding your revenue metrics is fundamental to running a successful online business. Whether you're processing hundreds or millions of dollars in payments, knowing exactly how much revenue you're generating, what you're paying in processing costs, and how efficiently your payment system is performing can make the difference between growth and stagnation.

Stripe provides powerful analytics tools, but many business owners struggle to extract actionable insights from their payment data. This tutorial will walk you through a comprehensive revenue analysis, showing you exactly how to answer critical questions about your business performance.

By the end of this guide, you'll be able to confidently track your total monthly revenue, calculate your exact processing costs, monitor payment success rates, and identify revenue trends that can inform your business strategy.

Prerequisites and Data Requirements

Before diving into revenue analysis, ensure you have the following:

Required Access and Tools

What You'll Learn

This tutorial covers four essential revenue metrics:

  1. Total revenue calculation for any time period
  2. Processing fee analysis and net revenue determination
  3. Payment success rate tracking
  4. Revenue trend identification (a look at past months; this tutorial does not forecast)

Time Commitment

Complete this tutorial in approximately 30 minutes.

Step 1: Calculate Your Total Revenue This Month

Your total revenue represents the gross amount of money your business has processed through Stripe. This is the starting point for all revenue analysis.

Using the Stripe Dashboard

  1. Log into your Stripe Dashboard at dashboard.stripe.com
  2. Navigate to Home → Payments
  3. Set your date range to the current month using the date picker in the top-right corner
  4. Look for the "Volume" metric, which shows your gross payment volume

Using the Stripe API

To track revenue in code, you can query the Stripe API directly. The month is read as a half-open range, from the first moment of the month up to but not including the first moment of the next, in UTC, so December needs no special case and no last-day timestamp is needed. Only charges with status succeeded count as revenue, and the totals cover one currency:

import stripe
from datetime import datetime, timezone

stripe.api_key = 'sk_test_your_api_key'

CURRENCY = 'usd'  # these totals cover one currency; for several, see the multi-currency tutorial

def month_bounds(year, month):
    """First moment of a month and of the next month, in UTC (the end is exclusive)."""
    start = datetime(year, month, 1, tzinfo=timezone.utc)
    if month == 12:
        end = datetime(year + 1, 1, 1, tzinfo=timezone.utc)
    else:
        end = datetime(year, month + 1, 1, tzinfo=timezone.utc)
    return start, end

def charges_in_month(year, month):
    """Every charge created in the calendar month, with its balance transaction (which holds the fee)."""
    start, end = month_bounds(year, month)
    charges = stripe.Charge.list(
        created={'gte': int(start.timestamp()), 'lt': int(end.timestamp())},
        expand=['data.balance_transaction'],
        limit=100
    )
    return [c for c in charges.auto_paging_iter() if c.currency == CURRENCY]

today = datetime.now(timezone.utc)
month_charges = charges_in_month(today.year, today.month)

# Gross revenue: charges that succeeded. Amounts are in the smallest unit (cents for USD).
succeeded = [c for c in month_charges if c.status == 'succeeded']
total_revenue = sum(c.amount for c in succeeded) / 100

print(f"Total Revenue This Month (month to date): ${total_revenue:,.2f}")

Expected Output

You should see a dollar amount representing your total processed payments for the month so far. The figures in this and the following Expected Output blocks come from a synthetic Stripe account generated for this tutorial, not from a real business, so your numbers will differ. The synthetic date is January 10, 2025, so this is ten days of data:

Total Revenue This Month (month to date): $21,851.49

What This Metric Tells You

Total revenue indicates your business's gross earning power. However, this is not your take-home amount. You'll need to subtract processing fees and other costs to determine net revenue.

Pro Tip: Compare complete months, or compare the month so far with the same number of days of the previous month. A month in progress always looks smaller than a finished one, so comparing it with a full month shows a decline that is not real.

Step 2: Calculate Your Processing Fees

Processing fees are the costs Stripe charges for handling your payments. Understanding these fees is crucial for calculating your true profitability.

Understanding Stripe's Fee Structure

Stripe's published pricing depends on your country and plan. For example, Stripe's US pricing page lists the following (as shown when this tutorial was written; check your own country and plan):

The code below does not apply a formula. It reads the fee Stripe actually recorded on each charge.

Accessing Fee Data in Dashboard

  1. From your Stripe Dashboard, navigate to Reports → Balance
  2. Select your desired date range
  3. Look for the "Fees" row in the breakdown table
  4. This shows your total processing costs for the period

Calculating Fees Programmatically

Each charge has a balance transaction with the fee Stripe took. The code in Step 1 already fetched it with the charge, so the fees below belong to exactly the charges counted as revenue. Refunds are subtracted using each charge's refunded amount to date, so refunds are attributed to the month of the original charge:

def pct(part, whole):
    """A percentage, or 'n/a' when there is nothing to divide by (an empty period)."""
    return f"{part / whole * 100:.2f}%" if whole else "n/a"

# Fees: the fee Stripe recorded on each included charge's balance transaction
total_fees = sum(c.balance_transaction.fee for c in succeeded) / 100

# Refunds: amount_refunded is the total refunded so far on each charge, partial refunds included
total_refunds = sum(c.amount_refunded for c in succeeded) / 100

# Net revenue = gross revenue - refunds - processing fees
net_revenue = total_revenue - total_refunds - total_fees

print(f"Total Refunds: ${total_refunds:,.2f}")
print(f"Total Processing Fees: ${total_fees:,.2f}")
print(f"Net Revenue: ${net_revenue:,.2f}")
print(f"Fees as a Share of Gross Revenue: {pct(total_fees, total_revenue)}")

Expected Output

Total Refunds: $563.02
Total Processing Fees: $770.54
Net Revenue: $20,517.93
Fees as a Share of Gross Revenue: 3.53%

Interpreting Your Fee Rate

In this example, fees are 3.53% of gross revenue. Compare your own rate with the rates on your pricing page: international cards and currency conversion raise it, and the fixed per-transaction part weighs more when payments are small. A rate well above what your pricing page implies is a reason to look at your mix of cards and currencies.

Important: Refunds reduce revenue, and the fee on the original charge may not come back, so check your Stripe pricing terms and read the fee off the balance transaction. The code above subtracts refunds, so net revenue is gross revenue minus refunds minus fees. A report by the date the refund was issued (Issue 5 below) will show a different refund total than this one.

Step 3: Monitor Your Payment Success Rate

Payment success rate measures how many attempted payments actually succeed. A low success rate indicates potential problems with your checkout flow, payment methods, or fraud detection settings.

Why Success Rate Matters

A falling success rate points to problems with your checkout flow, payment methods or fraud settings. Judge your rate against your own earlier months rather than a fixed threshold. A failed payment is revenue at risk, not necessarily lost revenue, because some customers retry or pay another way. Common causes of failures include:

Calculating Success Rate

This counts charge attempts: a charge that succeeded or failed. A customer who fails twice and then pays counts as two failures and one success. To measure payments instead, group the charges by payment intent, as in the failed payment recovery tutorial.

# A payment attempt is a charge that either succeeded or failed (a pending charge has no outcome yet)
successful_payments = sum(1 for c in month_charges if c.status == 'succeeded')
failed_payments = sum(1 for c in month_charges if c.status == 'failed')
total_attempts = successful_payments + failed_payments

print(f"Total Payment Attempts: {total_attempts}")
print(f"Successful Payments: {successful_payments}")
print(f"Failed Payments: {failed_payments}")
print(f"Success Rate: {pct(successful_payments, total_attempts)}")

Expected Output

Total Payment Attempts: 347
Successful Payments: 337
Failed Payments: 10
Success Rate: 97.12%

Taking Action on Low Success Rates

If your success rate drops or is lower than you expect, investigate these areas:

  1. Review Radar Rules: Check if Stripe Radar is blocking legitimate transactions
  2. Analyze Decline Codes: Identify the most common reasons for payment failures
  3. Test Checkout Flow: Ensure your payment form is user-friendly and error-free
  4. Expand Payment Methods: Consider adding alternative payment methods popular in your customer regions

For statistical analysis of payment patterns and optimization strategies, check out our guide on A/B testing statistical significance to scientifically test checkout improvements.

Step 4: Analyze Revenue Trends Over Time

Understanding how your revenue changes over time helps you identify growth patterns, seasonal variations, and potential problems before they become critical.

Analyzing Monthly Trends

To identify a trend you need several months of data. This example uses the six most recent complete calendar months; the current month is left out because it is not finished, and each month is read with the same half-open UTC range as Step 1:

import pandas as pd

def last_complete_months(n, now):
    """The n calendar months before the current one, oldest first, as (year, month)."""
    months, year, month = [], now.year, now.month
    for _ in range(n):
        month -= 1
        if month == 0:
            year, month = year - 1, 12
        months.append((year, month))
    return months[::-1]

months_data = []
for year, month in last_complete_months(6, today):
    ok = [c for c in charges_in_month(year, month) if c.status == 'succeeded']
    months_data.append({
        'month': f"{year}-{month:02d}",
        'revenue': sum(c.amount for c in ok) / 100
    })

# Create DataFrame and calculate growth
df = pd.DataFrame(months_data)
df['growth_rate'] = df['revenue'].pct_change() * 100

print(df.round(2).to_string(index=False))

# Average of the monthly growth rates (the first month has no previous month)
avg_growth = df['growth_rate'].mean()
print(f"\nAverage Monthly Growth Rate: {avg_growth:.2f}%")

Expected Output

  month  revenue  growth_rate
2024-07 46425.41          NaN
2024-08 49881.36         7.44
2024-09 47981.11        -3.81
2024-10 53862.04        12.26
2024-11 56349.69         4.62
2024-12 61240.90         8.68

Average Monthly Growth Rate: 5.84%

The average growth rate is the plain average of the five monthly growth rates (the first month has no previous month), not a compound rate, and the revenue column is gross revenue before refunds and fees.

Interpreting Revenue Trends

Look for these patterns in your data:

Positive Indicators

Warning Signs

These are measurements of past months. The tutorial does not forecast future revenue, and six months of totals are too few to separate a trend from seasonality.

Interpreting Your Revenue Overview Results

Now that you've gathered all your revenue metrics, it's time to synthesize this information into actionable insights.

Creating a Revenue Summary

Combine your metrics into one printout:

# Comprehensive Revenue Summary
print("="*50)
print("REVENUE OVERVIEW (MONTH TO DATE)")
print("="*50)
print(f"Gross Revenue:        ${total_revenue:>12,.2f}")
print(f"Refunds:              ${total_refunds:>12,.2f}")
print(f"Processing Fees:      ${total_fees:>12,.2f}")
print(f"Net Revenue:          ${net_revenue:>12,.2f}")
print(f"Fee Share of Gross:   {pct(total_fees, total_revenue):>13}")
print(f"Payment Success Rate: {pct(successful_payments, total_attempts):>13}")
print(f"Payment Attempts:     {total_attempts:>13,}")
print(f"Avg Transaction:      " + (f"${total_revenue / successful_payments:>12,.2f}" if successful_payments else "          n/a"))
print(f"Last Full-Month Growth:{df['growth_rate'].iloc[-1]:>12.2f}%")
print("="*50)

Expected Output

==================================================
REVENUE OVERVIEW (MONTH TO DATE)
==================================================
Gross Revenue:        $   21,851.49
Refunds:              $      563.02
Processing Fees:      $      770.54
Net Revenue:          $   20,517.93
Fee Share of Gross:           3.53%
Payment Success Rate:        97.12%
Payment Attempts:               347
Avg Transaction:      $       64.84
Last Full-Month Growth:        8.68%
==================================================

Key Questions to Ask

Use your revenue overview to answer critical business questions:

  1. Is my net revenue sufficient to cover operating costs? Compare net revenue against your fixed and variable expenses.
  2. Are my processing fees in line with my pricing plan? Compare your fee share with the rates on your Stripe pricing page and look into any gap.
  3. How much revenue is at risk from failed payments? Failed payments are revenue at risk, not necessarily lost, since some customers retry or pay another way. Track the value of failures and how many later succeed.
  4. Is my revenue growing or declining? Understand whether your business momentum is positive or negative.
  5. What's my average transaction value? This helps you understand customer purchasing behavior and set marketing targets.

Automating Your Revenue Analysis

Manual revenue analysis is valuable for learning, but automation ensures you stay consistently informed about your business performance.

Setting Up Scheduled Reports

Create a Python script that you schedule to send yourself a revenue summary each week. It reuses charges_in_month from Step 1 and reports the month to date:

import os
import smtplib
from email.mime.text import MIMEText

def generate_revenue_report(year, month):
    """Month-to-date revenue report, built from the same charges as the steps above"""
    charges = charges_in_month(year, month)
    ok = [c for c in charges if c.status == 'succeeded']
    failed = sum(1 for c in charges if c.status == 'failed')

    gross = sum(c.amount for c in ok) / 100
    refunds = sum(c.amount_refunded for c in ok) / 100
    fees = sum(c.balance_transaction.fee for c in ok) / 100

    return f"""Revenue Report - {datetime.now(timezone.utc):%Y-%m-%d}

Gross Revenue: ${gross:,.2f}
Refunds: ${refunds:,.2f}
Processing Fees: ${fees:,.2f}
Net Revenue: ${gross - refunds - fees:,.2f}
Payment Attempts: {len(ok) + failed} ({failed} failed)
"""

def send_email_report(report):
    """Send report via email"""
    msg = MIMEText(report)
    msg['Subject'] = 'Weekly Stripe Revenue Report'
    msg['From'] = '[email protected]'
    msg['To'] = '[email protected]'

    # Configure your SMTP settings (keep credentials out of the code)
    with smtplib.SMTP('smtp.gmail.com', 587) as server:
        server.starttls()
        server.login(os.environ.get('SMTP_USER', 'your_email'), os.environ.get('SMTP_PASSWORD', 'your_password'))
        server.send_message(msg)

# Run weekly using cron or scheduled task
if __name__ == '__main__':
    now = datetime.now(timezone.utc)
    report = generate_revenue_report(now.year, now.month)
    send_email_report(report)
    print("Report sent successfully")
Report sent successfully

Schedule this script using cron (Linux/Mac) or Task Scheduler (Windows) to run every Monday morning.

Run It on Your Own Stripe Export

Export your payments from Stripe as a CSV and upload it at MCP Analytics. The analysis runs a revenue overview on your file and shows the result with the method used. You choose the columns; nothing connects to your Stripe account.

Try it on your data

Common Issues and Solutions

Here are solutions to the most common problems encountered when analyzing Stripe revenue:

Issue 1: API Rate Limiting

Problem: Your script fails with "Rate limit exceeded" errors when processing large amounts of data.

Solution: Retry with exponential backoff, and fetch in smaller date windows if you keep hitting limits:

import time

def fetch_with_retry(api_call, max_retries=3):
    """Fetch data with exponential backoff"""
    for attempt in range(max_retries):
        try:
            return api_call()
        except stripe.RateLimitError:
            wait_time = (2 ** attempt)
            print(f"Rate limited. Waiting {wait_time}s...")
            time.sleep(wait_time)
    raise Exception("Max retries exceeded")

Issue 2: Incomplete Data Due to Pagination

Problem: Your revenue calculations are incorrect because you're not retrieving all transactions.

Solution: Always use auto_paging_iter() to ensure you retrieve all records (auto-pagination reference). Plain iteration over the list covers only the first page:

# Wrong - only gets first 100 charges
charges = stripe.Charge.list(limit=100)
total = sum(c.amount for c in charges)

# Correct - gets all charges
charges = stripe.Charge.list(limit=100)
total = sum(c.amount for c in charges.auto_paging_iter())

Issue 3: Currency Confusion

Problem: Revenue numbers don't match what you see in the dashboard.

Solution: Remember that Stripe amounts are in the smallest currency unit. Divide by 100 for two-decimal currencies such as USD, but not for zero-decimal currencies such as JPY (Stripe's currency reference):

# Stripe returns amounts in the smallest currency unit
amount = 4999            # e.g. a charge.amount in USD: 4999 = $49.99
dollar_amount = amount / 100  # $49.99

# Zero-decimal currencies such as JPY have no minor unit: 500 means 500 yen, so do not divide
yen_amount = 500

Issue 4: Timezone Discrepancies

Problem: Your monthly totals don't match the dashboard because of timezone differences.

Solution: Stripe's created values are Unix timestamps, which are UTC-based, so the code in Step 1 builds its month boundaries in UTC. If you compare with a report grouped in another time zone, charges near the start or end of a month can land in different months. Use UTC boundaries, and an exclusive end:

from datetime import datetime, timezone

# Use UTC timezone
first_day = datetime(2024, 12, 1, tzinfo=timezone.utc)
end_exclusive = datetime(2025, 1, 1, tzinfo=timezone.utc)  # use created={'gte': ..., 'lt': ...}

Issue 5: Refunds Skewing Revenue Data

Problem: Your net revenue doesn't account for refunds, making it inaccurate.

Solution: Step 2 subtracts each charge's refunded amount. If you want refunds by the date they were issued instead, list the refunds directly:

# Refunds by the date the refund was issued (the Dashboard's view), not by the charge date
start, end = month_bounds(2024, 12)
refunds = stripe.Refund.list(
    created={'gte': int(start.timestamp()), 'lt': int(end.timestamp())},
    limit=100
)

total_refunds_issued = sum(r.amount for r in refunds.auto_paging_iter() if r.status == 'succeeded' and r.currency == CURRENCY) / 100
print(f"Refunds issued in December 2024: ${total_refunds_issued:,.2f}")
Refunds issued in December 2024: $1,342.06

Issue 6: Test vs Live Mode Confusion

Problem: You're seeing zero revenue or test data in your reports.

Solution: Ensure you're using your live API key, not test key:

# Test mode (for development)
stripe.api_key = 'sk_test_...'

# Live mode (for production)
stripe.api_key = 'sk_live_...'

# Never commit API keys to version control!

Next Steps with Stripe Revenue Analysis

Congratulations! You now have a comprehensive understanding of how to analyze your Stripe revenue. Here's how to build on this foundation:

Immediate Actions

  1. Establish Baselines: Document your current metrics to track future improvements
  2. Schedule a Report: Run the report script on a schedule to stay informed about revenue changes
  3. Identify Opportunities: Focus on your lowest-performing metric for immediate improvement
  4. Share Insights: Distribute revenue reports to stakeholders and team members

Advanced Analysis Techniques

Once you've mastered basic revenue analysis, explore these advanced topics:

Integration Opportunities

Enhance your revenue analysis by integrating Stripe data with other business tools:

Optimization Strategies

Use your revenue insights to drive concrete improvements:

Continuous Learning

Stay current with best practices in payment analytics:

Conclusion

Mastering Stripe revenue analysis is essential for data-driven business decisions. By following this tutorial, you've learned how to calculate total revenue, understand processing costs, monitor payment success rates, and identify revenue trends, all critical components of effective financial management.

The skills you've developed here form the foundation for increasingly sophisticated revenue analytics. Whether you keep your own scripts or upload an export (see Run It on Your Own Stripe Export above), consistent revenue reviews will help you identify opportunities, address problems early, and make informed decisions.

Remember: revenue analysis isn't a one-time activity. Establish a regular cadence, weekly or monthly, to review these metrics, track changes over time, and continuously optimize your payment processes for maximum business growth.

Start implementing these practices today, and you'll have the insights needed to drive sustainable revenue growth for your business.

Explore more: Stripe Analytics: all tools, tutorials, and guides →

Your turn

Bring your own data and the question you actually need answered.

MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai