Dodo Payments analytics for indie founders
Dodo Payments shows you what sold. To see where each buyer came from, you connect Dodo to an analytics tool with one API key, and let it link each sale to the visit that produced it. Ownlytics supports this, with payment links tagged by the script and checkout sessions supported.
Fig.Dodo Payments sales by traffic source. Sample data, not a real site.
This post covers what that setup gives you, what to decide before connecting, and where it will not help.
What problem does this solve?
An indie founder usually has two views of the business. The payment provider has orders. The analytics tool has visits. Neither says which blog post, tweet or search brought a given buyer. Without the join, "what should I do more of" is a guess.
Linking the two is called revenue attribution. If you want the plain version first, read how to know which blog post made a sale.
How does Ownlytics connect to Dodo Payments?
You connect Dodo per website with an API key. That is the whole account-side step. From there:
- Payment links are tagged automatically by the tracking script. Nothing to do.
- Server-created checkout sessions are supported. Pass the visitor and session ids as metadata so they come back with the payment.
- Success page. When the buyer returns to your site with the provider's checkout id in the URL, the script can link it as a backup.
The first-party visitor id is the thing being carried: cookies on your own domain created by the Ownlytics script. When that id reaches the payment, Ownlytics knows the visit, source and campaign behind it. Exact fields and examples are in the revenue attribution docs, and the Dodo Payments overview shows the finished result.
Past sales are imported straight away when you connect.
One account or several sites?
Decide this before you connect, because each website connects its own payment account.
- Dedicated account per site. Every payment goes to that one site, new products included. Simplest.
- Shared account, split by product. You pick which products belong to which site.
If you sell several products from a single Dodo account and run one site per product, the product split is what keeps the reports clean.
Source: x.com → /blog/setup-guide
3 visits over 12 days
Source: google.com → /pricing
Fig.A sale alert in Telegram: the source and the page, not just the amount. Sample data, not a real site.
What do renewals, upgrades and refunds do?
Ownlytics classifies each payment as a one-time purchase, a subscription's first payment, an upgrade (a plan change or more seats), or a renewal. Renewals inherit the source of the first payment. Refunds come off the same source. A free trial's first paid charge is treated as a new sale credited to whoever started the trial.
Changelog notes mention that Stripe, Polar and Dodo previously treated a trial's first charge as a renewal, and that this was corrected so the sale goes to the person who began the trial. If you connected earlier and see old numbers, sales are re-checked with your payment provider in the background after updating.
Example (made-up numbers for illustration)
An indie founder sells a $39 one-time tool and made 20 sales in a month. The sources and counts below are invented.
| Source | Sales | Revenue |
|---|---|---|
| Blog post A | 7 | $273 |
| Blog post B | 2 | $78 |
| Newsletter | 6 | $234 |
| Direct, shared link | 3 | $117 |
| Unattributed | 2 | $78 |
Looking at this, the founder rewrites the blog post A call to action and stops posting the format behind post B. The "direct, shared link" row is worth a second look: that bucket covers new visitors landing on a deep page with no referrer, usually a link pasted in a chat or email. Ownlytics keeps it separate from plain direct traffic, which helps. See direct traffic explained for why.
Which attribution model should you use?
The default is last non-direct: the most recent visit with a real source gets credit. You can switch per website to first touch (the visitor's first visit ever) or last touch (the last visit before buying). For a small catalog with short buying cycles, the default is fine. For products people research for weeks, compare first touch too. The sources and attribution docs explain how each works.
When this is not the right setup
- If you only sell a handful of units a quarter, the dashboard will be sparse, and noise will dominate.
- If most buyers pay without ever visiting a page with the script (links you share on platforms where checkout opens directly), there is nothing to attribute to.
- If you need a payment provider that is not on the connect-with-a-key list (Stripe, Polar, Dodo, Creem), the Payments API accepts sales posted from your own server instead.
At a glance
| Item | Detail |
|---|---|
| Connection | One Dodo API key per website |
| Payment links | Tagged automatically by the script |
| Checkout sessions | Supported, pass visitor and session ids as metadata |
| Fallback match | Thank-you page, identified email, then checkout timing (estimated) |
| Renewals | Inherit the first payment's source |
| Default model | Last non-direct, switchable per website |
When you are ready to try it, the pricing page lists the one-time self-hosted license and the hosted plans. If you also run subscriptions, the post on subscriptions vs one-time sales attribution is the next one to read.
FAQ
Do I need a developer to connect Dodo Payments?
Not for payment links. The script tags them automatically. If your server creates checkout sessions, you add the visitor and session ids as metadata, which is a small server-side change.
Can I connect more than one site to the same Dodo account?
Yes. A shared account can split by product, so each website only counts its own products.
What happens if a sale cannot be linked to a visitor?
Ownlytics tries the thank-you page, then an email the visitor gave you, then checkout timing. If none fits, the sale stays unattributed with a note explaining why.
Are past Dodo sales imported?
Yes, past sales are imported straight away when you connect.