Skip to main content

What this lets you do

Connect Lemon Squeezy to Traceten and see which AI sources drive paying customers, not just pageviews. When an order is paid, Traceten matches it back to the originating session and attributes the revenue to the correct AI source.

Before you start

  • A Traceten account with at least one site tracked.
  • A Lemon Squeezy account, and permission to create API keys on it.
  • Your Lemon Squeezy store ID. It is the number in your store settings.
  • The Traceten snippet installed and verified on the site your checkout runs from.
  • Workspace admin in Traceten. Connecting and disconnecting a revenue source affects the whole workspace, so only admins can do it.

Connect Lemon Squeezy

You connect by pasting an API key and your store ID. There is no OAuth redirect, and there is no webhook to configure: Traceten creates the webhook on your Lemon Squeezy account for you.
1

Create an API key in Lemon Squeezy

Open Lemon Squeezy → Settings → API and click + to create a key.Give it a name (for example, Traceten) and copy it. Lemon Squeezy shows the key once.
2

Find your store ID

Open Settings → Stores and select the store whose revenue you want to attribute. The store ID is the number shown there.Traceten asks for it because a Lemon Squeezy API key covers every store on your account. Without the store ID, Traceten cannot tell which store this site sells through.
3

Paste both into Traceten

Go to app.traceten.com/dashboard, open Settings → Integrations, and choose the site your checkout runs from at the top of the page.Pick Lemon Squeezy from the list of payment providers, then paste the API key and the store ID.Click Connect.
4

Confirm the connection

Lemon Squeezy shows as Connected, with your store name, its currency, and the last four characters of the key.Traceten stores the key encrypted. After this point it is never shown again, in the dashboard or in the API, and only those last four characters are readable back.

What Traceten does with the key

In the same request, Traceten:
  1. Reads the store’s name and currency, to confirm the key can see the store you named.
  2. Reads one order, to prove the key can actually see the revenue it is being connected for.
  3. Creates a webhook on your Lemon Squeezy account pointed at Traceten, subscribed to two events.
  4. Stores the key and the webhook signing secret, both encrypted.
  5. Starts importing your last 90 days of paid orders.
You can see the webhook Traceten created under Settings → Webhooks. These are the two events: order_created carries every payment, renewals included, because a Lemon Squeezy subscription renewal creates a new order. Every renewal is attributed to the AI source that won the customer, exactly like a first purchase. That is also why Traceten subscribes to neither subscription_payment_success nor any subscription_* event: the money is already on the order, and taking it from both places would count it twice. One limit worth knowing: a Lemon Squeezy order does not say which subscription it belongs to, so Lemon Squeezy renewals appear in your revenue totals and per-source breakdowns but not in the per-subscription lifetime value report.

The signing secret

Traceten generates the webhook signing secret and sends it to Lemon Squeezy when it creates the webhook. Lemon Squeezy never returns a webhook secret through its API, so the copy Traceten stores is the only one it will ever have. If that store fails for any reason, Traceten deletes the webhook it just created rather than leaving one behind that it could never verify. If you rotate the secret by hand in the Lemon Squeezy dashboard, Traceten stops accepting deliveries. Reconnect from the Traceten dashboard to provision a fresh one.

Keys Traceten will not accept

  • Stripe keys. Pasting one names the mistake rather than failing on a network call.
  • A key with no store ID. The connect form asks for both, and refuses with an explanation rather than guessing at a store.
  • A key with whitespace or a line break in it. Copy it again from Settings → API.

How attribution works

When an order is paid, Lemon Squeezy sends an order_created webhook to Traceten. Traceten then tries to tie the payment back to the originating session, in priority order:
  1. Checkout custom data: if you passed the visitor’s _traceten_vid cookie as traceten_visitor_id, Traceten matches it to the originating session exactly.
  2. Confirmation modal button: if you added ?order_identifier=[order_identifier] to the confirmation modal’s button link and the buyer clicks it, the Traceten snippet on that page reports the order identifier and Traceten matches it to the browser that completed the purchase. See below.
  3. Email hash: if the buyer’s session called traceten.identify({ email }), Traceten matches the order’s email (hashed, never stored) to that visitor.
  4. No match: the payment is still recorded so revenue totals stay complete, but it shows as unattributed (no AI source).
Orders with a status of pending, failed or refunded are not counted. A fully refunded order is skipped outright rather than counted and then taken back off, because there would be nothing to take it off with: the 90-day history import reads orders and never refunds, so importing one that was already refunded would add revenue that no later event ever removes. Only paid and partial_refund orders produce revenue. An order that was paid when Traceten recorded it and is refunded afterwards is a different case, and that one is reduced: see below.

Refunds and net revenue

Your attributed revenue is net of refunds. When an order_refunded event arrives, Traceten subtracts the refunded amount from the AI source the original order was attributed to.
  • The refund is dated on the day it was issued, not the day of the original order. A past day’s revenue figure never changes after the fact, and a day on which you refunded more than you took in reads as a negative number.
  • Conversion counts stay gross. A refunded order still counts as a conversion. The money is reported separately as a refunded figure beside the net one.
  • A partial refund subtracts only the part you returned. Lemon Squeezy reports refunded_amount as the running total refunded against the order, so a second partial refund subtracts only the difference rather than the whole new total. A partial_refund order keeps the share you kept.
  • A cancelled subscription is not a refund. Cancelling stops future charges. The charges already paid were earned and stay in your totals, so cancelling a subscription changes no figure in Traceten. Only an order_refunded takes money back off.
