Rekomi Docs
For developers
Developers

Track leads and signups

Capture a free identified signup (an email tied to the referral) before payment, so a later sale is still credited to the affiliate even if the click cookie is gone. Automatic for Stripe, Paddle, Chargebee, Recurly, and Creem; optional for everything else.

A lead is a free identified signup: an email tied to a referral, recorded before any payment. Recording a lead buys you two things:

  1. Durable email-match attribution. When the same email later pays, the sale is credited to the referring affiliate even if the click cookie was cleared, blocked, or expired in the meantime.
  2. A Visitor → Lead → Sale funnel. Free signups become a real acquisition stage in your dashboard and insights, not just clicks and sales.

A lead does not mint a commission on its own. It records email + name against the referral; the commission still happens when the paid sale comes through your processor or the S2S API.

Enabled by default

Lead tracking is enabled for every brand by default. The automatic capture below and the browser / S2S endpoints work as soon as the tracking loader is installed.

Identifying a lead vs earning a per-lead reward (CPL)

Recording a lead (identifying a referred signup by email) is live for every brand today. Paying affiliates for leads is a separate leg of the campaign: tick Leads under What do you pay affiliates for? on the campaign form and set the per-lead rate (see Pay per click or lead). This page covers lead identification so a later sale still credits the affiliate; it does not mint a commission on the signup itself.

Automatic for Stripe, Paddle, Chargebee, Recurly, and Creem

For Stripe, Paddle, Chargebee, Recurly, and Creem, leads are captured automatically, with zero brand code. You need nothing beyond what you already have:

  • the normal tracking loader (loader.js) on your site, and
  • your existing processor connection.

When a referred visitor signs up for a subscription or a free trial, Rekomi records a lead straight from the processor webhook your brand already receives. No convert() call, no signup form wiring. The first real payment is then recorded as the Sale, and it is attributed back to the same affiliate (the paid charge matches the lead by customer history).

Free and 100%-off coupon signups count as leads

This includes free / fully-discounted coupon signups. When a referred visitor redeems a 100%-off (or otherwise fully discounting) coupon, the subscription is created but no paid invoice ever fires. Rekomi still records that signup as a lead, so it shows up in your funnel even if the customer never pays. The coupon's redemption count still increments and the lead is attributed to the affiliate who owns the code.

Which processors capture leads automatically?

ProcessorAutomatic leads?How to capture a lead
StripeYesAutomatic on subscription / trial signup. No code.
PaddleYesAutomatic on subscription / trial signup. No code.
ChargebeeYesAutomatic on subscription / trial signup. No code.
RecurlyYesAutomatic on subscription / trial signup. No code.
CreemYesAutomatic on subscription / trial signup. No code.
BraintreeNoUse Rekomi.convert().
ShopifyNoUse Rekomi.convert().
Lemon SqueezyNoUse Rekomi.convert().
PolarTrials onlyAutomatic on trial start (the trial's $0 order records a $0 lead). Use Rekomi.convert() for non-trial signups.
GumroadNoUse Rekomi.convert().
Dodo PaymentsNoUse Rekomi.convert().
MollieNoUse Rekomi.convert(). The sale is matched to the lead by the buyer email: billingAddress.email on the payment, or the email on the Mollie customer record when the payment carries none (a token created before customers.read was added to the Mollie permission list cannot read it, so reconnect with a fresh seven-permission token).

Leads are captured automatically, with zero code, for Stripe, Paddle, Chargebee, Recurly, and Creem: when a referred visitor starts a subscription or trial, the processor webhook records the lead. For Braintree, Shopify, Lemon Squeezy, Gumroad, Dodo Payments, and Mollie there is no automatic lead capture; Rekomi does not receive a usable pre-payment signup event for them, so capture those leads with Rekomi.convert() in the browser instead. On Mollie, also pass the same email as billingAddress.email on one-time payments (or stamp metadata.rekomi_ref on them): the hosted checkout runs no script, so the sale arrives through the webhook and the email is what matches it to the lead; a payment that belongs to a Mollie customer is matched by that customer record's email instead. Polar sits in between: an attributed trial-start subscription automatically records a $0 lead (the trial's $0 order carries the referral), but non-trial checkouts have no pre-payment signup event, so capture those with Rekomi.convert(). The S2S lead endpoint is reserved for organizations without a native processor connection: while Stripe (via the Rekomi app for Stripe), Paddle, Braintree, Lemon Squeezy, Chargebee, Polar, Recurly, Gumroad, Creem, Dodo Payments, Mollie, or the Shopify app is connected, it returns a 409 (*_connect_active) to keep one conversion source per workspace.

