Skip to main content
Revenue is part of product analytics, which is coming soon. A project can use it only when product analytics is available for the project. See Product analytics.
Revenue records each money movement of your business: payments, refunds, and disputes. It shows gross and net revenue, refunds, paying and new customers, and monthly recurring revenue (MRR) in one reporting currency. When a payment carries the user id of the buyer, the revenue links to the same person in product analytics.

Send revenue to Squasher

Use one of two sources, or both for different payments:
  • Stripe. Connect a restricted read-only key and add a webhook endpoint. Squasher reads the payments of the last 13 months, then records new ones as Stripe sends them. See Stripe.
  • Your server. Send payments, refunds, and subscription states from your billing system with the API or the CLI. See Send revenue from your server.
Do not send the same payment from both sources: each source counts its own payments.

How Squasher counts revenue

  • Each payment, refund, dispute withdrawal, and dispute reversal is one row. A second delivery of the same Stripe event, or a second send of the same id, changes the row instead of adding one.
  • Refunds and disputes are their own negative rows, on the date they were processed, not the date of the payment. A refund that fails or is canceled does not count.
  • Gross is the sum of payments. Net is gross minus refunds and disputes, plus dispute reversals.
  • A paying customer made a payment in the range. A new customer made the first payment in the range.
  • A Stripe subscription payment counts once: Squasher reads the charge, and the invoice only adds the plan, the subscription, and whether the payment is a renewal.

MRR

MRR comes from subscription states. For each subscription, Squasher keeps the monthly amount from each time it changed: the price times the quantity, scaled to a month (a yearly price is divided by 12), minus a percent discount. A subscription that is trialing, paused, unpaid, or canceled has an MRR of 0. When Squasher reads past Stripe subscriptions, a canceled subscription gets MRR for its past only when its latest invoice shows a paid period, so a trial canceled before it paid never counts as MRR or churn. For a range, Squasher compares each customer’s MRR at the start and at the end: Net new MRR is new plus expansion plus reactivation, minus contraction and churn.

Reporting currency

Squasher keeps each amount in its own currency. Reports convert amounts to the project’s reporting currency (USD by default) with the euro foreign exchange reference rates that the European Central Bank publishes each working day. A payment uses the rate of its own date; a weekend or holiday uses the rate of the working day before. MRR uses the rate of the last day of the range. A currency without a reference rate stays in the breakdown by currency in its own amounts, and the report lists it under missing_currencies. It is not counted in converted totals. To change the reporting currency:
Revenue links to a person in product analytics when the payment carries the user id that you pass to identify() in the Browser SDK. With Stripe, use one of these:
  • Set client_reference_id of the Checkout Session to the user id.
  • Set the metadata key squasher_distinct_id to the user id on the Checkout Session, the customer, the subscription, or the payment. Use squasher_anonymous_id for a visitor who has not signed in.
A link on the customer also applies to the customer’s earlier and later payments. Refunds and disputes take the person of their payment. The setup check shows how much revenue has a link. Squasher never links revenue by email, IP address, name, or device fingerprint.

Send revenue from your server

Send up to 100 money movements in one request. amount is positive, in the smallest unit of the currency (cents for USD, yen for JPY); type sets the sign. Use your own id for each movement: sending the same id again replaces it.
For MRR, send subscription states with the monthly amount from a time on:
The API key needs the revenue:write permission. See Revenue API.

Revenue impact

Issue, incident, and release pages show the revenue at risk, and the revenue API returns it for a slow page too. It is an estimate, shown as a range, never an exact loss.
  • Issues and slow pages (affected people). Squasher finds the browser sessions with the error (or with a poor LCP, INP, or CLS on the page) in the last 30 days. It links those sessions to identified people through product analytics and adds the net revenue of those people in the same 30 days. That is the low end. The high end scales the low end to all affected sessions, at most 5 times, and never above the project’s net revenue.
  • Incidents and releases (baseline). Squasher compares the net revenue in the first 7 days (or less) of the incident or release with the same time in each of the four weeks before. The range runs from the shortfall against the lowest week to the shortfall against the highest week. Revenue that is higher than before shows as zero.
The estimate needs identified people for issues and pages: call identify with your user id, and put the same id on the payment. See Link revenue to people.

Revenue attribution

The Revenue page shows net revenue by the source, medium, or campaign that brought each paying person. The revenue API returns the same table. A touch is a consented page view or event whose page address has UTM parameters or an ad click ID (gclid, fbclid, msclkid, ttclid, li_fat_id, twclid), or that comes from another site. Squasher reads touches from 90 days before the range to its end, and links them to people in the same way as product analytics: the user id of identify, else the visitor. An identify call up to 400 days before the range still links a later visit of the same visitor.
  • Source: utm_source; else the ad network of the click ID (for example google for gclid); else the referrer host.
  • Medium: utm_medium; else cpc for a click ID; else referral for another site.
  • Campaign: utm_campaign.
A value that a touch does not have shows as (not set). Links from other hosts of your own site, and returns from a hosted checkout (Stripe, PayPal, Paddle), are not touches. Revenue of a person with no touch before the payment shows as direct. A payment without an analytics id (no distinct_id or anonymous_id) shows as not linked. Refunds and disputes count against the touch of their own date, so the net of each row is correct.
Touches come only from consented product analytics. Without consent the SDK sends nothing. An event that the SDK holds while consent is pending is sent after the grant without its UTM values, click IDs, referrer, and query parameters, so a visit before consent is never a touch. That revenue shows as direct or not linked.

Check the setup

The check shows whether the Stripe key works, whether webhook events arrive, whether past payments are read, how many rows are recorded, whether reports are up to date, and how much revenue links to people. Each check says what to do next.

Privacy

Squasher receives amounts, currencies, dates, plan names, and the provider’s customer and object ids. It does not receive card data, names, emails, or addresses from Stripe. When you delete a person in product analytics, Squasher removes the person’s link from their revenue rows and keeps the amounts, so totals stay correct.

Plans and usage

Each revenue row counts as one product event. A repeated delivery of the same row does not count again. See Plans and billing.

Next steps

Connect Stripe

Read payments, refunds, disputes, and subscriptions from Stripe.

Revenue API

Read revenue and MRR, and send revenue from your server.