By Dilhan · · 5 min read
SaaS Free Trial Conversion Rate: Measure the Right Cohort
Calculate trial-to-paid conversion from mature cohorts, explain why Stripe and product analytics differ, and find the activation step to investigate.
Calculate paid outcomes from the same trial cohort
A SaaS free trial conversion rate should tell you what share of a defined group of trial customers became paying customers. Dividing this month's payments by this month's trial starts often mixes two groups: the people paying now may have started their trials weeks earlier.
For a report about trial starts, define the cohort by trial start date and choose a consistent outcome window. Then calculate:
Trial-to-paid conversion = customers with a first successful payment
÷ customers who started a qualifying trial
× 100
Both counts must come from the same cohort, use the same customer definition, and follow the same eligibility rules. For B2B SaaS, that unit may be an account or workspace rather than every invited teammate.
Separate pending trials from the cohort you compare
Suppose you offer a 14-day trial and want to observe the first payment through day 21 after trial start. On 28 September, the trial-start cohort from 1–7 September has had that full observation window. The cohort from 22–28 September has not.
These are hypothetical counts:
| Trial-start cohort | Trial customers | Paid by day 21 | Observation complete? |
|---|---|---|---|
| 1–7 September | 100 | 25 | Yes |
| 22–28 September | 100 | 5 so far | No |
The first cohort's day-21 conversion is 25%. The second has a provisional 5% observed so far. That does not establish a drop from 25% to 5%: the second group has had less time to pay.
Compare whole cohorts after the same window. Avoid counting only whichever customers in the newest cohort happened to finish early; early cancellations and early purchases can make that subset unrepresentative.
Keep pending outcomes visible. A fixed-window report can classify each customer at the cutoff, while a later update can record delayed payments separately. Name the window in the metric so everyone knows what “converted” means.
Why Stripe and your product dashboard may disagree
A discrepancy is a reason to compare definitions before debugging your integration.
Stripe documents its Billing trial conversion rate as conversions divided by ended trials over a rolling 30-day period. That is a different grouping from a report about customers who started a trial during a particular week. An early cancellation and a completed trial can also enter an ended-trial report at different times.
Subscription apps face a similar distinction. RevenueCat's charts overview distinguishes a Trial Conversion Rate chart based on trial starts from a Trial Conversion Funnel based on the customer's first-seen or first-purchase cohort date. Those charts can answer different questions without either being wrong.
Use this reconciliation checklist:
- Are cohorts grouped by signup, trial start, trial end, or first app open?
- Is the counted unit a user, account, customer, or subscription?
- Does conversion require a successful payment, or only a changed subscription status?
- Are repeated trials, test customers, direct purchases, and refunded payments treated the same way?
- Are the timezone, product, acquisition source, and observation window identical?
A refund does not undo the fact that an initial payment occurred. Report refunds or retained revenue alongside conversion if they matter to the decision, with an explicit policy.
Measure the path to payment as well as the final rate
A mature conversion rate identifies the outcome. To choose a product change, follow the steps preceding it.
For a collaboration SaaS, a practical path could be account created, first project created, first useful result delivered, collaborator invited, trial ended, and first payment received. For a single-user tool, inviting a collaborator would be an irrelevant milestone.
Separate an activation hypothesis from an established finding. “Created a project” may merely indicate setup; “delivered the first report to a customer” may be closer to experienced value. Start with the activation metric generator, then validate the candidate against your own customer behaviour.
In a hypothetical mature cohort of 100 trial accounts:
| Group | Accounts | Paid within the window | Conversion |
|---|---|---|---|
| Reached the candidate activation event | 40 | 20 | 50% |
| Did not reach it | 60 | 5 | 8.3% |
| Total | 100 | 25 | 25% |
That split makes activation worth investigating. It does not prove that forcing everyone through the event would cause payment. More motivated customers may be more likely to do both. Inspect the workflow and test a specific hypothesis.
Choose the next action from the failing step
If many users never produce a useful result, examine setup requirements, empty states, errors, and whether the product makes the next action obvious. If activated users finish the trial without paying, investigate the offer, recurring value, purchase friction, and cancellation reasons.
If payment is failing, treat that as a billing problem. Rewriting the welcome email will not repair a failed payment method or an incorrectly configured subscription.
Segment only as far as the counts support. A source with three trial accounts and one payment has a 33.3% observed rate, but one additional payment changes it by another 33.3 percentage points. Show counts beside percentages and avoid declaring a channel winner from a tiny cohort.
Build a weekly report you can explain
Record trial-start dates, your customer unit, the observation window, paid outcomes, unresolved states, activation counts, and the relevant source or version. Preserve those definitions across releases.
Compare mature cohorts before changing the offer. If traffic is too low for a formal experiment, use the low-traffic onboarding plan to choose the next evidence-gathering step.
OnRamp's funnel reporting helps locate product drop-off, and its Stripe integration brings billing events into the same customer investigation. You can start with the free funnel calculator, or try OnRamp to collect the underlying events.
