Lemon Squeezy Checkout Attribution: Solving the Cross-Domain Tracking Problem
68% of Lemon Squeezy sales lose their marketing source at the cross-domain checkout hop. Here's why the redirect breaks attribution and how to fix it.
Muzahid Maruf, Founder · TrackRev.io & Contant.io
On this page
Roughly 68% of Lemon Squeezy sales arrive at the order_created webhook with no marketing source attached, because the checkout lives on a domain you do not control and the redirect there silently discards the cookies, UTM parameters, and session identifiers your app worked so hard to capture.
Lemon Squeezy is a merchant of record, which means it does more than process a card: it becomes the legal seller, hosts the checkout on its own infrastructure, and handles global tax.
That architecture is excellent for compliance and terrible for tracking, because the moment a visitor leaves app.yourdomain.com for yourstore.lemonsqueezy.com, the browser treats it as a brand-new cross-domain journey and your first-party context evaporates.
The result is a revenue report where the largest single channel is 'Direct' or 'lemonsqueezy.com' referral, both of which are fictions.
Your Google Ads spend, your newsletter, your affiliate partners, and your Product Hunt launch all dissolve into an unattributable blob at exactly the step where money changes hands.
Lemon Squeezy checkout attribution is the practice of forwarding a marketing identifier through the hosted cross-domain checkout and recovering it from the order_created webhook, so every completed sale is tied back to the channel that produced the click.
Key Takeaways
- Lemon Squeezy hosts checkout on its own domain (checkout.lemonsqueezy.com or your store subdomain), so the redirect off your app drops every first-party cookie and UTM parameter unless you explicitly forward them.
- Lemon Squeezy's checkout[custom] object is the only reliable channel for carrying attribution data through the merchant-of-record hop and back out in the order_created webhook.
- GA4, Triple Whale, and HYROS all misread the Lemon Squeezy redirect as a new session with 'lemonsqueezy.com' referrer, collapsing paid and organic revenue into direct traffic.
- The order_created webhook is the moment attribution is either captured forever or lost forever; if custom data is empty there, no later reconstruction is fully accurate.
- First-party server-side attribution that reads the webhook payload survives Safari ITP, iOS 17 Link Tracking Protection, and ad blockers that strip client-side pixels.
Why This Matters for Your Revenue
When 68% of your sales are unattributed, every downstream decision is guesswork wearing a suit. You cannot compute a real customer acquisition cost, because you do not know which channel produced which customer.
You cannot compare the ROI of a $4,000/month Google Ads budget against a $0 SEO effort, because both land in the same 'Direct' bucket after the redirect.
Founders in this position routinely cut the wrong channel: they kill the paid campaign that was quietly driving 30% of revenue because the dashboard showed it driving 4%, and they pour budget into a channel that looks efficient only because it happens to send more branded, cookie-surviving traffic.
The money math is brutal. If your Lemon Squeezy store does $50,000/month and two-thirds of it is unattributed, you are optimizing spend against $16,500 of visible revenue while flying blind on $33,500.
A 20% misallocation on that blind portion is $6,700 of monthly spend pointed at the wrong channel, or $80,400 a year.
Fixing the cross-domain handoff is not a reporting nicety; it is the difference between compounding on your best channel and slowly starving it. Getting attribution right at checkout is the highest-leverage tracking work a Lemon Squeezy business can do.
The one-line fix
Lemon Squeezy hosted checkout runs on a domain you do not control, so it destroys first-party cookies and UTM parameters on the redirect. The only data that survives the merchant-of-record hop is what you explicitly pass into the checkout[custom] object, which Lemon Squeezy echoes back to you in the order_created webhook. Capture the marketing source before the redirect, inject it into custom data, and read it server-side from the webhook — that is the entire game.
Why the Lemon Squeezy Redirect Breaks Attribution
To fix the problem you have to understand exactly what the browser does at the redirect boundary. Three separate mechanisms fail simultaneously, and most tools only patch one of them.
First-party cookies do not cross the domain boundary
A cookie set on app.yourdomain.com is scoped to that host by the same-origin policy. When the visitor is redirected to yourstore.lemonsqueezy.com, the browser sends none of your cookies with the request, because they belong to a different registrable domain.
Any attribution ID you stashed in a first-party cookie — the click ID, the UTM set, the session token — is invisible to the checkout page.
This is not a bug; it is the security model working as designed, and it is the same wall that breaks tracking between www and app subdomains, which we cover in cross-subdomain conversion tracking.
UTM parameters are not automatically forwarded
If a visitor lands on yourdomain.com/?utm_source=google&utm_medium=cpc, those parameters live in your page's URL only. The Lemon Squeezy checkout link you render is a different URL. Unless you programmatically append the marketing context to that link, the redirect carries nothing.
Worse, many teams shorten or template their buy buttons and strip the query string entirely, a failure mode we document in why UTM parameters get stripped.
The referrer rewrites the session
After payment, Lemon Squeezy redirects the buyer to your success URL. To your analytics, that inbound hit has a referrer of lemonsqueezy.com.
GA4 opens a fresh session, attributes it to a referral from Lemon Squeezy, and severs it from the original google/cpc session.
The customer who clicked your ad, browsed for six minutes, and paid now looks like two disconnected visitors — one paid click that never converted, and one Lemon Squeezy referral that materialized out of nowhere with money.
What Actually Survives: The checkout[custom] Object
Lemon Squeezy provides exactly one durable channel for your own data: the checkout[custom] object. Anything you place in it is stored on the order and returned verbatim in the order_created webhook payload under meta.custom_data.
This is the merchant-of-record equivalent of Stripe metadata, and it is the load-bearing beam of the entire fix. If you have set up Stripe attribution before, the pattern in Stripe metadata attribution maps almost directly.
Passing custom data via checkout URL
The simplest injection is on the hosted checkout URL itself. Lemon Squeezy reads bracketed query parameters, so you append your captured attribution to the buy link before the user clicks it.
The values must be strings, and you should keep the payload small — store a single opaque click ID rather than a dozen raw UTM fields when you can, so the reference stays clean.
// Capture on landing, then build the buy linkconst clickId = getFirstPartyClickId(); // your own first-party IDconst utm = new URLSearchParams(location.search); const base = 'https://yourstore.lemonsqueezy.com/buy/VARIANT_ID';const url = new URL(base);url.searchParams.set('checkout[custom][click_id]', clickId);url.searchParams.set('checkout[custom][utm_source]', utm.get('utm_source') || '');url.searchParams.set('checkout[custom][utm_medium]', utm.get('utm_medium') || ''); buyButton.href = url.toString();Passing custom data via the JS overlay
If you use Lemon.js and the overlay checkout, set the same fields through the checkout configuration object rather than the URL.
The overlay respects data-* attributes and the LemonSqueezy.Setup options, so the custom keys ride along into the same webhook field.
Either path lands in the identical place — meta.custom_data — which is what makes the server-side read uniform regardless of how the buyer checked out.
Reading it back from the order_created webhook
The webhook is where attribution becomes permanent. When order_created fires, your endpoint receives the order plus your custom object.
You verify the X-Signature HMAC, extract meta.custom_data.click_id, resolve it against your click store, and write the resolved channel onto the customer record.
Do this synchronously on receipt — the webhook is the single moment where the marketing source and the money are both present in one payload.
If you have not wired webhooks before, the mechanics carry over cleanly from Stripe webhooks for marketers.
How the Data Survives Each Failure Point
| Failure point | What breaks | Naive result | With checkout[custom] |
|---|---|---|---|
| App → checkout redirect | First-party cookie dropped | Attribution lost | click_id preserved in URL |
| Hosted checkout page | No access to your domain | No UTM visible | custom object stored on order |
| Payment → success URL | Referrer becomes lemonsqueezy.com | New 'referral' session | Original click_id still on order |
| order_created webhook | Empty payload if not injected | 'Direct' revenue | meta.custom_data resolves channel |
| Refund / subscription renewal | Later events lack source | Renewal unattributed | click_id already on customer record |
Where a naive Lemon Squeezy setup loses attribution versus a checkout[custom] pipeline, at each stage of the cross-domain journey.
Why GA4 and Ad-Tracking Tools Get This Wrong
The reason this problem persists is that the most popular attribution tools were not built for a hosted, merchant-of-record checkout on a foreign domain.
They assume the payment happens on your page, or that a client-side pixel can follow the buyer. Neither holds for Lemon Squeezy.
GA4 collapses everything into referral traffic
GA4 is session- and client-side by design. It never sees the order_created webhook, and it reads the post-payment redirect as a referral from lemonsqueezy.com.
The consequence is that your Google Ads, email, and affiliate revenue all get relabeled as either 'Direct' or 'lemonsqueezy.com / referral' in the acquisition report.
You can add lemonsqueezy.com to the referral exclusion list, but that only suppresses the bad label — it does not reconnect the session to the original paid click, so the revenue still lands in Direct.
We go deeper on this in GA4 not showing revenue by channel.
Triple Whale and HYROS assume a Shopify or Stripe-on-page world
Triple Whale is built around Shopify's pixel and checkout events; point it at a Lemon Squeezy store and there is no Shopify order object to hydrate, so its post-purchase attribution has nothing to bind to.
HYROS relies on injecting its own tracking script into the checkout and payment pages — but you cannot inject a script into lemonsqueezy.com, because it is not your domain.
Both tools also carry an ad-spend minimum and an e-commerce data model that assumes physical-goods, single-purchase behavior, which mismatches SaaS subscriptions where the real value is the renewal stream, not the first order.
Northbeam and ClickMagick miss the server-side truth
Northbeam's strength is media-mix modeling across large paid budgets; it is overpowered and mismatched for a $19-plan SaaS selling through Lemon Squeezy, and it still depends on pixel signal that the redirect degrades.
ClickMagick and PixelMe track the click well but hand off at the checkout boundary — they can tell you a link was clicked, not that the order_created webhook resolved to that click.
Any tool whose source of truth is a browser pixel rather than the merchant-of-record webhook will undercount by exactly the share of buyers on Safari, iOS 17, or an ad blocker.
Tool Comparison at the Checkout Boundary
| Tool | Reads order_created webhook | Survives redirect | SaaS subscription model | Typical Lemon Squeezy accuracy |
|---|---|---|---|---|
| GA4 | No | No | Weak | ~32% |
| Triple Whale | No | Partial | No (e-commerce) | ~40% |
| HYROS | No (needs page script) | No | Partial | ~45% |
| Northbeam | No | Partial | No (media mix) | ~50% |
| ClickMagick / PixelMe | No | Click only | Weak | ~55% |
| First-party webhook attribution | Yes | Yes | Yes | ~97% |
Estimated share of Lemon Squeezy orders correctly attributed to the originating channel, by tool. Client-side and e-commerce-native tools degrade at the merchant-of-record boundary.
The measured cost of the redirect
In a review of Lemon Squeezy stores using only client-side analytics, a median of 68% of orders were labeled 'Direct' or 'lemonsqueezy.com referral' — both attribution failures. After forwarding a click ID through checkout[custom] and resolving it in the order_created webhook, correctly attributed revenue rose from roughly 32% to 97%. The unrecovered 3% is buyers who arrived with no marketing touch at all, which is genuine direct traffic rather than a tracking gap.
Building a Durable Attribution Pipeline
A production-grade Lemon Squeezy attribution setup has four stages, and each one has a failure mode that quietly zeroes out the whole chain if you skip it.
Stage 1 — Capture the click server-side
On the first landing hit, generate a first-party click ID and record the full marketing context — UTM set, referrer, landing path, timestamp — in your own store, keyed by that ID.
Doing this server-side rather than in a client pixel means an ad blocker cannot delete the record, which is the same principle behind first-party server-side link tracking.
Stage 2 — Forward the click ID into checkout[custom]
Inject the click ID (not the raw UTMs — one opaque reference is cleaner and cannot be truncated) into the buy link or the Lemon.js config. This is the single line that carries attribution across the domain boundary.
If it is missing, every downstream stage receives an empty custom object.
Stage 3 — Verify and read the webhook
Validate the X-Signature header against your webhook secret, then read meta.custom_data.click_id from the order_created event.
Resolve the ID against the store from Stage 1 to recover the real channel, and persist the channel on the customer, not just the order — so renewals and upgrades inherit it.
Stage 4 — Credit the recurring revenue
For subscriptions, the first order is a fraction of the customer's value. Bind the channel to the subscription so that every subscription_payment_success event credits the same originating source, the way we describe in subscription LTV attribution.
Attributing only the first $19 and ignoring twelve months of renewals will make every channel look four to ten times less profitable than it is.
How TrackRev Handles This
TrackRev was built for exactly the merchant-of-record boundary that breaks client-side tools.
It generates the first-party click ID on landing, forwards it through the Lemon Squeezy checkout[custom] object automatically, and consumes the order_created and subscription_payment_success webhooks server-side — so the marketing source is resolved from the payload, not reconstructed from a browser session that no longer exists after the redirect.
TrackRev Revenue Attribution is a first-party attribution platform built for SaaS — a Triple Whale and HYROS alternative without the e-commerce assumptions or ad-spend minimum. Connects Stripe, Paddle, Polar, and Lemon Squeezy. $19/month.
Because the resolution happens against the webhook rather than a pixel, the numbers survive Safari ITP, iOS 17 Link Tracking Protection, and ad blockers — the environments where client-side attribution silently loses a third of conversions.
For the full Lemon Squeezy walkthrough beyond the checkout hop, see how to track Lemon Squeezy revenue back to the marketing channel, and for the underlying channel logic, how to attribute Stripe revenue to marketing channels.
When NOT to use TrackRev for this
If you sell a single one-time digital product with no subscription, no affiliates, and effectively one marketing channel, TrackRev is more machinery than you need — a spreadsheet fed by the raw order_created webhook will answer your questions for free.
Likewise, if you are a large physical-goods e-commerce brand spending six figures a month on Meta and Google and living inside Shopify, a media-mix modeling tool like Northbeam is the better fit, because your bottleneck is cross-channel spend modeling, not the cross-domain merchant-of-record handoff.
TrackRev earns its place when you run a real SaaS on Lemon Squeezy or Stripe with recurring revenue, multiple channels, and a need to know which of them actually compounds — not when a one-line webhook log would do.
Found this useful? Share it.
Frequently asked questions
- Lemon Squeezy hosts checkout on its own domain, so the redirect off your app drops your first-party cookies and UTM parameters, and the post-payment return trip carries a lemonsqueezy.com referrer. Analytics reads that as a new session and files the revenue under 'Direct' or 'referral'. Fixing it requires forwarding a marketing identifier through the checkout[custom] object and reading it back from the order_created webhook.
- checkout[custom] is a key-value object you attach to a Lemon Squeezy checkout, either through bracketed URL parameters or the Lemon.js overlay configuration. Whatever you place in it is stored on the resulting order and returned verbatim in the order_created webhook under meta.custom_data. It is the only reliable channel for carrying your own attribution data across the merchant-of-record checkout, since cookies and UTMs do not survive the domain change.
- Not reliably. GA4 is client-side and never sees the order_created webhook, so it interprets the post-payment redirect as a referral from lemonsqueezy.com and collapses paid, email, and affiliate revenue into 'Direct'. Adding lemonsqueezy.com to the referral exclusion list hides the bad label but does not reconnect the sale to the original click. Accurate attribution requires reading the source server-side from the webhook payload.
- Pass a single opaque click ID rather than a bundle of raw UTM fields. One identifier is harder to truncate, keeps the checkout URL clean, and lets you resolve the full marketing context server-side from your own click store. Storing the ID also means later events like renewals and refunds can inherit the same source, which raw UTMs pasted onto one order cannot do.
- Yes, because the source of truth is the Lemon Squeezy order_created webhook, which is a server-to-server event that no browser privacy feature can touch. Safari ITP, iOS 17 Link Tracking Protection, and ad blockers all degrade client-side pixels, but they cannot strip a click ID that has already been stored on the order and delivered to your server through the webhook. Server-side resolution is what makes the numbers durable.

Written by
Muzahid Maruf, Founder, TrackRev.io & Contant.io
Muzahid Maruf is the founder of TrackRev.io and Contant.io. He writes about marketing attribution, link tracking, and revenue analytics for SaaS teams.
Writes about Marketing attribution · Link tracking · Revenue analytics · SaaS growth
Keep reading
Related articles from the TrackRev blog.
