Payments

Refunds and attribution: why net revenue matters

Ownlytics team · · 6 min read

If you credit a sale to a traffic source and never subtract the refund, you are rewarding that source for money you no longer have. The fix is to tie every refund back to the same source as the original sale, and judge channels by what you kept.

yourapp.comToday7d30d9 online
SourceVisitorsSalesRevenue
Xx.com6,2479$441
Ggoogle.com4,43314$686
@newsletter1,1307$343
Ynews.ycombinator.com2,0153$147
Cchatgpt.com1,4114$196

Fig.Gross revenue by source. A refund should come off the source that earned it. Sample data, not a real site.

It sounds like bookkeeping. It changes which channel you invest in.

Why do refunds distort attribution?

Most attribution reports are built at the moment of sale. A buyer arrives from a source, pays, and the source gets the credit. Refunds happen days or weeks later, in a different place (your payment provider), and often nobody goes back to adjust the source report.

The result is a quiet bias. A channel that attracts impulse buyers or mismatched expectations looks great on gross revenue and poor on what you actually keep. Another channel that sends fewer, better-informed buyers looks smaller than it is.

How does Ownlytics treat a refund?

Per the product docs, refunds come off the same source as the original sale. Subscriptions keep their source too: renewals inherit the visitor of the first payment, and a refund on any of them reduces that same source. Telegram alerts also cover refunds, along with sales, traffic spikes and a daily digest. Each of the connected providers, Stripe, Polar, Dodo Payments and Creem, is described as including refunds in its attribution.

If you send sales from your own server through the Payments API, refunds are explicit. Send the original transaction_id with "refunded": true for a full refund, or "refunded_amount": 10 for a partial one. Resending the original payment never undoes a refund, and sending the same transaction_id twice does not count anything twice.

Gross, net, and the number you should watch

Here is a simple way to think about it.

Compare channels on the second and third, not the first. A channel with a refund rate far above your others may be telling you something about the promise made before the click.

Example (made-up numbers for illustration)

Four weeks of one-time sales of a $60 product.

SourceSalesGrossRefundedNetRefund rate
Newsletter10$600$0$6000%
Search8$480$60$42012.5%
Social post14$840$360$48043%

On gross, social wins at $840. On net, newsletter wins at $600, and social is barely ahead of search despite 14 sales against 8. If you had doubled down on social after the first view, you would have scaled the channel with the worst refund rate. In this made-up case the better move is to look at what the social post promised, then compare it with what the product does.

V
Visitor 4821First seen 12 days ago · India · desktop
  1. Read “Setup guide”x.comNov 1 · 3 min on page
  2. Came back from a newsletternewsletterNov 6 · read pricing
  3. Opened checkoutNov 12 · 14:02
  4. Paid $49Dodo PaymentsCredited to the newsletter visit (last non-direct)

Fig.The sale a refund has to be traced back to. Sample data, not a real site.

What should you do with this?

  1. Check refund rate per source monthly, not just revenue per source.
  2. Read the posts behind high-refund sources. Often the headline overpromises.
  3. Use enough sales to judge. With three sales, one refund looks like 33%. Wait for a larger sample before acting.
  4. Consider keeping your own refund policy visible before checkout. Clear expectations may reduce surprise. What it should say is your call.

What about chargebacks and failed payments?

We only document refunds in the product facts, so we will not claim how other payment events are shown. Check your provider's dashboard for those, and compare it to what you see per source. If the totals disagree, the difference is worth understanding before you act on either number.

When this does not matter

If you rarely refund (a handful of cases a year), net and gross are nearly the same, and the extra attention is not worth it. It also matters less when you sell a single low-priced product and all your traffic comes from one place. Where it matters most: several channels, a higher price point, and a product people judge only after using it.

A note on subscriptions

Because renewals inherit the first payment's source, one refund on a subscription can reduce a source's lifetime value, not just the first month. For deeper reading on that split, see subscriptions vs one-time sales attribution. Ownlytics also lets you turn off counting renewals in revenue per website, so revenue, sales and conversion reflect new sales only, which helps if you want to judge acquisition separately from retention. See revenue attribution docs for the setup.

At a glance

ConceptMeaning
Refund attributionRefund reduces the same source as the original sale
Full refund via API"refunded": true with the original transaction_id
Partial refund via API"refunded_amount": 10 (major units)
Resending the paymentNever undoes a refund
Compare channels onNet revenue and refund rate, not gross
AlertsTelegram pings for refunds

If you want to see how a connected site presents revenue by source, try the live demo. For the foundational question of why the payment dashboard alone is not enough, read why your payment dashboard can't tell you where buyers came from.

FAQ

Do refunds reduce the source's revenue?

Per the Ownlytics docs, refunds come off the same source as the original sale, so a source's credit follows what you kept.

How do I record a partial refund through the Payments API?

Send the original transaction_id with "refunded_amount" set to the amount refunded, in major units, for example 10 for ten dollars.

Will I be told when a refund happens?

Telegram alerts cover refunds, along with sales, traffic spikes and a daily digest.

Is a high refund rate always a problem with the traffic source?

Not always. It can also mean a product or onboarding issue. Compare the refund rate across sources before concluding anything.

See the live demo · View pricing

Keep reading