Dodo end to end
Connect Dodo Payments, attach attribution at checkout, and see which channel paid you.
Go from no Dodo connection to a payment that shows the channel that brought the buyer. About 15 minutes, once.
Before you start
You need a FounderHQ brand with the web SDK installed on your pricing page, and a Dodo Payments account you can open the dashboard for. New to the SDK? Start with Quickstart: Web (snippet).
Revenue attribution needs two halves, and one half alone tells you nothing:
- The Dodo connection tells FounderHQ that money moved.
- The checkout metadata tells FounderHQ who to thank.
Do them in that order. A read-only API key is the recommended connection: no webhook setup, and revenue appears within a few minutes.
Connect Dodo
Follow Connect Dodo. In short, you:
- Create a live API key in Dodo and leave Enable write access off.
- Paste that key into the Dodo connection for your FounderHQ brand.
- Wait a few minutes for the first sync, or choose Sync now.
FounderHQ verifies the key against Dodo's live API and binds its business before saving it. The key is encrypted and can be revoked from Dodo anytime.
Prefer webhooks? The same connection page keeps the manual webhook path. Add the URL FounderHQ gives you, select the listed events, paste Dodo's signing secret, and send a signed test event. Both paths feed the same revenue records.
Attach attribution when you create the checkout
Dodo carries your metadata from the checkout into the payment. The browser holds the two IDs, and your server builds the metadata object.
Read the IDs in the browser, and post them with the rest of the checkout request:
import { founderhq } from "@founderhq/events";
const identity = founderhq.checkoutMetadata();
// { fhq_anonymous_id, fhq_session_id }On your server, build the metadata with the Node SDK and pass it as the
metadata object of your Dodo payment or subscription call. The server
code is on Connect Dodo, step 5.
checkoutMetadata() in the browser returns an empty object when the
visitor has not granted consent. Treat that as normal, and complete the
sale without attribution.
Know what creates revenue
| Dodo event | Effect in FounderHQ |
|---|---|
payment.succeeded | Creates revenue. This covers first payments, renewals, and Indian recurring debits. |
refund.succeeded | Subtracts revenue. |
subscription.* | Updates subscription state and MRR only. It never creates revenue. |
dispute.* | Stored as evidence. It does not change revenue today. |
Dodo fires a renewal event alongside the first payment. That is why lifecycle events never create money on their own.
Renewals carry no browser session. FounderHQ binds the Dodo customer and subscription on the first payment, and resolves renewals through that binding.
Selling in India? FounderHQ stores both the charged total and the settlement amount. Channel revenue uses the charged total.
Verify
- In FounderHQ, open Revenue. The Dodo connection shows Connected.
- Start a checkout on your pricing page, and take a live payment.
- In Dodo, open the payment. Its metadata shows
fhq_anonymous_idandfhq_session_id. - In FounderHQ, open Revenue. The payment shows the channel that brought the buyer, under Introduced by and Closed by.
Troubleshoot
The payment arrives, but with no channel
The webhook half works and the metadata half does not. Open the payment in Dodo and look for the two IDs. Empty IDs mean the visitor denied consent, or the buyer never loaded a page that runs the SDK.
FounderHQ asks for a live-mode API key
The pasted key belongs to Dodo test mode. Create the key from your live Dodo dashboard and leave write access off.
The webhook connection stays on "Waiting for test"
No signed event has arrived yet. Send a test event from the Dodo endpoint.
Dodo shows "Invalid signature"
The pasted secret is wrong, or you rotated it more than 24 hours ago. Copy the current secret from Dodo and paste it again.