# Connect Lemon Squeezy

> Send Lemon Squeezy orders, subscription payments and refunds to Revfaro with a webhook, and pass the visitor to checkouts as custom data.

**In short:** Add a webhook in Lemon Squeezy for `order_created`, `order_refunded`, `subscription_payment_success` and `subscription_payment_refunded` pointing to your website's Revfaro address, with a signing secret you choose (and paste into Revfaro as well). Pass the visitor in the checkout's custom data; hosted checkout links and Lemon.js buttons on your pages are tagged by the script. Set each product's confirmation and receipt button to your site with `?order_identifier=[order_identifier]`.

You need a Lemon Squeezy store and a website in Revfaro with tracking installed. Open **Website settings › Setup**, go to **Connect payments** and choose the **Lemon Squeezy** tab.

These steps work with the script or [npm SDK](https://revfaro.com/docs/javascript-sdk/). With npm, initialize tracking on
checkout and return pages, and use your shared `tracker.attribution()` instead of
`window.revfaro?.attribution?.()` in browser examples. The SDK does not create a window global.

![The Lemon Squeezy tab of Connect payments with the webhook address and signing secret](https://revfaro.com/docs/img/payments-lemonsqueezy.webp 'Website settings › Setup › Connect payments › Lemon Squeezy.')

### Add the webhook in Lemon Squeezy

In Lemon Squeezy, go to **Settings › Webhooks** and add a webhook with your website's address from the Lemon Squeezy tab:

```text
https://revfaro.com/api/webhooks/lemonsqueezy/YOUR_SITE_ID
```

Select `order_created`, `order_refunded`, `subscription_payment_success` and `subscription_payment_refunded`. Add it in live mode: test-mode orders are acknowledged but never counted.

### Use the same signing secret in both places

Lemon Squeezy asks you to choose the webhook's signing secret, a random string of 6 to 40 characters. Click **Generate a secret** in the Lemon Squeezy tab to get one, enter the same secret in Lemon Squeezy, then click **Save** in Revfaro. The tab shows **Connected**.

### Pass the visitor to your checkout

When your server creates a checkout with the Lemon Squeezy API, add the visitor's cookies as custom data:

```ts checkout.ts
import { createCheckout } from '@lemonsqueezy/lemonsqueezy.js';

const jar = await cookies(); // next/headers

await createCheckout(STORE_ID, VARIANT_ID, {
  checkoutData: {
    custom: {
      rf_visitor_id: jar.get('rf_vid')?.value ?? '',
      rf_session_id: jar.get('rf_sid')?.value ?? '',
    },
  },
});
```

Calling the REST API directly? The same two keys go into `data.attributes.checkout_data.custom`.

### Send buyers back to your site

In each product's **Confirmation modal** and **Email receipt** settings, set the button link to a page on your site with the order number:

```text
https://example.com/thanks?order_identifier=[order_identifier]
```

Use the UUID `order_identifier`; sequential `order_id` values are not accepted for attribution because they can be guessed. Lemon Squeezy fills in `[order_identifier]`, and Revfaro links the order to whoever lands there, even without custom data. The page must load the script and must not be excluded.

## Using checkout links and Lemon.js

Hosted checkout links (`https://STORE.lemonsqueezy.com/checkout/buy/…`), including Lemon.js overlay buttons, need no code: the script adds `checkout[custom][rf_visitor_id]` and `checkout[custom][rf_session_id]` to them, which Lemon Squeezy saves as custom data.

Opening a checkout from your own code, such as `LemonSqueezy.Url.Open(url)`? Add the same parameters yourself:

```js
const { rf_visitor_id, rf_session_id } = window.revfaro?.attribution?.() ?? {};
const url = new URL('https://STORE.lemonsqueezy.com/checkout/buy/VARIANT');
if (rf_visitor_id) {
  url.searchParams.set('checkout[custom][rf_visitor_id]', rf_visitor_id);
  url.searchParams.set('checkout[custom][rf_session_id]', rf_session_id);
}
LemonSqueezy.Url.Open(url.toString());
```

## What Revfaro records

- **Orders**: `order_created`, including the first payment of a subscription.
- **Renewals**: `subscription_payment_success` is credited to the visitor who first subscribed.
- **Refunds**: `order_refunded` and `subscription_payment_refunded` are subtracted, partial refunds included.
- **Currency**: when your website's revenue currency is USD, orders paid in another currency are counted with Lemon Squeezy's USD amount.

Requests are checked against Lemon Squeezy's `X-Signature` header, so only your store can send payments to your website.

## Frequently asked questions

### Do Lemon Squeezy checkout links and Lemon.js overlays work?

Yes. The script adds the visitor as custom data (`checkout[custom][rf_visitor_id]`) to every `lemonsqueezy.com/checkout/buy/` link on your pages, including Lemon.js overlay buttons.

### Are Lemon Squeezy test-mode orders counted?

No. Test-mode events are acknowledged but never counted, so you can test your setup safely.

### My store sells products for several websites. What happens?

A Lemon Squeezy store sends every order to every webhook. Add the webhook to each website in Revfaro; a payment counts where its buyer was tracked, or where the same customer paid before. Orders with neither signal count on every website that has the webhook, so pass the visitor at checkout.

---

Source: https://revfaro.com/docs/lemon-squeezy/ · Last updated 2026-11-01
