Skip to main content

LemonSqueezy

LemonSqueezy

Connect LemonSqueezy to see which channel, campaign or page brought each payment — not just how much you earned.

LemonSqueezy tells you what you earned. It cannot tell you what earned it.

Connect it and every payment is matched to the visit that led to it, so the revenue card breaks down by channel, campaign and landing page beside the traffic that produced it.

What you get

  • Payments attributed to a source. A sale traced back to the search, the post or the campaign that brought the customer.

  • The subscription goals, with no code from you — the full list covers trials, upgrades, downgrades, pauses, cancellations and churn.

  • MRR, with a yearly plan counted as its monthly equivalent rather than as a spike and then a crash.

  • Your history, imported once on connection.

Connecting

Check the Test/Live switch first

It is at the bottom left of the LemonSqueezy dashboard, and it decides which data your key can read.

A LemonSqueezy key carries no mode inside it — a test key and a live key look identical. Create one in the wrong mode and it authenticates perfectly, then reads an empty store. Nothing on either side can catch that for you, which is why it comes first.

Create an API key

Settings → API → +. LemonSqueezy offers no scopes: the key carries the whole account, so there is nothing to tick.

Copy it when it is shown — it is not displayed again.

screenshot coming

LemonSqueezy Settings → API with the new-key dialog open and the Test/Live switch visible at the bottom left. Light theme, cropped to include both the key field and the switch, since the switch is the thing that goes wrong.

Find your store ID

Settings → Stores — the number beside your store's name, like 470275.

You supply this rather than us picking it, because an account can hold several stores and only you know which one this site sells through. Choosing for you would silently attribute another shop's revenue to this dashboard.

Paste both into TrueStat

Settings → Integrations → LemonSqueezy. The key is encrypted before it is stored, and the webhook is created for you.

screenshot coming

Site settings, Integrations tab: the LemonSqueezy card with the API key and Store ID fields, before any connection. Light theme, cropped to the card.

Linking a payment to a visitor

Without this, payments still appear — but under Unattributed, because nothing connects the payment to the visit that led to it.

Our script stores a visitor id in a cookie. How you pass it to LemonSqueezy depends on how your checkout opens:

Checkout API

Your server creates the checkout and sets the custom data.

Overlay checkout

A buy button on your page, with no server call of your own.

Other methods

A shared link's order id, or matching on e-mail.

The field is nested one level deeper than on every other provider. It is checkout_data.custom, not a top-level custom_data. Sending it at the top level is accepted and silently dropped — the Checkout API page covers this.

What the numbers mean

  • Amounts include tax. A €100 sale with €20 VAT is recorded as €120, matching what LemonSqueezy shows.

  • Fees are recorded, not subtracted. LemonSqueezy is the merchant of record, so its fee and the net payout are stored beside the amount — the revenue figure is the gross, which is the number that reconciles with your store.

  • A plan change is counted as the difference. Moving a customer from $29 to $79 records $50 of new MRR, not $79 — the $29 was already there.

A downgrade can produce a negative payment, and it is real.

Moving to a cheaper plan makes LemonSqueezy issue a credit for the unused time, and that credit arrives as an invoice with a negative total. It is not a refund: nothing was returned to the card, the charge and the credit simply cancel out.

You will see both rows. Their sum is what the customer actually paid, and it is what your store's own total shows.

screenshot coming

The Revenue card with a LemonSqueezy connection: total, new versus renewal, and refunds over the selected range. Light theme, cropped to the card.

Your history comes with you

Connecting imports the store's past orders and subscriptions, so the dashboard is not empty on day one.

What imported payments can and cannot tell you

They carry the amount, the date, the plan and the customer — everything except which visit produced them. LemonSqueezy does not return checkout metadata on a listed order, so history arrives under Unattributed and attribution begins with the first payment after you connect.

That is a limit of what the API returns, not a shortcut on our side.

Re-syncing later

Settings → Integrations → LemonSqueezy → Re-sync history rebuilds payments and subscriptions from the store.

It is safe to repeat: a payment already recorded is not counted twice. Your recorded lifecycle events — upgrades, pauses, trial conversions — are kept as they happened, because no provider can reproduce when they happened after the fact.

screenshot coming

The LemonSqueezy card while the history import is running: the progress line naming how many payments have been imported so far. Light theme, cropped to the card.

Changing a plan

A plan change is the one thing LemonSqueezy does not announce. Swapping a subscription's variant fires no subscription webhook at all — only the invoice for the money, if any moved.

So when an invoice arrives for a plan change, TrueStat re-reads the subscription from the API rather than assuming it is unchanged. You do not have to do anything; it is written down here because it explains why a plan change can take a few seconds longer to appear than a payment does.

Disconnecting

Settings → Integrations → LemonSqueezy → Disconnect removes the webhook from your store, deletes the stored key, and clears the revenue this connection wrote. Your pageviews and goals are untouched.

If something is not working

The key was accepted but no data appeared. Almost always the Test/Live switch — a key made in the other mode reads an empty store without erroring. Check which mode you were in when you created it.

Payments arrive but everything is Unattributed. The checkout is not passing ts_vid. Check that you read window.truestat.visitorId at click time rather than at page load.

A payment is missing. Only orders and invoices that actually collected money are recorded — pending, failed and fraudulent orders are not revenue and are deliberately skipped.

Was this page helpful?

Last updated September 9, 2026