Polar sales by traffic source: how to see what worked
To see Polar sales by traffic source, connect your Polar account to an analytics tool that records each visit's source and tags your checkout links with a reference id. Polar copies that id onto the order, so every order can be joined back to the visit that produced it.
Fig.Polar sales by traffic source. Sample data, not a real site.
With Ownlytics, the tagging is automatic for links on your own pages. The work is the one-time connection and a few decisions about what counts.
Why is Polar revenue hard to tie to a source?
Polar tells you what sold. It does not tell you that the buyer arrived from a newsletter on Tuesday, read two posts, and came back by search on Friday. Your web analytics knows the visit but not the order. Two systems, no join.
The join key has to be created on your site and carried through checkout. Without it, you are left guessing from timestamps or asking buyers. For the general reasoning, see why your payment dashboard can't tell you where buyers came from.
How does the connection work?
The Ownlytics script gives each visitor a first-party id (cookies on your own domain). For Polar there are two ways that id reaches the order.
- Checkout links. Nothing to do. The script adds
reference_idto everybuy.polar.shlink on your site, and Polar copies it onto the order. - Checkout API. If your server creates checkouts, pass the visitor and session ids yourself. The revenue attribution docs have the exact code.
Either path can use a backup: set the success URL to https://yoursite.com/thanks?checkout_id={CHECKOUT_ID} so the script can link a returning buyer to their checkout.
What do you set up on the Polar side?
You create a token in Polar under Settings, Developers, New token, with no expiration. The scopes Ownlytics lists are: organizations:read, products:read, orders:read, subscriptions:read, customers:read, refunds:read, checkouts:read, webhooks:read and webhooks:write.
Then, in the website's setup in Ownlytics:
- Paste the token (it starts with
polar_oat_). - Choose Production or Sandbox. Use Sandbox only if you are testing.
- Keep "Instant updates" on so orders show up as they happen.
- Choose every payment in the account, or only specific products.
Each website connects its own payment account. If one Polar account sells products for several sites, a shared account can split by product. A dedicated account can send everything, new products included, to one site. Past orders are imported straight away. The Polar analytics overview summarizes the result.
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 and refunds look like?
Subscriptions keep their source. A renewal inherits the visitor of the first payment, so a customer who found you through one post keeps being credited to that post as they pay month after month. Refunds come off the same source they were credited to.
A free trial's first paid charge counts as a new sale, credited to whoever started the trial. Plan changes and seat upgrades are labeled upgrades. If you want the numbers to show only what traffic brings in, a website setting called "Count subscription renewals in revenue" can be turned off, so revenue, sales and conversion count new sales only. Switching it never deletes anything.
Example (made-up numbers for illustration)
Suppose a month of Polar orders for a $15/month tool, grouped by the source of the customer's first payment.
| First source | New customers | Orders incl. renewals | Revenue |
|---|---|---|---|
| Organic search | 6 | 14 | $210 |
| Newsletter | 3 | 9 | $135 |
| Social post | 5 | 5 | $75 |
Social looks nearly as good as search by new customers. Over time it is worth far less, because those buyers did not stay. A report that only counted first payments would hide that. This is the reason to read lifetime value by first source, not just the sale count. We cover that distinction in subscriptions vs one-time sales attribution.
What can go wrong?
- Buyers who never touched your site. If someone buys from a link you shared elsewhere that bypasses your pages, there is no visit to credit.
- Cross-device buyers. Phone in the morning, laptop at night. The id is a cookie, so the second device is a new visitor unless the email links them.
- Sandbox mixups. You choose Production or Sandbox when you paste the token. Pick the one that matches the token, and use Sandbox only for testing.
- Unattributed rows. A sale that arrives without its visitor is matched by thank-you page, then identified email, then checkout timing. Timing is an estimate and is marked as one. Otherwise it stays unattributed with a note.
Our honest limitation: attribution can only credit what the script saw. It will not fix a funnel where most buyers arrive through channels that hide where they came from.
At a glance
| Item | Detail |
|---|---|
| Connection | Polar token, Production or Sandbox |
| Buy links | Script adds reference_id to buy.polar.sh links |
| Server checkouts | Pass visitor and session ids via the Checkout API |
| Backup | Success URL with {CHECKOUT_ID} |
| Renewals | Inherit the first payment's source |
| Refunds | Come off the same source |
| Docs | Revenue attribution, Sources and attribution |
If you want to see how a connected site reads before setting anything up, open the live demo. To see this next to another provider, Dodo Payments analytics for indie founders walks through a similar setup.
FAQ
Do I have to tag my Polar buy links by hand?
No. The script adds reference_id to every buy.polar.sh link on your site, and Polar copies it onto the order.
Can I use Polar's Sandbox?
Yes. When you paste the token you choose Production or Sandbox. Pick the one that matches the token you created.
Are subscription renewals credited to the right source?
Renewals inherit the visitor of the subscription's first payment, so they stay with the source that first brought the customer.
Can one Polar account feed several websites?
Yes. A shared account can split by product, so each website gets only its own products.