Why LS for indie SaaS
Lemon Squeezy fits indie SaaS because it removes the part of billing that usually slows down tiny teams. As merchant of record it takes responsibility for tax collection, invoicing, and a lot of international payment complexity that would otherwise pull a founder into compliance work instead of product work. That is especially useful when the team is one founder or a very small engineering group that needs a checkout that simply works across markets without building a billing operations layer from scratch.
The tradeoff is that hosted merchant-of-record checkout can make attribution feel more fragmented if you only rely on browser tracking. TrackLayer fixes that by treating Lemon Squeezy webhooks as the source of revenue truth after checkout. The app captures identity and click context before handoff, Lemon Squeezy confirms the commercial event, and TrackLayer converts that payload into one canonical server-side stream for ad platforms, analytics, and internal revenue reporting.
Prerequisites
A live Lemon Squeezy account with products, variants, and subscription billing already configured.
Access to Lemon Squeezy webhooks and the signing secret for the workspace that owns checkout.
A TrackLayer workspace with permission to configure inbound sources and inspect `/events`.
A product or app flow that already captures first-party identifiers such as email, user ID, click IDs, or referral codes before checkout.
Setup
Create the TrackLayer webhook destination in Lemon Squeezy
In Lemon Squeezy, create one webhook destination per environment and point it directly at TrackLayer. This keeps the billing platform as the source of truth for cash events while TrackLayer becomes the canonical delivery layer for attribution, enrichment, and downstream retries.
Lemon Squeezy → Settings → Webhooks
Endpoint URL:
https://edge.tracklayer.io/v1/webhooks/lemonsqueezy
Environment:
production
Signing secret:
store in TrackLayerSubscribe to the minimum event set that changes revenue state
Do not ingest every available webhook just because it exists. Start with the events that actually change attributable revenue or subscription state. For most indie SaaS teams that means the first order, subscription creation, successful rebill, and cancellation state transition.
order_created
subscription_created
subscription_payment_success
subscription_cancelledAttach identity before the hosted checkout begins
Merchant of record checkout is simpler operationally, but it means your app has to hand off identity cleanly before the user leaves. Pass email, external user ID, campaign parameters, and any internal plan context into the Lemon Squeezy checkout creation flow so TrackLayer can later join the webhook back to the acquisition session.
TrackLayer pre-checkout payload
email → captured
external_id → app_user_8421
utm_source → newsletter
click_id → fb.1.171234567890
plan → pro-monthlyVerify canonical events inside TrackLayer before forwarding downstream
Run a real or low-value test purchase, then inspect TrackLayer first. Confirm the webhook signature, event ID, value, currency, customer identifiers, and subscription identifiers are correct. Only after that should you trust what Meta or Google receives, because wrong value logic compounds fast in bidding systems.
Expected canonical flow
order_created → purchase
subscription_created → subscription_started
subscription_payment_success → subscription_renewed
subscription_cancelled → subscription_cancelledEvent mapping
Lemon Squeezy webhook names are implementation detail. TrackLayer should expose a stable business vocabulary so downstream tools do not have to care whether the value came from the initial order or a later rebill. That translation layer is what keeps Meta, Google, internal dashboards, and lifecycle reporting aligned even if billing logic evolves later.
| Lemon Squeezy event | TrackLayer canonical event | Mapping intent |
|---|---|---|
| order_created | purchase | Initial paid order or first transaction created by checkout |
| subscription_created | subscription_started | New subscriber becomes active with plan and customer context |
| subscription_payment_success | subscription_renewed | Recurring payment succeeds and should count as retained revenue |
| subscription_cancelled | subscription_cancelled | Subscription is set to end or stop renewing |
Affiliates tracking
Lemon Squeezy already includes an affiliate system that is useful for indie SaaS teams leaning on creators, niche newsletters, or partner referrals instead of running only paid media. The basic dashboard is enough to pay commissions, but it is rarely enough for full attribution analysis because affiliate performance ends up isolated from paid search, paid social, organic, and product funnel data.
TrackLayer closes that gap by preserving affiliate context as part of the same identity and revenue record used for server-side conversion events. If the Lemon Squeezy checkout carries partner or referral metadata, TrackLayer can attach it to the customer, first purchase, and later renewals. That means a referred subscriber is not just visible as one conversion in the affiliate dashboard. You can see whether that partner drives higher retention, lower churn, better expansion, or stronger blended payback than paid acquisition channels.
In practice, the strongest setup is to capture the referral code or affiliate identifier before checkout, pass it through the Lemon Squeezy session, and let TrackLayer merge it with click identifiers and internal user IDs. Revenue from the initial order and every successful subscription payment can then retain partner attribution. For founder-led growth this matters a lot, because the question is usually not just who drove the first sale. It is which partner or content source keeps producing subscribers who stay active and keep paying.
affiliate_id → checkout metadata → Lemon Squeezy webhook
click_id → TrackLayer identity graph → attributed referral revenue
subscription_payment_success → renewal value stays linked to partnerCommon questions
Why use Lemon Squeezy instead of billing directly in Stripe for an indie SaaS?
Because Lemon Squeezy removes a lot of merchant overhead. As merchant of record it handles sales tax, VAT, invoicing, and international checkout complexity that would otherwise land on a very small team. For many solo founders that operational simplicity matters more than owning every billing surface.
Do I still need client-side tracking if TrackLayer receives webhooks?
Yes. Webhooks close the revenue loop, but they do not replace click capture, landing-page context, signup events, or product analytics. The clean pattern is client and backend context before checkout, then Lemon Squeezy webhooks for confirmed server-side revenue after checkout.
Should renewals be sent to ad platforms or only stored internally?
Usually both, if the destination supports repeated value-bearing conversions and your optimization model depends on retained revenue. TrackLayer can keep the full lifecycle internally while selectively forwarding renewal value to the platforms that should learn from long-term customer quality.
How do I avoid double counting the first payment?
Choose one canonical purchase moment. Some teams map only `order_created` as the first purchase and reserve `subscription_created` for lifecycle state without value. Others treat subscription creation as the source of truth. The key is consistency, stable event IDs, and deduplication inside TrackLayer before anything is forwarded.
Can this work for affiliates and creators, not just paid ads?
Yes. Lemon Squeezy affiliate metadata can be preserved as partner attribution, while TrackLayer stores the same customer and revenue events in one normalized stream. That lets you compare affiliate revenue, paid media, content, and direct traffic without each source living in a separate reporting silo.
Related implementation guides
Stripe webhook bridge
Compare the merchant-of-record flow to a direct Stripe webhook architecture.
Read guide →Subscription events
Define a canonical lifecycle across starts, renewals, recoveries, and churn.
Read guide →Meta CAPI setup
Route normalized TrackLayer events into Meta with stable IDs and value logic.
Read guide →