Browser method: Rekomi.convert()

The browser Rekomi.convert() call records a lead at account creation. With Stripe, Paddle, Chargebee, Recurly, and Creem you do not need it for subscription / trial signups; those are already automatic. It is the primary lead path in the cases below.

Freemium and free plans

If your product has a free tier where signing up does not create a Stripe or Paddle subscription or customer, there is no processor event for Rekomi to turn into a lead automatically. This is roughly half of SaaS, so for those products Rekomi.convert() is the main way leads are captured, not a fallback.

Call Rekomi.convert({ email }) at account creation, the moment the free account is made:

Rekomi.convert({ email: "user@example.com" });

Pass the same email the customer will use for billing. When that free user later upgrades to a paid plan, Rekomi matches the sale back to this lead by email (the email-match attribution below), so the referring affiliate is still credited even though the click cookie is long gone. This is what carries attribution across the free-to-paid gap, which can be weeks or months:

Visitor (click) -> free signup (lead via convert) -> later upgrade (sale, email-matched to the lead)

Other cases for convert()

Rekomi.convert() is also the right tool for:

  • Braintree, Shopify, Lemon Squeezy, Gumroad, Dodo Payments, and Mollie, where Rekomi does not capture a lead automatically, so convert() is how you record the signup (on Mollie, pass the same email as billingAddress.email on one-time payments so the sale matches the lead). On Polar, trial starts already record a $0 lead automatically; convert() covers non-trial signups.
  • Capturing the lead earlier or richer: at the signup form, before checkout, or together with a name.

If you cannot run your own code on the page (a hosted platform such as beehiiv), use the loader attribute described in Three ways to record a lead in the browser instead. On beehiiv, Kit, MailerLite, Ontraport and GoHighLevel you may not need a lead at all: the platform connection credits sales from the platform's own signup record and pushes tagged signups to Rekomi as leads; see Leads and sales from your platform.

This is also the direct replacement for Rewardful's rewardful('convert', { email }), which makes it the easy path for teams migrating from Rewardful.

After the tracking script (loader.js) is installed, call Rekomi.convert(...) at signup, the moment a user creates an account:

Rekomi.convert({ email: "user@example.com", name: "Jane Doe" });

name is optional. There is also an identify alias and a string shorthand, all equivalent:

Rekomi.identify({ email: "user@example.com", name: "Jane Doe" });
Rekomi.convert("user@example.com");

The call posts to /api/v1/r/lead/signup and is a no-op when there is no referral context or no email, so it is safe to call unconditionally. To be explicit and only fire for referred visitors, wrap it in a ready() callback:

Rekomi.ready(function (R) {
  if (!R.referral) return; // visitor was not referred, nothing to record

  Rekomi.convert({
    email: signupForm.email,
    name: signupForm.name,
  });
});

ready() waits for the referral context to resolve, so you can read R.referral reliably before deciding whether to record the lead. See the full window.Rekomi API for referral, affiliate, campaign, and ready().

Migrating from Rewardful?

Rekomi.convert({ email }) is the direct replacement for rewardful('convert', { email }). The semantics match: a free signup is recorded as a lead, and the paid charge is the conversion. On Stripe, Paddle, Chargebee, Recurly, and Creem you can often drop the call entirely, since the lead is captured automatically.

Three ways to record a lead in the browser

