Revenue Connectors · Lemon Squeezy

Connect Lemon Squeezy to Admaxxer

Forward Lemon Squeezy's order_created webhook to Admaxxer so every digital product, license-key purchase, and subscription first-payment shows up in your revenue attribution, blended MER, and cohort LTV. Five-minute setup, signed via the X-Signature header (HMAC-SHA256), visitors stitched via meta.custom_data.admx_visitor_id.

Open Revenue Settings Back to all connectors

1. Prerequisites

2. Create a Lemon Squeezy API key

  1. In the Lemon Squeezy dashboard, go to Settings › API › + Create API key.
  2. Name it Admaxxer Revenue Read.
  3. Copy the generated key and paste it into Admaxxer › Revenue Settings › Lemon Squeezy.
  4. Lemon Squeezy keys are scoped to the store; rotate the key from the same screen when needed.

3. Add the webhook endpoint

Lemon Squeezy will send signed webhook events to a single Admaxxer URL. Replace <YOUR_WEBSITE_ID> with the UUID shown in Revenue Settings.

https://admaxxer.com/api/pixel/webhooks/lemonsqueezy/<YOUR_WEBSITE_ID>
  1. In the Lemon Squeezy dashboard, go to Settings › Webhooks › + Add new webhook.
  2. Callback URL: paste your Admaxxer webhook URL.
  3. Signing secret: enter a strong random string (32+ chars). Save it — you'll paste it into Admaxxer next.
  4. Subscribed events:
    • order_created
  5. Recommended additional: order_refunded, subscription_payment_success.
  6. Click Save.
  7. Copy the signing secret and paste it into Admaxxer Revenue Settings › Lemon Squeezy › Webhook signing secret.

The signing secret is what makes the X-Signature header verifiable. Without it, Admaxxer rejects every inbound webhook with 401 invalid_signature.

4. Stamp the visitor ID on every checkout

Lemon Squeezy supports custom data on every checkout via URL parameters. Append checkout[custom][admx_visitor_id]=<visitor-id> to the checkout URL:

// Browser-side, when generating checkout link
const visitorId = window.admx.getVisitorId() || '';
const url = new URL('https://yourstore.lemonsqueezy.com/checkout/buy/PRODUCT_ID');
url.searchParams.set('checkout[custom][admx_visitor_id]', visitorId);
window.location.href = url.toString();

Lemon.js overlay flow

// If you use Lemon.js to open checkout in an overlay
LemonSqueezy.Url.Open(
  'https://yourstore.lemonsqueezy.com/checkout/buy/PRODUCT_ID' +
  '?checkout[custom][admx_visitor_id]=' + (window.admx.getVisitorId() || '')
);

Lemon Squeezy stores the value at meta.custom_data.admx_visitor_id on the resulting Order, which is what the order_created webhook payload includes.

5. Verify the connection

  1. In Lemon Squeezy, go to Settings › Webhooks and use the Test webhook button.
  2. Choose order_created and send.
  3. In Admaxxer, open Revenue Settings. The "Last 50 webhook deliveries" panel shows the test with status ok.
  4. Run a real test purchase in Lemon Squeezy test mode. Inspect the resulting Order and confirm meta.custom_data.admx_visitor_id is non-empty.
  5. Within 3 seconds, the order appears in the Admaxxer attribution dashboard, joined to the visitor's acquisition source.

6. Troubleshooting

Webhook returns 401 invalid_signature
Signing secret mismatch. Re-copy the signing secret you set on the Lemon Squeezy webhook into Admaxxer Revenue Settings. Note: it's the secret you choose on the LS side, not an LS-generated value.
Order appears as unattributed
meta.custom_data.admx_visitor_id was empty on the Order. Confirm the checkout URL had checkout[custom][admx_visitor_id]=... appended. Inspect the Order in the LS dashboard and check the custom_data section under meta.
Subscription renewals not appearing
Subscribe the same endpoint to subscription_payment_success. The first subscription payment fires order_created; renewals fire subscription_payment_success instead.
Refunds not subtracting from MER
Add order_refunded to the same endpoint. Admaxxer treats refunds as negative revenue events linked to the original order.

Frequently asked

Does this work for both digital products and subscriptions?
Yes. Lemon Squeezy fires order_created for one-time purchases (digital downloads, license keys) and the first transaction of a subscription. For ongoing subscription renewals, also subscribe to subscription_payment_success and Admaxxer will record each renewal as an additional revenue event linked to the same visitor.
Why is the visitor field nested under meta.custom_data instead of metadata?
Lemon Squeezy's API uses a meta object on the order which contains custom_data — the API field name they chose. So the path is meta.custom_data.admx_visitor_id, not metadata.admx_visitor_id. The Admaxxer Lemon Squeezy connector reads exactly this nested path, so make sure the value is set there (not at the top level).
How do I pass custom_data on a Lemon Squeezy checkout?
When constructing the Lemon Squeezy Checkout link or button, append checkout[custom][admx_visitor_id]=<visitor-id> to the checkout URL — Lemon Squeezy treats checkout[custom][...] params as custom_data and they end up at meta.custom_data on the resulting order. The Admaxxer pixel exposes window.admx.getVisitorId() so your client can build the URL on the fly.
How does X-Signature verification work?
Lemon Squeezy signs every webhook with HMAC-SHA256 using your endpoint's signing secret. The X-Signature header carries the hex-encoded HMAC of the raw request body. Admaxxer recomputes the HMAC, compares constant-time, and rejects mismatches with 401. Lemon Squeezy doesn't include a timestamp in the header, so we instead deduplicate on the order ID + webhook event_id to defeat replay.
What about license-key revocation on refunds?
Lemon Squeezy revocation is handled inside Lemon Squeezy itself — Admaxxer doesn't issue or revoke license keys, only records the revenue. The order_refunded event fires when a customer refunds; subscribe to it on the same endpoint to subtract refunded amounts from MER and cohort LTV.

Next steps