How to track lead source in Polar
Tie every Polar order, subscription, and renewal back to the marketing channel that drove it. Revenue attribution for open-source maintainers and developer-tool SaaS.
On this page
- Why this matters
- What SourceLoop captures from Polar
- Before you start
- Step 1: Install the SourceLoop tracking script
- Step 2: Add a webhook in your Polar Dashboard
- Step 3: Paste the signing secret back into SourceLoop
- Step 4: Wire attribution into your checkout
- (1) Checkouts API
- (2) Polar Checkout Links
- Step 5: Run a test order to verify
- Where to see Polar revenue in SourceLoop
- Contacts Hub: revenue per contact
- Attribution dashboard: revenue by channel
Polar is the merchant-of-record platform built around the GitHub-native developer ecosystem, sponsorships, paid issues, license products, and SaaS, all from the same primitives. The blind spot, like every payments tool, is which marketing channel earned each subscriber. SourceLoop fills that in without changing how Polar charges your customers.
Every order, every subscription event, every refund mapped back to the visitor’s original session, so Polar’s revenue dashboard finally answers the marketing question too, not just “what did we make” but “which content, repo, or sponsorship link produced it”.
Five steps, around ten minutes. Works on every Polar organisation.
Why this matters
Polar is heavy on indirect channels, GitHub README links, Discord drops, dev blog mentions, conference repos. The revenue lifecycle that comes out the other side is hard to map without attribution that follows the customer through:
- A developer reads your README in March, clicks the Polar buy link, and starts the $19/mo plan
- They upgrade to $99/mo in July when their team grows
- They renew every month for two years
- They cancel when they migrate to a self-hosted alternative
Without revenue tracking, “github” gets credit for one event and never sees the $2,000+ that flowed from it. With Polar wired into SourceLoop, every state change, every renewal, every cancel hangs off the same contact, and channel-level MRR finally has signal.
What SourceLoop captures from Polar
Each Polar customer arrives in SourceLoop tagged with:
- Acquisition channel of the visitor at signup (paid, organic, social, referral, direct, GitHub)
- UTM parameters from the landing URL of the converting session
- Pages browsed before checkout was opened
- Time on site and return-visit count ahead of the purchase
- Email + name from Polar’s customer record
- First-touch landing page plus the original referrer
- Source of the converting session (often distinct from first-touch)
- Full revenue history, orders (initial + renewals), subscription created / active (trial converted) / updated / canceled / revoked
- Device, country, browser
Before you start
You’ll need:
- A SourceLoop workspace (free trial)
- Edit access to the site that hosts your Polar buy link or backend API
- A Polar organisation with at least one product live
- Admin access to your Polar Dashboard, you’ll need it to add a webhook
Step 1: Install the SourceLoop tracking script
Sign in to SourceLoop, open Setup -> Tracking code in the sidebar, and copy the snippet.
Paste it into the <head> of every page on your site, especially the pages with your Polar Checkout buttons or buy links. From this point on, every visitor session, UTM, and journey is being recorded. The next steps connect that data to the orders Polar will start sending.
Step 2: Add a webhook in your Polar Dashboard
Polar sends order and subscription events as webhooks. SourceLoop gives you a dedicated URL, you paste it into Polar, and Polar starts delivering events.
- In SourceLoop, open Setup -> Payment in the sidebar.
- Click the Polar card. A drawer opens on the right with two tabs: Connect webhook and Wire attribution. Stay on the first tab and copy the webhook URL SourceLoop shows you.
- Open the Polar Dashboard, navigate to Settings -> Webhooks, and click Add endpoint.
- Paste SourceLoop’s URL into the endpoint URL field.
- Under Events, select the events SourceLoop needs to read. The recommended set:
order.created,subscription.created,subscription.active,subscription.updated,subscription.canceled,subscription.revoked. - Save the endpoint. Polar generates a Signing secret (prefixed
whsec_...), copy it.
Step 3: Paste the signing secret back into SourceLoop
Polar signs every webhook with the secret it generated for the endpoint.
- Copy the
whsec_...value from the endpoint detail page in Polar. - Back in the same SourceLoop drawer, paste it into the Signing secret field and click Save.
SourceLoop’s connection status flips from pending to active the first time Polar delivers a verified event through.
Step 4: Wire attribution into your checkout
The webhook tells SourceLoop a payment happened. The attribution wiring tells SourceLoop which visitor session that payment belongs to. Without it, events still flow in, but stitching falls back to matching by customer email, lower fidelity, especially for one-off buys where the customer has no pre-purchase site history.
Once the tracker is installed, it exposes a small helper on every page that returns the two stitching identifiers for the current visitor:
window.sourceloop.checkoutMetadata()
// returns { sourceloop_anonymous_id: '...', sourceloop_id: '...' }
Pass that object through to Polar using the method that matches your checkout. Use this guide to pick:
- (1) Checkouts API — Recommended for any production setup. If you create the checkout server-side using the Polar SDK (or the underlying REST API) and redirect the customer to the returned URL, this is you. Picked by SaaS, paid licenses, and anyone who needs server-validated prices or pre-applied discounts.
- (2) Polar Checkout Links — Static
buy.polar.sh/...URLs you paste into a GitHub README, Discord, a docs page, or a blog post. Easiest to deploy, lower fidelity than the API because the metadata travels through query parameters.
Wire each one you use.
(1) Checkouts API
Pass metadata when creating the checkout server-side. Polar attaches it to the resulting Order and Subscription so every downstream event stays stitched.
Server (Node.js):
import { Polar } from '@polar-sh/sdk';
const polar = new Polar({ accessToken: process.env.POLAR_ACCESS_TOKEN });
const checkout = await polar.checkouts.create({
products: ['prod_xxx'],
successUrl: 'https://your.site/thanks',
metadata: meta,
});
return { url: checkout.url };
(2) Polar Checkout Links
Patch each Polar buy link with metadata[key] query parameters before the visitor clicks.
<a class="polar-buy" href="https://buy.polar.sh/polar_cl_xxx">Subscribe</a>
<script>
document.querySelectorAll('a.polar-buy').forEach(a => {
const m = window.sourceloop.checkoutMetadata();
const u = new URL(a.href);
u.searchParams.set('metadata[sourceloop_anonymous_id]', m.sourceloop_anonymous_id);
u.searchParams.set('metadata[sourceloop_id]', m.sourceloop_id);
a.href = u.toString();
});
</script>
Step 5: Run a test order to verify
Open the page with your Polar checkout in an incognito window, append ?utm_source=test&utm_medium=verify&utm_campaign=polar-check to the URL, and complete a real transaction. Polar’s test mode is the safest path if you’d rather not move real money.
Within seconds of Polar confirming the order, the customer should appear at the top of the Contacts Hub in SourceLoop with the test UTMs attached and a revenue event linked to the same contact.
Where to see Polar revenue in SourceLoop
Contacts Hub: revenue per contact
Every Polar customer becomes a contact row at app.sourceloop.ai/contacts with a revenue column showing what they’ve paid you to date. Click a contact to expand the full revenue ledger, initial order, every renewal, every plan change, every cancellation, alongside the visitor’s pre-purchase journey.
Filter, sort, or segment the hub by revenue to surface your highest-value customers, or by source to see which channels (GitHub, Reddit, your docs site) are bringing in paying subscribers vs. just stargazers.
Attribution dashboard: revenue by channel
app.sourceloop.ai/dashboards/traffic adds a revenue column alongside the breakdowns you already see: source, medium, campaign, landing page, content, term, device, country. So instead of “github.com referral drove 1,200 sessions”, you see “github.com referral drove 1,200 sessions and $3,400 in attributed Polar revenue.”
Switch attribution models from the dropdown at the top to see how the numbers shift:
- Last Non-Direct (the default, matches Google Analytics)
- First Touch / First Non-Direct for top-of-funnel weighting
- Last Touch for closing-channel weighting
- Linear to split credit evenly across every touchpoint
- Position-Based (U-Shaped) for 40% first / 40% last / 20% middle
- Time Decay to weight recent touches higher (7-day half-life)
For developer products, the README typically gets a discovery role and the docs get the conversion. First Touch shows you the README is doing its job; Last Touch shows you the docs page is closing. Both numbers are real, depending on which question you’re asking.
Once Polar revenue is flowing, push it back to Google Ads, Meta, and LinkedIn as offline conversions with revenue values so the bidding algorithms optimise toward paying customers, not just clicks. Connect your Google Ads account covers the wiring.
Frequently asked questions
-
Does this work with the Polar Checkouts API and Polar's static Checkout Links?
Yes. Both surfaces are covered. The webhook setup is identical for both, only the attribution wiring in step 4 differs. The article walks through each method.
-
Are subscription renewals attributed back to the original source?
Yes. Every `order.created` event tied to a recurring subscription cycle gets stitched onto the same contact that started the subscription, so MRR stays tied to the channel that earned the original signup.
-
How do refunds and cancellations show up?
Cancellations come through as `subscription.canceled` and `subscription.revoked`, which SourceLoop records as a state change on the contact. Refunds reduce the contact's attributed revenue and flow back to the original source in the dashboard.
-
I'm using Polar as a GitHub-integrated sponsorship / paid issues product. Anything different?
No. Whether Polar is hosting sponsorships, paid issues, products, or full subscriptions, every order or subscription event flows through the same webhook channel. SourceLoop attributes them the same way.
-
My Polar Checkout Link is shared on GitHub README and Discord, not on a tracked page. Are those purchases attributed?
When the customer clicks a Checkout Link from outside your tracked site, SourceLoop can't see a pre-purchase journey. The purchase is still captured (via the webhook) but the source shows as "Direct" since there's no UTM trail. Patch the Checkout Link with metadata via JavaScript on a tracked page to keep the source intact.
-
Will my Polar webhooks to other tools (Slack, my backend) still fire?
Yes. SourceLoop subscribes as its own endpoint. Every other endpoint you've configured continues to receive Polar events independently.