Stripe Revenue Overview: Monitoring & Reporting
Updated October 2026
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
- Active Stripe Account: You'll need administrator or developer access to your Stripe dashboard
- Payment History: At least one month of payment data for meaningful analysis
- API Access: Needed for the Python steps (Steps 1 to 4 each have a code version); the Dashboard instructions for revenue and fees need no code, but the success-rate and monthly-trend steps have no Dashboard version here
- Analytical Mindset: Basic understanding of revenue metrics and financial terminology
What You'll Learn
This tutorial covers four essential revenue metrics:
- Total revenue calculation for any time period
- Processing fee analysis and net revenue determination
- Payment success rate tracking
- 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
- Log into your Stripe Dashboard at
dashboard.stripe.com - Navigate to Home → Payments
- Set your date range to the current month using the date picker in the top-right corner
- 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.
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):
- Standard rate: 2.9% + 30 cents per successful transaction for domestic cards
- International cards: an additional 1.5%
- Currency conversion: an additional 1% when conversion is required
- Disputes: $15.00 for each dispute received
The code below does not apply a formula. It reads the fee Stripe actually recorded on each charge.
Accessing Fee Data in Dashboard
- From your Stripe Dashboard, navigate to Reports → Balance
- Select your desired date range
- Look for the "Fees" row in the breakdown table
- 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.
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:
- Overly aggressive fraud detection rules
- Poor checkout user experience
- Limited payment method options
- Technical integration issues
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:
- Review Radar Rules: Check if Stripe Radar is blocking legitimate transactions
- Analyze Decline Codes: Identify the most common reasons for payment failures
- Test Checkout Flow: Ensure your payment form is user-friendly and error-free
- 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
- Consistent Growth: Steady month-over-month increases indicate healthy business expansion
- Accelerating Growth: Increasing growth rates suggest successful marketing or product improvements
- Seasonal Peaks: Predictable increases during certain months (e.g., holiday season) help with planning
Warning Signs
- Declining Trend: Multiple consecutive months of decreasing revenue require immediate investigation
- High Volatility: Large swings month-to-month may indicate dependence on irregular large transactions
- Stagnation: Flat revenue for several months suggests market saturation or competitive pressure
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:
- Is my net revenue sufficient to cover operating costs? Compare net revenue against your fixed and variable expenses.
- 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.
- 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.
- Is my revenue growing or declining? Understand whether your business momentum is positive or negative.
- 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.
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
- Establish Baselines: Document your current metrics to track future improvements
- Schedule a Report: Run the report script on a schedule to stay informed about revenue changes
- Identify Opportunities: Focus on your lowest-performing metric for immediate improvement
- Share Insights: Distribute revenue reports to stakeholders and team members
Advanced Analysis Techniques
Once you've mastered basic revenue analysis, explore these advanced topics:
- Cohort Analysis: Track revenue by customer acquisition cohort to understand customer lifetime value
- Product Performance: Break down revenue by product or SKU to identify top performers
- Geographic Analysis: Analyze revenue by country or region to inform expansion decisions
- Customer Segmentation: Group customers by behavior patterns and analyze revenue by segment
- Predictive Modeling: Use machine learning to forecast future revenue based on historical patterns
Integration Opportunities
Enhance your revenue analysis by integrating Stripe data with other business tools:
- Accounting Software: Sync Stripe data with QuickBooks or Xero for complete financial tracking
- Data Warehouses: Export Stripe data to Snowflake, BigQuery, or Redshift for advanced analytics
- Business Intelligence: Connect Stripe to Tableau, Looker, or Power BI for visualization
- Customer Data Platforms: Integrate with Segment or mParticle for unified customer views
Optimization Strategies
Use your revenue insights to drive concrete improvements:
- Reduce Failed Payments: If your success rate has dropped against your earlier months, implement retry logic and better error messaging
- Optimize Fee Structure: If processing costs are high, negotiate custom pricing with Stripe for your volume
- Increase Average Transaction Value: Use upselling and cross-selling techniques to boost revenue per transaction
- Improve Revenue Predictability: Convert one-time purchases to subscriptions for stable recurring revenue
Continuous Learning
Stay current with best practices in payment analytics:
- Subscribe to Stripe's blog for updates on new analytics features
- Join payment processing communities to learn from peers
- Attend webinars and conferences focused on e-commerce analytics
- Regularly review and refine your analytical processes
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 →