Article · Updated August 2026
Track revenue across Stripe, app stores and multiple products

One revenue view should not flatten Stripe, app-store and product ledgers into one unexplained total. Reconcile each source first, then normalize the measures that are genuinely comparable.
Keep separate columns for:
- gross sales or transaction value;
- refunds;
- taxes and fees where available;
- proceeds or net receipts;
- cash paid out;
- normalized recurring revenue;
- recognized revenue when accounting requires it.

Choose the reporting basis
| Measure | Question | Timing |
|---|---|---|
| Gross sales | What did customers purchase? | Transaction event |
| Proceeds/net receipts | What remains after defined deductions? | Source estimate/finalization |
| Cash collected | What settled or paid out? | Payment/payout timing |
| MRR | What is the normalized value of active recurring subscriptions? | Subscription state |
| Recognized revenue | What revenue belongs to this accounting period? | Service/performance obligation |
Stripe documents that revenue recognition can defer subscription invoice line items across their service periods (Stripe). That is different from cash and MRR.
Build a source register
| Source | Accounts/products | Currency | Authoritative for | Owner |
|---|---|---|---|---|
| Stripe | Web SaaS, two accounts | USD/AUD | Customers, invoices, subscriptions, payments, payouts | Finance/founder |
| App Store Connect | iOS app | Store currencies | Apple transactions, proceeds, subscription state | Founder |
| Play source | Android app | Store currencies | Google transactions and payouts | Founder |
| RevenueCat | Cross-platform subscription view | Display currency | Entitlements and normalized subscription analytics | Product/founder |
Record account IDs, project/product mappings and timezone. Never rely on display names alone.
Reconcile every source independently
For each source and period:
- confirm the account and currency;
- export or query transactions;
- remove sandbox/test activity;
- classify purchase, renewal, refund, dispute and fee;
- tie transaction totals to source reports;
- tie payouts to the cash ledger separately;
- document late events and adjustments.
Only after this source-level check should values enter the combined view.
Normalize products and customers
Create mapping tables:
| Source product ID | Canonical product | Billing interval | Revenue class |
|---|---|---|---|
price_web_pro_monthly | Acme Pro | Monthly | Recurring |
ios.acme.pro.yearly | Acme Pro | Annual | Recurring |
android_acme_lifetime | Acme Lifetime | One-time | Non-recurring |
Keep a separate customer bridge where lawful and available:
| Product account | Stripe customer | RevenueCat app user | Store transaction |
|---|---|---|---|
acct_123 | cus_… | acct_123 | original transaction ID |
Do not deduplicate people from weak personal attributes. Report unknown cross-platform identity when no stable mapping exists.
Normalize MRR deliberately
Stripe defines MRR as the monthly-normalized value of active and past-due subscriptions, excluding trials, taxes, free plans and—in its standard MRR—metered products. It allows configuration of discount treatment and when subscribers become active (Stripe).
Write your policy:
- annual subscription value divided by 12;
- monthly subscriptions at current recurring value;
- trials excluded;
- one-time purchases excluded;
- refunds and delinquency handled according to stated source policy;
- currency conversion rate and date recorded;
- product/account mappings versioned.
Do not call this cash revenue.
Multiple Stripe accounts
Stripe Organizations can provide consolidated balance and payout-reconciliation reports across enabled accounts, with filters for accounts, time period and settlement currency (Stripe). Consolidated financial reports do not remove the need for product and MRR definition alignment.
When accounts settle in different currencies, retain the source amount and currency, then add a reporting-currency amount with the rate source and date. Do not sum currency symbols.
App stores and web revenue together
RevenueCat Web can place web purchases alongside mobile-store purchases and supports integrations with RevenueCat Billing, Stripe Billing and Paddle Billing (RevenueCat). Whether you use it or another layer, preserve which billing engine owns products, renewals, taxes and customer management.
For every combined row, keep:
- source/store;
- product and interval;
- transaction and service dates;
- gross, refund and proceeds fields;
- original and reporting currency;
- customer/account join confidence;
- recurring/non-recurring classification.
Create a canonical transaction table
The normalized layer should preserve the source record rather than replace it.
| Field | Purpose |
|---|---|
source and source_account_id | Trace the owning ledger |
source_transaction_id | Deduplicate and link back |
canonical_product_id | Group equivalent products |
product_type | Recurring, one-time or usage |
customer_bridge_id | Join only when defensible |
event_type | Purchase, renewal, refund, dispute, fee |
transaction_at | Customer transaction timing |
service_period_start/end | Recognition and subscription context |
gross, tax, fee, refund, proceeds | Keep bases separate |
original_currency and amount | Preserve source truth |
reporting_currency and rate | Explain normalization |
is_test | Exclude sandbox activity explicitly |
Use (source, source_account_id, source_transaction_id, event_type) or another source-supported key for idempotent imports. A retry should update or ignore the record, not create a second sale.
Reconcile cash separately from activity
A payout can contain many transactions, fees, refunds and adjustments. Build two checks:
- transaction activity reconciles to the source’s activity report;
- payouts reconcile to the bank or cash ledger.
Do not force daily transaction totals to equal daily bank deposits. Payout schedules and settlement delays make that expectation false.
Allocate revenue by product without losing source totals
First reproduce the source total. Then group by canonical product.
| Canonical product | Stripe web | App Store | Play Store | Combined proceeds |
|---|---|---|---|---|
| Acme Pro | $4,900 | $3,100 | $1,740 | $9,740 |
| Acme Teams | $2,930 | $1,140 | $795 | $4,865 |
| Source total | $7,830 | $4,240 | $2,535 | $14,605 |
These fictional allocations tie exactly to the source proceeds in the worked example. If the product table does not tie, leave an “unmapped” row visible rather than silently dropping transactions.
Handle late events and restatements
Refunds, disputes, store proceeds and subscription state can arrive after the initial report. Choose a policy:
- maintain an open recent period that can restate;
- close periods after a stated delay;
- record late adjustments in the current period while retaining original transaction date;
- show when a previously published number changed.
For an operating dashboard, restating recent periods is often clearer than pretending the first value was final. Accounting policy should be confirmed with the appropriate professional; this article is an analytics method, not accounting advice.
Data-quality checks for the combined view
Run:
- transaction IDs unique within source/account;
- all products mapped or explicitly unmapped;
- original currency always present;
- gross minus refunds/fees ties to proceeds on the chosen basis;
- source totals tie before cross-source aggregation;
- beginning MRR plus movements equals ending MRR;
- test data excluded;
- refresh timestamps within the expected source delay;
- imported Stripe transactions not counted again through a subscription layer.
Surface failures beside the dashboard. A combined total with a stale store source should be marked partial.
A fictional monthly view
| Source | Gross | Refunds | Fees | Proceeds | Ending MRR |
|---|---|---|---|---|---|
| Stripe web | $8,400 | −$300 | −$270 | $7,830 | $6,900 |
| App Store | $5,200 | −$180 | −$780 | $4,240 | $3,950 |
| Play Store | $3,100 | −$100 | −$465 | $2,535 | $2,300 |
| Combined | $16,700 | −$580 | −$1,515 | $14,605 | $13,150 |
The fictional MRR does not reconcile to monthly proceeds because they are different measures. Annual cash transactions, one-time purchases, renewal timing and fees all contribute to the difference.
Add an MRR bridge:
| Movement | Amount |
|---|---|
| Beginning MRR | $12,600 |
| New | +$1,100 |
| Expansion | +$260 |
| Reactivation | +$90 |
| Contraction | −$180 |
| Churn | −$720 |
| Ending MRR | $13,150 |
Common reconciliation failures
- Mixing transaction date with payout date.
- Treating proceeds and gross sales as synonyms.
- Double-counting Stripe transactions imported into a subscription layer.
- Including annual cash in one month of MRR.
- Combining test and production.
- Summing multiple currencies without a disclosed conversion.
- Deduplicating customers without a stable identity.
- Changing discount/delinquency definitions without restating history.
Build or buy the reporting layer
Use source exports or a spreadsheet when the products and accounts are few, the process is stable and one owner accepts the maintenance. Use a warehouse/BI layer when flexible finance and product analysis justify modeling work. Use a subscription analytics platform when entitlement and recurring lifecycle are the main job. Use a thin founder-reporting layer when definitions already exist and the repeated need is one operating view.
No layer removes the need to preserve source IDs and revenue bases. It changes who owns collection, refresh, mapping and presentation.
Frequently asked questions
Should Stripe or RevenueCat be the source of truth?
Stripe owns Stripe billing events; app stores own their transactions; RevenueCat can own cross-platform entitlement logic and normalized charts. Name the source per measure rather than selecting one universal truth.
Can I combine several Stripe accounts?
Stripe Organizations support consolidated financial reports for eligible accounts. Product analytics and MRR still require aligned mappings and definitions.
Why does combined MRR not match monthly revenue?
MRR normalizes active recurring subscriptions. Revenue records transactions in the period and can include one-time or annual purchases. They should not be expected to match.
How should currencies be handled?
Retain original amounts and currencies. Add a reporting-currency value using a documented rate source, rate date and policy.
What belongs on the founder view?
Show source health, proceeds or cash on the chosen basis, the MRR bridge and product/source mix. Link to detailed transaction and accounting reports.
Sources
- Stripe Billing analytics and MRR definitions
- Stripe reports for multiple accounts
- Stripe revenue recognition for subscriptions
- RevenueCat Web cross-platform purchases
- Revenue per project discussion
- Combining Stripe accounts discussion