LemonSqueezy
Set up revenue attribution with LemonSqueezy.
LemonSqueezy
LemonSqueezy is a merchant of record that handles payments, taxes, and subscriptions. This guide shows how to pass EngageTrack visitor and session IDs through LemonSqueezy's custom_data field for revenue attribution.
How It Works
- The EngageTrack SDK generates a visitor ID and session ID (stored in browser storage, accessible via the SDK's JavaScript API)
- When creating a checkout, you pass these values in the
custom_datafield - After payment, LemonSqueezy sends a webhook to EngageTrack with the custom data
- EngageTrack reads the visitor ID and attributes the revenue to the traffic source
Checkout API
Node.js / Express
import { lemonSqueezySetup, createCheckout } from "@lemonsqueezy/lemonsqueezy.js";
lemonSqueezySetup({ apiKey: process.env.LEMONSQUEEZY_API_KEY });
app.post("/create-checkout", async (req, res) => {
// Receive visitor/session IDs from the client request body
const { engagetrack_visitor_id: visitorId, engagetrack_session_id: sessionId } = req.body;
const { data } = await createCheckout(process.env.LEMONSQUEEZY_STORE_ID, {
productOptions: {
redirectUrl: "https://yoursite.com/success",
},
checkoutData: {
custom: {
engagetrack_visitor_id: visitorId,
engagetrack_session_id: sessionId,
},
},
});
res.json({ url: data.data.attributes.url });
});Next.js App Router (Route Handler)
import { NextRequest, NextResponse } from "next/server";
import { lemonSqueezySetup, createCheckout } from "@lemonsqueezy/lemonsqueezy.js";
lemonSqueezySetup({ apiKey: process.env.LEMONSQUEEZY_API_KEY! });
export async function POST(request: NextRequest) {
// Receive visitor/session IDs from the client request body
const { variant_id, engagetrack_visitor_id, engagetrack_session_id } =
await request.json();
const visitorId = engagetrack_visitor_id ?? "";
const sessionId = engagetrack_session_id ?? "";
const { data } = await createCheckout(process.env.LEMONSQUEEZY_STORE_ID!, {
productOptions: {
redirectUrl: "https://yoursite.com/success",
},
checkoutData: {
variantId: Number(variant_id),
custom: {
engagetrack_visitor_id: visitorId,
engagetrack_session_id: sessionId,
},
},
});
return NextResponse.json({ url: data!.data.attributes.url });
}LemonSqueezy uses custom_data (accessed via the custom field in the SDK)
to pass arbitrary data through the checkout. EngageTrack expects the keys
engagetrack_visitor_id and engagetrack_session_id inside this object.
Checkout Links
If you use LemonSqueezy Checkout Links (no server code), append the custom data as URL parameters:
<a id="ls-checkout" href="https://yourstore.lemonsqueezy.com/buy/abc123">
Buy Now
</a>
<script>
document.addEventListener("DOMContentLoaded", function () {
const visitorId = window.engagetrack?.getVisitorId() || "";
const sessionId = window.engagetrack?.getSessionId() || "";
document
.querySelectorAll('a[href*="lemonsqueezy.com/buy"]')
.forEach((link) => {
const url = new URL(link.href);
url.searchParams.set(
"checkout[custom][engagetrack_visitor_id]",
visitorId,
);
url.searchParams.set(
"checkout[custom][engagetrack_session_id]",
sessionId,
);
link.href = url.toString();
});
});
</script>The URL parameter syntax for LemonSqueezy checkout links uses bracket
notation: checkout[custom][engagetrack_visitor_id]. This is how
LemonSqueezy maps URL parameters to the custom_data field.
Set Up the Webhook
- Go to LemonSqueezy Dashboard → Settings → Webhooks
- Click Add endpoint
- Enter the webhook URL:
https://api.engagetrack.net/api/v1/webhooks/revenue/lemonsqueezy/{YOUR_SITE_PUBLIC_ID}
- Under Events, select:
order_createdsubscription_payment_successorder_refunded
- Enter a signing secret and save it — you will need this when connecting LemonSqueezy in EngageTrack
- Click Save
If you connected LemonSqueezy via the EngageTrack dashboard (Site Settings → Revenue), the webhook is registered automatically and you can skip this step.
Verify
- Open your site and confirm the SDK is loaded by running
window.engagetrack.getVisitorId()in the browser console - Complete a test purchase using LemonSqueezy's test mode
- Go to your EngageTrack dashboard → Revenue tab
- The test payment should appear within a few seconds, attributed to your traffic source
If the payment appears without attribution:
- Check the LemonSqueezy webhook logs for delivery errors (LemonSqueezy Dashboard → Webhooks → select endpoint)
- Verify the
custom_datafield in the webhook payload containsengagetrack_visitor_id - Ensure the cookie values are non-empty when creating the checkout