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.
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.
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:
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.
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.
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.