Traceten also ignores a delivery for an order created more than seven days ago. Lemon Squeezy’s signature carries no timestamp, so this is what stops an old delivery being replayed against your account; Lemon Squeezy’s own retries all happen well inside it.

Checkout overlay: attribute without writing code

A bare Lemon Squeezy checkout link or Buy Now button never goes through your server, so there is no place to attach custom data. Instead, have Lemon Squeezy hand the order identifier back to your own site, and let the snippet do the rest.
1

Connect Lemon Squeezy to Traceten

Follow the connection steps above. Traceten ignores a confirmation-page report for a site whose Lemon Squeezy store is not connected.
2

Open the product's confirmation modal settings

Lemon Squeezy dashboard, Products → your product → Edit → Confirmation modal.
3

Set the button link

Point it at a page on your site that has the Traceten snippet installed, and append the order_identifier parameter:
The square brackets are part of the syntax here, not a placeholder to fill in. Lemon Squeezy replaces [order_identifier] with the order’s unique identifier when it builds the button. Curly braces will not work.Use [order_identifier], not [order_id]. Traceten does not accept the numeric order id, because it counts up one order at a time and anyone could guess it.
4

Save, then buy something through the checkout

Complete a real purchase and click the button in the confirmation modal. The snippet reads order_identifier out of the URL, and the order appears against its AI source in Revenue, usually within a minute or two.
This is a button the buyer has to click, not an automatic redirect. Lemon Squeezy’s own docs say not to rely on the confirmation modal for order fulfilment for exactly this reason. Buyers who close the modal are never matched, so this path attributes a meaningful share of your Payment Link sales, not all of them. Checkout custom data, where you can use it, matches every order.
More things worth knowing:
  • You change nothing in your code. The only edit is the button link in Lemon Squeezy.
  • The order of events does not matter. Lemon Squeezy’s webhook usually reaches Traceten before the buyer clicks through. When that happens the order is recorded first and re-attributed the moment the browser reports in, on the original order’s own date.
  • The buyer has to click through within 30 minutes of paying. Traceten pairs a report with an order only when the two are no more than 30 minutes apart. A button clicked later than that is not matched, and the order stays as it was.
  • The page needs the snippet. If the button points somewhere the snippet is not installed, nothing is reported and the order stays unattributed.
  • Connecting comes first. Reports that arrive before your store is connected are discarded, not held until later. A report can also be discarded for up to a minute after you connect.
This path matches a browser, not a person. A confirmation link opened on a different device, or forwarded to somebody else, is not matched.

Passing the visitor ID through checkout

This is the most reliable attribution path, and the only one that works for a buyer who never identified themselves on your site. Pass the visitor’s pseudonymous Traceten identifier into the checkout as custom data.
In the dashboard, open Settings → Integrations, pick Lemon Squeezy and click Set up with AI. It copies a prompt for your coding assistant that wires the visitor ID into your checkout. The same card shows this site’s Visitor cookie name.
The robust way to get the value is window.traceten.getVisitorId(), called client-side and forwarded to whatever creates the checkout:
If you’d rather not change your client-side request shape, read the cookie directly server-side instead:
Do not hardcode this cookie name. It is per-site and only correct on your configured domain (not on localhost). Find the real one under Sites → Settings → Cookies → Visitor cookie name.
Lemon Squeezy returns the value as meta.custom_data on the webhook, and Traceten matches it back to the AI session that produced the visit. No personal data leaves your server on this path: the cookie value is pseudonymous and is not PII. If you use a hosted Lemon Squeezy checkout link instead, append the value as a query parameter:

What the 90-day import can and cannot match

Traceten imports your last 90 days of paid orders when you connect, so revenue from before the webhook existed is not lost. It reads newest first and stops paging at the first order older than 90 days. Lemon Squeezy’s orders endpoint has no date filter, so one page (the one straddling that boundary) is retrieved and parsed in full, including the buyer email addresses on the orders that turn out to be older than 90 days. Those orders are discarded in memory: not imported, not stored, not logged. No page beyond the boundary is requested. Those historical orders match by email only. Lemon Squeezy’s orders API does not return checkout custom data, so the visitor ID path above applies to live orders only. An imported order whose buyer never called traceten.identify({ email }) lands as unattributed.

Verify it worked

  1. Lemon Squeezy reads Connected in the dashboard.
  2. The import banner finishes, and the Revenue page shows historical orders.
  3. Place a real order (or a test-mode one in a non-production Traceten environment). It appears in Revenue within a minute or two.

Troubleshooting

“Lemon Squeezy would not let this key read the store’s orders.” The key cannot see the store you named. Confirm the store ID belongs to the same account as the key, and create the key with full access. “That store ID does not look right.” Traceten accepts only letters, digits, hyphens and underscores in a store ID, because the value goes into a URL. Copy the number from Settings → Stores. Connected, but revenue is not appearing. Check that the webhook under Settings → Webhooks is still there and pointed at Traceten. If you deleted it, reconnect from the Traceten dashboard. Everything shows as unattributed. Nothing is tying orders back to sessions. Either pass traceten_visitor_id through checkout, or call traceten.identify({ email }) when a visitor signs in. Test-mode orders are missing. Traceten drops test-mode orders in production, because their synthetic amounts would corrupt your revenue totals.

Next