Stripe Multi-Currency Revenue Analysis Guide
Introduction to Multi-Currency Revenue Analysis
Understanding your revenue breakdown by currency is essential for businesses operating in international markets. Whether you're a SaaS company serving customers globally, an e-commerce platform with international shipping, or a digital marketplace connecting buyers and sellers across borders, knowing where your money comes from—and in what currencies—provides critical insights for strategic planning.
Multi-currency revenue analysis helps you answer crucial questions: What percentage of your revenue comes from international customers? Which markets are growing fastest? Are you properly hedging against currency fluctuations? How do transaction fees vary across different currencies? This tutorial will walk you through the complete process of analyzing your Stripe revenue by currency, from data extraction to actionable insights.
By the end of this guide, you'll be able to segment your revenue streams, understand your international exposure, identify opportunities for market expansion, and make data-driven decisions about pricing strategies in different regions. Similar to how AI-first data analysis pipelines can automate complex analytical workflows, this structured approach will help you systematically understand your multi-currency revenue landscape.
Prerequisites and Data Requirements
What You'll Need Before Starting
Before diving into multi-currency revenue analysis, ensure you have the following:
- Active Stripe Account: You'll need administrator or developer access to your Stripe account with permission to view payment data and export reports.
- Multi-Currency Enabled: Your Stripe account should be configured to accept payments in multiple currencies. If you're only accepting one currency, you'll need to enable additional currencies in your Stripe settings first.
- Historical Transaction Data: At least 3-6 months of transaction history for meaningful analysis. The more data you have, the better your trend analysis will be.
- Basic Technical Skills: Familiarity with data exports, CSV files, and basic spreadsheet operations. If you plan to use code examples, knowledge of Python or JavaScript is helpful but not required.
- Exchange Rate Data: Access to historical exchange rates for accurate currency conversion (we'll cover free sources in this tutorial).
Understanding Stripe's Currency Structure
Stripe stores currency information in several key fields:
- Currency Code: The three-letter ISO 4217 currency code (e.g., USD, EUR, GBP)
- Amount: The transaction amount in the smallest currency unit (cents for USD, pence for GBP)
- Presentment Currency: The currency shown to the customer
- Settlement Currency: The currency deposited to your bank account
Understanding the difference between presentment and settlement currency is crucial. A customer might pay in EUR (presentment), but you might receive USD (settlement) after Stripe's conversion.
Step-by-Step Guide to Multi-Currency Revenue Analysis
Step 1: Access Stripe Dashboard and Export Payment Data
The first step in analyzing your multi-currency revenue is extracting comprehensive payment data from Stripe. Here's how to do it properly:
- Log into your Stripe Dashboard at
dashboard.stripe.com - Navigate to Payments in the left sidebar
- Click the Export button in the top-right corner
- Select your date range (recommend at least 90 days for trend analysis)
- Choose All columns to ensure currency data is included
- Select CSV format for easier manipulation
- Click Export and download the file when ready
Expected Output: You should receive a CSV file named something like stripe-payments-2024-01-01-to-2024-12-31.csv containing all payment records with currency information.
Pro Tip: Using the Stripe API
For ongoing analysis or larger datasets, consider using the Stripe API to automate data extraction:
const stripe = require('stripe')('sk_test_your_key');
// Fetch payments with currency information
const payments = await stripe.charges.list({
limit: 100,
created: {
gte: Math.floor(Date.now() / 1000) - (90 * 24 * 60 * 60), // Last 90 days
},
});
// Group by currency
const currencyBreakdown = {};
payments.data.forEach(charge => {
const currency = charge.currency.toUpperCase();
if (!currencyBreakdown[currency]) {
currencyBreakdown[currency] = {
count: 0,
total: 0
};
}
currencyBreakdown[currency].count++;
currencyBreakdown[currency].total += charge.amount;
});
console.log(currencyBreakdown);
Step 2: Prepare Your Data for Analysis
Raw Stripe export data requires cleaning and structuring before analysis. Follow these preparation steps:
- Open the exported CSV in your preferred tool (Excel, Google Sheets, or a programming environment)
- Identify key columns: Look for
Currency,Amount,Status,Created, andFeecolumns - Filter for successful payments: Remove refunded, failed, or pending transactions by filtering where
Status = "succeeded" - Normalize currency codes: Ensure all currency codes are uppercase and consistent
- Convert amounts: Stripe stores amounts in smallest units. Convert to decimal by dividing by 100 (for most currencies)
Here's a Python example for data preparation:
import pandas as pd
# Load the Stripe export
df = pd.read_csv('stripe-payments.csv')
# Filter for successful payments only
df = df[df['Status'] == 'succeeded']
# Normalize currency codes
df['Currency'] = df['Currency'].str.upper()
# Convert amounts from cents to dollars/euros/etc
df['Amount_Decimal'] = df['Amount'] / 100
# Convert fees
df['Fee_Decimal'] = df['Fee'] / 100
# Calculate net revenue
df['Net_Revenue'] = df['Amount_Decimal'] - df['Fee_Decimal']
print(f"Total transactions: {len(df)}")
print(f"Unique currencies: {df['Currency'].nunique()}")
print(f"Date range: {df['Created'].min()} to {df['Created'].max()}")
Expected Output: A cleaned dataset showing metrics like:
Total transactions: 3,847
Unique currencies: 12
Date range: 2024-01-01 to 2024-12-31
Step 3: Calculate Revenue by Currency
Now that your data is clean, calculate aggregate metrics for each currency. This step reveals your revenue distribution and identifies your primary markets.
Key metrics to calculate for each currency:
- Total revenue (sum of all successful transactions)
- Transaction count (number of payments)
- Average transaction value (total revenue / transaction count)
- Total fees paid
- Net revenue (after fees)
# Group by currency and calculate metrics
currency_analysis = df.groupby('Currency').agg({
'Amount_Decimal': ['sum', 'count', 'mean'],
'Fee_Decimal': 'sum',
'Net_Revenue': 'sum'
}).round(2)
# Flatten column names
currency_analysis.columns = ['Total_Revenue', 'Transaction_Count',
'Avg_Transaction', 'Total_Fees', 'Net_Revenue']
# Sort by total revenue descending
currency_analysis = currency_analysis.sort_values('Total_Revenue', ascending=False)
print(currency_analysis)
Expected Output: A breakdown showing each currency's performance:
Currency Total_Revenue Transaction_Count Avg_Transaction Total_Fees Net_Revenue
USD 487,250.00 1,842 264.52 14,127.50 473,122.50
EUR 156,830.00 687 228.32 4,548.87 152,281.13
GBP 89,420.00 412 217.04 2,592.68 86,827.32
CAD 45,680.00 298 153.29 1,324.68 44,355.32
AUD 28,910.00 187 154.65 838.93 28,071.07
Step 4: Convert to Base Currency for Comparison
To accurately compare revenue across currencies and calculate percentages, convert everything to your base currency (typically your settlement currency or primary operating currency).
You'll need historical exchange rates for the transaction dates. Free sources include:
- European Central Bank API: Provides daily EUR exchange rates
- exchangerate-api.com: Free tier with historical data
- Open Exchange Rates: Free tier for basic historical data
Here's how to implement currency conversion:
import requests
from datetime import datetime
# Fetch exchange rates (using exchangerate-api.com as example)
def get_exchange_rate(from_currency, to_currency='USD', date=None):
"""
Get historical exchange rate for a specific date
If date is None, uses latest rate
"""
if date:
date_str = datetime.strptime(date, '%Y-%m-%d').strftime('%Y-%m-%d')
url = f"https://api.exchangerate-api.com/v4/history/{from_currency}/{date_str}"
else:
url = f"https://api.exchangerate-api.com/v4/latest/{from_currency}"
response = requests.get(url)
data = response.json()
return data['rates'].get(to_currency, 1.0)
# Apply conversion to base currency (USD)
def convert_to_base_currency(row, base='USD'):
if row['Currency'] == base:
return row['Net_Revenue']
rate = get_exchange_rate(row['Currency'], base)
return row['Net_Revenue'] * rate
# Add converted column
df['Revenue_USD'] = df.apply(convert_to_base_currency, axis=1)
# Recalculate totals in base currency
currency_analysis_usd = df.groupby('Currency').agg({
'Revenue_USD': 'sum',
'Transaction_Count': 'count'
}).round(2)
# Calculate percentage of total revenue
total_revenue_usd = currency_analysis_usd['Revenue_USD'].sum()
currency_analysis_usd['Percentage'] = (
currency_analysis_usd['Revenue_USD'] / total_revenue_usd * 100
).round(2)
print(currency_analysis_usd.sort_values('Revenue_USD', ascending=False))
Expected Output: Revenue converted to base currency with percentages:
Currency Revenue_USD Transaction_Count Percentage
USD 473,122.50 1,842 58.42%
EUR 165,428.45 687 20.43%
GBP 108,534.00 412 13.40%
CAD 33,876.00 298 4.18%
AUD 19,249.37 187 2.38%
Others 9,789.68 421 1.19%
-------------------------------------------------------
TOTAL 809,999.00 3,847 100.00%
Step 5: Analyze International Exposure
With your revenue normalized to a base currency, you can now assess your international market exposure and identify strategic insights. This analysis goes beyond simple percentages to understand the health and trajectory of each market.
Key analyses to perform:
Geographic Revenue Distribution
Calculate what percentage of your revenue comes from domestic vs. international markets:
# Assuming USD is your domestic currency
domestic_revenue = currency_analysis_usd[
currency_analysis_usd.index == 'USD'
]['Revenue_USD'].sum()
international_revenue = currency_analysis_usd[
currency_analysis_usd.index != 'USD'
]['Revenue_USD'].sum()
total = domestic_revenue + international_revenue
print(f"Domestic Revenue (USD): ${domestic_revenue:,.2f} ({domestic_revenue/total*100:.2f}%)")
print(f"International Revenue: ${international_revenue:,.2f} ({international_revenue/total*100:.2f}%)")
print(f"\nInternational Exposure: {international_revenue/total*100:.2f}%")
Expected Output:
Domestic Revenue (USD): $473,122.50 (58.42%)
International Revenue: $336,876.50 (41.58%)
International Exposure: 41.58%
Growth Trends by Currency
Compare month-over-month or quarter-over-quarter growth for each currency:
# Add month column
df['Month'] = pd.to_datetime(df['Created']).dt.to_period('M')
# Calculate monthly revenue by currency
monthly_trends = df.groupby(['Month', 'Currency'])['Revenue_USD'].sum().unstack(fill_value=0)
# Calculate month-over-month growth
monthly_growth = monthly_trends.pct_change() * 100
print("Month-over-Month Growth Rates (%):")
print(monthly_growth.tail())
Currency Concentration Risk
Assess whether your revenue is too concentrated in specific currencies, which could expose you to exchange rate volatility. Just as AdaBoost focuses on difficult-to-classify cases, you should pay special attention to currencies with high volatility or concentration.
# Calculate Herfindahl-Hirschman Index (HHI) for currency concentration
# HHI ranges from 0 (perfect diversity) to 10,000 (complete concentration)
hhi = (currency_analysis_usd['Percentage'] ** 2).sum()
print(f"Currency Concentration (HHI): {hhi:.2f}")
if hhi > 2500:
print("⚠️ High concentration - consider diversifying currency exposure")
elif hhi > 1500:
print("⚡ Moderate concentration - monitor major currency markets")
else:
print("✓ Well-diversified currency exposure")
Step 6: Visualize and Interpret Results
Data visualization transforms raw numbers into actionable insights. Create visualizations that help you and your stakeholders understand currency performance at a glance.
Revenue Distribution Pie Chart
import matplotlib.pyplot as plt
# Create pie chart of revenue by currency
fig, ax = plt.subplots(figsize=(10, 8))
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#FFA07A', '#98D8C8', '#F7DC6F']
currency_analysis_usd.plot(
kind='pie',
y='Revenue_USD',
ax=ax,
autopct='%1.1f%%',
startangle=90,
colors=colors[:len(currency_analysis_usd)]
)
ax.set_ylabel('')
ax.set_title('Revenue Distribution by Currency (USD Equivalent)', fontsize=16, fontweight='bold')
plt.savefig('currency_distribution.png', dpi=300, bbox_inches='tight')
plt.show()
Time Series Analysis
Track how currency mix has changed over time:
# Create stacked area chart showing currency revenue over time
monthly_trends.plot(
kind='area',
stacked=True,
figsize=(14, 7),
alpha=0.7,
color=colors[:len(monthly_trends.columns)]
)
plt.title('Revenue Trends by Currency Over Time', fontsize=16, fontweight='bold')
plt.xlabel('Month', fontsize=12)
plt.ylabel('Revenue (USD)', fontsize=12)
plt.legend(title='Currency', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.grid(True, alpha=0.3)
plt.savefig('currency_trends.png', dpi=300, bbox_inches='tight')
plt.show()
Transaction Value Distribution
Compare average transaction values across currencies to identify premium markets:
# Create bar chart of average transaction values
avg_transaction = df.groupby('Currency')['Revenue_USD'].mean().sort_values(ascending=False)
fig, ax = plt.subplots(figsize=(12, 6))
avg_transaction.plot(kind='bar', ax=ax, color='#4ECDC4', edgecolor='black')
ax.set_title('Average Transaction Value by Currency', fontsize=16, fontweight='bold')
ax.set_xlabel('Currency', fontsize=12)
ax.set_ylabel('Average Transaction Value (USD)', fontsize=12)
ax.grid(True, alpha=0.3, axis='y')
# Add value labels on bars
for i, v in enumerate(avg_transaction):
ax.text(i, v + 5, f'${v:.2f}', ha='center', va='bottom', fontweight='bold')
plt.xticks(rotation=0)
plt.savefig('avg_transaction_by_currency.png', dpi=300, bbox_inches='tight')
plt.show()
Key Insights to Look For:
- Growing Markets: Currencies showing consistent month-over-month growth indicate expanding markets worth investing in
- Premium Markets: Currencies with higher average transaction values may indicate customers with greater purchasing power
- Seasonal Patterns: Some currencies may show seasonal fluctuations tied to regional shopping patterns or business cycles
- Currency Pair Correlations: Similar patterns across related currencies (e.g., EUR and GBP) may indicate regional trends
Interpreting Your Results
Understanding the Numbers
Once you've completed your multi-currency analysis, interpreting the results correctly is crucial for making strategic decisions. Here's how to read and act on your findings:
Revenue Concentration
- High concentration (>70% in one currency): You have limited international diversification. Consider expanding to new markets or improving localization in existing markets.
- Balanced distribution (30-50% international): Healthy international presence. Focus on optimizing high-performing markets and identifying growth opportunities.
- Heavy international exposure (>60% international): Strong global presence but higher currency risk. Consider hedging strategies and monitor exchange rate fluctuations closely.
Growth Indicators
Positive month-over-month growth in specific currencies signals market opportunities:
- Consistent growth (>5% monthly): Invest in market-specific features, localized marketing, and regional payment methods
- Stagnant growth (±2% monthly): Market may be saturated or facing competitive pressure. Investigate and potentially test new pricing or features
- Declining growth (<-5% monthly): Identify root causes: competition, product-market fit issues, pricing problems, or macroeconomic factors
Transaction Value Patterns
Average transaction values reveal purchasing behaviors and opportunities:
- Higher than domestic average: Premium market opportunity. Consider premium features or tiered pricing for these regions
- Lower than domestic average: Price sensitivity or different use cases. Consider localized pricing strategies or entry-level offerings
- High variance: Diverse customer segments within the currency group. Segment further by customer type or product category
Strategic Decision-Making
Use your multi-currency analysis to inform business strategy across multiple dimensions. Similar to how accelerated failure time models guide time-to-event decisions, currency analysis should drive time-sensitive strategic choices.
Pricing Strategy
- Implement purchasing power parity pricing for markets with significantly different average transaction values
- Test psychological pricing in high-volume currencies (e.g., €99 vs €97)
- Consider dynamic pricing based on currency strength and local competition
Market Expansion Priorities
- High-growth currencies: Double down with localized content, regional payment methods, and local customer support
- Adjacent markets: If EUR is strong, consider other European currencies (SEK, NOK, DKK, PLN)
- Untapped regions: Low or zero representation in major economies (JPY, CNY, INR) may indicate expansion opportunities
Risk Management
- Currency hedging: For markets representing >15% of revenue, consider forward contracts or currency options
- Diversification targets: Set goals to reduce concentration (e.g., no single currency >50% of revenue)
- Settlement strategy: Optimize when to convert currencies based on rate forecasts and cash flow needs
Automate Your Multi-Currency Analysis
Manual currency analysis is valuable for understanding the fundamentals, but it's time-consuming and prone to errors. MCP Analytics provides automated multi-currency revenue analysis for Stripe, giving you real-time insights without the manual work.
What You Get with Automated Analysis:
- Real-time dashboards showing currency distribution, growth trends, and international exposure
- Automatic currency conversion using daily exchange rates to ensure accuracy
- Anomaly detection to alert you when currency patterns deviate from expectations
- Predictive analytics forecasting revenue by currency based on historical trends
- Custom reporting tailored to your business metrics and KPIs
- API integration for embedding insights directly into your internal tools
Try Multi-Currency Analysis Now
Connect your Stripe account and get instant insights into your international revenue breakdown.
Start Free Analysis →For businesses requiring custom currency analysis solutions, including hedge recommendations, scenario planning, and integration with financial systems, explore our enterprise currency analysis services.
Common Issues and Solutions
Issue 1: Missing Currency Data in Exports
Problem: Your Stripe export doesn't include currency information or shows null values.
Solution: Ensure you selected "All columns" when creating the export. If using the API, explicitly request the currency field in your query. For older transactions, you may need to use the Stripe API with expand: ['data.currency'] parameter.
// Correct API call with currency data
const charges = await stripe.charges.list({
limit: 100,
expand: ['data.currency', 'data.balance_transaction']
});
Issue 2: Inconsistent Exchange Rates
Problem: Your conversion totals don't match Stripe's reporting or show large discrepancies.
Solution: Use transaction-date exchange rates rather than current rates. Stripe converts currencies at the time of transaction, so historical rates are essential for accuracy. Consider using Stripe's built-in balance transaction data, which includes the converted amount.
# Get the actual converted amount from Stripe's balance transaction
df['Converted_Amount'] = df['balance_transaction'].apply(
lambda x: x['amount'] if pd.notnull(x) else None
)
Issue 3: Large Number of Low-Volume Currencies
Problem: You have many currencies each representing <1% of revenue, making analysis cluttered.
Solution: Group low-volume currencies into an "Other" category for high-level reporting, but maintain detailed records for specific analysis:
# Group currencies with <2% of total into "Other"
threshold = 2.0
currency_analysis_usd['Category'] = currency_analysis_usd['Percentage'].apply(
lambda x: 'Other' if x < threshold else currency_analysis_usd.loc[
currency_analysis_usd['Percentage'] == x
].index[0]
)
# Create summary with "Other" grouped
summary = currency_analysis_usd.groupby('Category').agg({
'Revenue_USD': 'sum',
'Transaction_Count': 'sum'
})
Issue 4: Presentment vs Settlement Currency Confusion
Problem: Different totals when analyzing presentment currency vs settlement currency.
Solution: Decide on your analysis objective. For customer experience and market analysis, use presentment currency (what customers pay). For financial planning and accounting, use settlement currency (what you receive). Document which you're using in all reports.
Issue 5: Time Zone Differences Affecting Monthly Totals
Problem: Monthly revenue totals differ depending on time zone conversion.
Solution: Standardize on UTC for all analysis, or use your business's local time zone consistently. Stripe timestamps are in UTC by default:
# Ensure consistent timezone handling
df['Created_UTC'] = pd.to_datetime(df['Created'], utc=True)
df['Created_Local'] = df['Created_UTC'].dt.tz_convert('America/New_York')
# Use local time for monthly grouping
df['Month'] = df['Created_Local'].dt.to_period('M')
Issue 6: API Rate Limiting
Problem: Hitting Stripe's API rate limits when fetching large amounts of historical data.
Solution: Implement pagination and rate limiting in your code:
import time
async function fetchAllCharges() {
let allCharges = [];
let hasMore = true;
let startingAfter = null;
while (hasMore) {
const charges = await stripe.charges.list({
limit: 100,
starting_after: startingAfter
});
allCharges = allCharges.concat(charges.data);
hasMore = charges.has_more;
startingAfter = charges.data[charges.data.length - 1].id;
// Respect rate limits
if (hasMore) {
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
return allCharges;
}
Issue 7: Currency-Specific Fee Structures
Problem: Different currencies have different fee structures, making net revenue comparisons difficult.
Solution: Calculate effective fee rates for each currency and factor this into ROI calculations:
# Calculate effective fee rate by currency
fee_analysis = df.groupby('Currency').agg({
'Amount_Decimal': 'sum',
'Fee_Decimal': 'sum'
})
fee_analysis['Effective_Fee_Rate'] = (
fee_analysis['Fee_Decimal'] / fee_analysis['Amount_Decimal'] * 100
).round(2)
print("Fee Rates by Currency:")
print(fee_analysis['Effective_Fee_Rate'].sort_values(ascending=False))
When to Seek Expert Help: If you're dealing with complex currency scenarios (hedging strategies, multi-entity structures, cross-border tax implications), consider consulting with financial analysts or using specialized tools like those offered through MCP Analytics' currency analysis services.
Conclusion
Multi-currency revenue analysis in Stripe provides essential insights for any business operating internationally. By systematically extracting payment data, normalizing currencies, calculating key metrics, and visualizing trends, you gain a comprehensive understanding of your international exposure and market opportunities.
The techniques covered in this tutorial—from basic currency grouping to advanced concentration analysis—form the foundation for data-driven international growth strategies. Whether you're just beginning to accept international payments or managing a complex multi-currency operation, regular currency analysis helps you make informed decisions about pricing, market expansion, and risk management.
Remember that currency analysis is not a one-time exercise but an ongoing process. Set up regular reporting cadences (weekly for fast-growing businesses, monthly for stable operations) to track trends and respond quickly to market changes. Automate where possible to reduce manual effort and ensure consistency.
Ready to take your currency analysis to the next level? Try MCP Analytics' automated multi-currency analysis and get instant insights into your international revenue breakdown, complete with actionable recommendations for growth and optimization.
Explore more: Stripe Analytics — all tools, tutorials, and guides →