All three run on top of the tracking loader. Pick the one that matches where the email is typed.

  1. window.Rekomi.convert({ email }) from your own code. Use it when you control the signup flow: call it the moment the account is created, as shown above. It is the most precise option and the only one that can pass a name.
  2. data-email-selector on the loader tag, for a classic HTML form submit. Point it at your email input, or add data-rekomi-email to the input itself. The loader reads that value when the form is submitted, so you write no code.
  3. data-rkmi-email-capture="auto" on the loader tag, on by default in the tag Rekomi hands out. The loader records the lead the moment a referred visitor finishes typing an email into any email or text field (on change or focus-out), and it also sweeps the inputs of any submitted form, so it covers hosted platforms and in-page checkouts where the page never submits a form: a platform login step that is a plain text field, or a checkout that runs inside a pricing block. This is what lets a sale be credited even when your checkout passes no referral. Remove the attribute to turn it off; explicit Rekomi.convert() calls still work, and the loader falls back to the submit-based capture in option 2. On beehiiv and Kit this is optional once the platform connection has Credit sales on: it then only covers readers who were already subscribed before they clicked.
<script async
  src="https://api.rekomi.com/api/v1/r/loader.js"
  data-program-id="{your_program_id}"
  data-rkmi-email-capture="auto"></script>

If you added a separate lead-capture snippet from an earlier version of a Rekomi install guide, delete it; the attribute replaces it.

The same guarantees apply to all three. Nothing is recorded without a referral, each email is sent once per browser session, and the server dedups. Plus-addressed variants of one inbox (you+test@gmail.com and you@gmail.com) count as the same person for matching.

On a hosted platform without a Credit sales connection, a purchase that reaches Rekomi with no matching lead does not appear as a sale. If that happens, check two things: the loader tag carries the attribute, and the email was typed on a page where the loader runs. On beehiiv, Kit, MailerLite, Ontraport and GoHighLevel the platform lookup runs after the lead match, so the sale can still be credited without a lead.

Server-to-server method

When signups happen on your backend, record the lead server-side instead:

POST /api/tracking/lead

It uses the same authentication as the S2S sale postback: a Authorization: Bearer rk_live_* API key plus an X-Rekomi-Signature HMAC-SHA256 header. The signing computation is identical to the sale endpoint, so reuse the same helper. See Server-to-server tracking for the signing details and code in Node.js, Python, and other languages.

The endpoint requires a Starter or higher plan (14-day trials accepted; lower tiers get 402 plan_tier_required) and an approved affiliate (a non-approved affiliate returns 400 affiliate_not_active). An optional programId body field disambiguates account-level slugs that span multiple campaigns.

Body:

{
  "affiliateSlug": "jane-recommends",
  "email": "user@example.com",
  "name": "Jane Doe",
  "externalEventId": "signup_abc123"
}
  • affiliateSlug (required): the affiliate to credit. From the affiliate's tracking URL. Matched case-insensitively, so SERKAN and serkan credit the same affiliate.
  • email (required): the customer's email. This is what a later sale is matched against.
  • name (optional): the customer's display name.
  • externalEventId (optional): your unique id for this signup. Used for de-duplication, so retries are safe. Omit it unless you need your own retry key: without it, duplicate signups for the same affiliate and email collapse into one lead across the browser, server, and webhook paths. Supplying your own id keys the lead on that id instead, so the same person recorded through both the browser and a backend call with a custom id can become two lead rows.

Use the S2S path whenever the signup originates on your server, you can keep a secret server-side, and your workspace has no native processor connection. While Stripe (via the Rekomi app for Stripe), Paddle, Braintree, Lemon Squeezy, Chargebee, Polar, Recurly, Gumroad, Creem, Dodo Payments, Mollie, or the Shopify app is connected, this endpoint returns 409 with the matching *_connect_active error (one conversion source per workspace); capture leads with Rekomi.convert() there instead. It is the right path for gateways you drive entirely over S2S.

MCP method

For AI-assistant and automation flows, the MCP server exposes a record_lead tool. Inputs: affiliateSlug, email, optional name, and optional campaignId. It records a signup lead the same way the browser and S2S paths do.

How attribution works

Email-match is a fallback only. It never overrides an attribution Rekomi already has. The resolver tries, in order:

  1. Coupon-code override
  2. Processor metadata (e.g. the Stripe rekomi_affiliate_id) or any other referral passed on the payment
  3. Prior conversion by customer history
  4. Coupon
  5. An email match against a recorded lead (this page)
  6. The platform lookup, on beehiiv, Kit, MailerLite, Ontraport and GoHighLevel connections with Credit sales on (the section below)

