Stripe Multi-Currency Revenue Analysis Guide

Category: Stripe Analytics | Reading Time: 12 minutes

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:

Understanding Stripe's Currency Structure

Stripe stores currency information in several key fields:

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:

  1. Log into your Stripe Dashboard at dashboard.stripe.com
  2. Navigate to Payments in the left sidebar
  3. Click the Export button in the top-right corner
  4. Select your date range (recommend at least 90 days for trend analysis)
  5. Choose All columns to ensure currency data is included
  6. Select CSV format for easier manipulation
  7. 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:

  1. Open the exported CSV in your preferred tool (Excel, Google Sheets, or a programming environment)
  2. Identify key columns: Look for Currency, Amount, Status, Created, and Fee columns
  3. Filter for successful payments: Remove refunded, failed, or pending transactions by filtering where Status = "succeeded"
  4. Normalize currency codes: Ensure all currency codes are uppercase and consistent
  5. 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:

# 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:

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:

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

Growth Indicators

Positive month-over-month growth in specific currencies signals market opportunities:

Transaction Value Patterns

Average transaction values reveal purchasing behaviors and opportunities:

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

Market Expansion Priorities

Risk Management

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:

Marketing Team? Get Channel-Level ROI — See which channels actually drive revenue with media mix modeling, multi-touch attribution, and ad spend analysis.
Explore Marketing Analytics →

Try Multi-Currency Analysis Now

Connect your Stripe account and get instant insights into your international revenue breakdown.

Start Free Analysis →

Compare plans →

For businesses requiring custom currency analysis solutions, including hedge recommendations, scenario planning, and integration with financial systems, explore our enterprise currency analysis services.

Next Steps with Stripe Analytics

Multi-currency analysis is just one component of comprehensive Stripe analytics. Once you understand your currency breakdown, consider these advanced analyses:

1. Customer Segmentation by Geography

Combine currency data with customer behavioral data to understand how different geographic segments use your product. This reveals opportunities for localization, regional feature development, and targeted marketing.

2. Payment Method Analysis

Different regions prefer different payment methods (credit cards in the US, SEPA transfers in Europe, digital wallets in Asia). Analyze payment method usage alongside currency data to optimize conversion rates.

3. Failed Payment Analysis

Compare failed payment rates across currencies to identify regions with payment friction. High failure rates in specific currencies may indicate issues with payment methods, fraud detection, or local banking infrastructure.

4. Subscription Cohort Analysis

For subscription businesses, analyze retention and churn rates by currency. Different markets may have different lifetime value profiles, which should inform customer acquisition cost targets.

5. Tax and Regulatory Compliance

Use currency analysis to ensure proper tax collection and regulatory compliance in each jurisdiction. Different countries have different VAT, GST, or sales tax requirements.

6. Currency-Specific A/B Testing

Just as A/B testing requires statistical rigor, testing pricing, features, or messaging across different currency groups requires proper experimental design. Test variations specific to high-value currency markets to maximize ROI.

Recommended Reading

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 →