Updated 2 October 2026
Dodo Payments revenue attribution
Dodo Payments takes the payment. trckable shows which visit, source and campaign it came from, with refunds and disputes taken out.
In short
- Connect with one Dodo Payments API key. Test and live keys are separate, and trckable creates the webhook and fetches its signing secret.
- Checkout links carry the visit: the tracker adds a
metadata_trckable_vidparameter to Dodo links on click. Checkout sessions you create take onemetadatafield. - Payments, refunds and the whole dispute lifecycle are counted, so revenue is what you kept and not what you were first charged.
Why a payment total is not enough#
A payment provider reports what was paid. It does not know that this customer found you through a comparison page, read your pricing twice and then paid from a link in an email. Without that, the best you can say about a good month is that it was good.
trckable connects each Dodo payment to the visit behind it. Your reports then show what each source and page brings in, and your attention goes where the money actually comes from.
How a Dodo payment finds its visit#
- Checkout links on your page. When a visitor clicks a Dodo checkout link, the tracker adds the visitor id as
metadata_trckable_vid. Nothing to configure. - Checkout sessions created with the SDK. Add the metadata with the helper from the npm package:
const ids = getIds(request.headers.get('cookie'))
await dodo.checkoutSessions.create({ ...params, ...checkoutFields('dodo', ids) })
- Subscriptions. The
subscription.activeevent links a subscription to the visit, and later payments follow it. A renewal is credited to the visit that started the subscription.
A payment with no visitor id still counts in your totals and shows as unattributed.
Connect Dodo Payments in three steps#
- Create an API key in the Dodo Payments dashboard under Developer → API keys. Test and live mode have separate keys.
- Paste it in Settings → Payments → Dodo Payments and pick Live or Test mode. trckable creates the webhook endpoint, reads its signing secret back from Dodo, and stores it encrypted. If the secret cannot be read, it removes the endpoint again rather than leave one whose deliveries could never be verified. It then backfills the last 90 days.
- Follow one test payment through: visit your site with the tracker on, click a checkout link in test mode, and watch it appear in the Payments page.
Prefer to keep the key to yourself? Use the manual setup: trckable shows the endpoint address and the events, and you paste the signing secret back. A self-hosted trckable needs a public HTTPS address for Dodo to reach (TRCKABLE_BASE_URL).
Test and live#
Dodo's payloads do not say whether a payment is test or live. trckable knows from the mode you chose when you connected. Test payments are kept apart from your real numbers, and a toggle in the dashboard shows them. That makes test mode a safe place to try the full chain.
What trckable listens for#
| Event | Used for |
|---|---|
payment.succeeded | The payment itself. Dodo's total includes tax, and trckable subtracts the tax to get revenue |
refund.succeeded, refund.failed | Refunds, once each |
dispute.opened, dispute.challenged, dispute.won, dispute.lost, dispute.accepted, dispute.cancelled, dispute.expired | The dispute lifecycle. A dispute that is lost or accepted is subtracted from revenue; one that is won or cancelled is not |
subscription.active | Linking a subscription to its visit |
Dodo signs its webhooks following the Standard Webhooks scheme, and trckable checks every signature. Each delivery carries the object's latest state, and the same payment arriving twice is one payment.
What you see#
Revenue, conversion and revenue per visitor sit in the key numbers. Revenue plots under the visitors chart, every breakdown row has revenue and conversion columns, and Sources that pay ranks channels by revenue per visitor. In Full mode, Pages that sell and Latest buyers show where money was made.

What counts as revenue#
- The amount paid excluding tax, before fees, converted to your site's currency at the European Central Bank's rate on the day of the payment.
- Refunds are subtracted, once per refund. Disputes are recorded as opened, won or lost.
- Attribution goes to the last non-direct visit within 90 days before the payment, or to the first touch if you switch the model. The total never changes, only the credit.
If a webhook is missed#
trckable writes every webhook to disk before it answers. And every six hours it lists recent payments, refunds and disputes through Dodo's API and fills in what never arrived, so a missed delivery is a delay and not a hole.
Questions#
- Where do I get the API key?
- In the Dodo Payments dashboard under Developer → API keys. Test and live are separate keys, and you pick the matching mode in trckable.
- Does Dodo's total include tax?
- Dodo's
total_amountincludes tax. trckable subtracts it, so revenue is the amount excluding tax. - Are disputes subtracted?
- Disputes are recorded as they open, are won or lost. Money is taken out when a dispute is lost or accepted, not when it is merely opened.
- Do I have to touch my checkout code?
- For plain checkout links, no: the tracker adds the visitor when the link is clicked. For sessions you create with the SDK, add the
metadatafield. - Will it match Dodo's dashboard?
- trckable shows amounts excluding tax, before fees, converted at the ECB rate. We say "reconciled with Dodo Payments", not "identical".
Keep reading#
- Revenue attribution for every provider
- The full revenue docs
- Stripe, Paddle, Lemon Squeezy, Polar
- Any other checkout: a signed webhook from your own code