Only when all of steps 1 to 4 miss does Rekomi fall back to matching the sale's email against a recorded lead, and only when that misses too does it ask the platform. Step 5 runs the same way on every gateway Rekomi receives sales from over its API (Stripe, Paddle, Braintree, Chargebee, Polar, Recurly, Creem, Dodo Payments, Lemon Squeezy, Gumroad and Mollie) and on the beehiiv, Kit, MailerLite, Ontraport and GoHighLevel connections. The lead match is:

  • Second to a passed referral. A referral the payment already carries always wins. The email match only fills in when the sale arrived with none.
  • Scoped to your own workspace. A lead in one workspace can never credit a sale in another.
  • Aged to 90 days. A sale is matched only against a lead recorded within the last 90 days; the newest qualifying lead wins.
  • Not for an affiliate's own purchase. When the buyer email is the email of the affiliate the lead points to, the match is skipped and the sale is not credited. Two paths keep their earlier behaviour and credit that sale: Stripe, and sales recorded through the platform connections (Kit Commerce purchases, Ontraport transactions and GoHighLevel orders).
  • Read from the Mollie customer when the payment has no email. A Mollie payment created without billingAddress.email is matched by the email on its Mollie customer record instead, when the payment belongs to a Mollie customer. Reading it uses the customers.read permission, one of the seven the Mollie connection asks for; a token created before customers.read was added does not carry it, so a brand that connected earlier reconnects with a fresh seven-permission token and passes billingAddress.email on the payments it creates itself until then.

Because it runs after every processor-native step, existing attribution is unchanged and sales are never mis-credited. For the automatic processor path (Stripe, Paddle, Chargebee, Recurly, Creem), the later paid charge already attributes by customer history (step 3 finds the lead row by customer id), so email-match is not even needed for the same-customer case. Brands not using leads see no difference at all.

Leads and sales from your platform

On beehiiv, Kit, MailerLite, Ontraport and GoHighLevel, the CRM connection under Integrations does two jobs, each with its own switch: Sync affiliates into the platform, and Credit sales through the platform. With the second switch on (it is on by default):

  • Every affiliate link Rekomi hands out carries utm_source=rekomi and utm_campaign set to the affiliate's link slug, for example https://newsletter.example.com?via=jane&utm_source=rekomi&utm_campaign=jane. The platform stores those values on the person at signup: beehiiv, Kit, Ontraport and GoHighLevel natively, MailerLite in one custom field named Rekomi affiliate tag that the Rekomi loader fills from the link.
  • When a sale reaches Rekomi with no affiliate named by steps 1 to 5 above, Rekomi looks the buyer up on the platform by email, reads the stored tag, and credits the affiliate. It is the last step of the resolver, it runs inside a three-second budget, and it can never delay or fail the sale itself. If the platform is slow or has not created the person yet, Rekomi retries a few times over the next two hours and credits the sale once at most.
  • Where the platform can send them, tagged signups reach Rekomi as leads too: beehiiv (Scale plan and above), Kit, MailerLite and Ontraport through webhooks Rekomi registers when you connect, GoHighLevel through a workflow webhook you add. Those leads collapse into the same row as a lead recorded by the loader or the S2S endpoint, so nothing is counted twice.
  • A lead you recorded yourself still wins: step 5 runs before the platform lookup.

Where the sale itself comes from differs by platform. beehiiv and MailerLite sales arrive through the Stripe account you connect under Setup (for beehiiv, the account beehiiv created for paid subscriptions). Kit Commerce sales arrive through a purchase feed Rekomi registers with Kit. Ontraport sales arrive through the Ontraport connection itself. GoHighLevel recurring products arrive through your connected Stripe, and one-time order forms or non-Stripe gateways through a workflow webhook.

Flodesk has nowhere to store the tag, so its connection has no Credit sales switch; use the loader and a connected gateway there. The prerequisites, the status line, the Check a subscriber's email box and the limits (the main one: beehiiv and Kit write the arrival once, so a subscriber who joined before clicking is not credited by the lookup) are on each platform's page: beehiiv, Kit, MailerLite, Ontraport, GoHighLevel.

Where leads show up

Once leads are flowing, the dashboard surfaces a Visitor → Lead → Sale funnel and lead counts alongside clicks and conversions, in the campaign's Performance tab, Leads section, and in Reports. The funnel stage appears adaptively: brands that never record a lead do not see an empty Lead row.