Rekomi Docs
For developers
Developers

Tracking script & window.Rekomi

Install the Rekomi browser loader and read the referral context (affiliate + campaign) on page load, in real time.

The Rekomi tracking script (loader.js) does two things:

  1. Captures the click: reads the affiliate attribution param from the URL (?via=, ?ref=, ?fpr=, etc.) into localStorage on your domain (plus a cookie on the tracking host, which becomes first-party once you use a custom tracking domain) and records the click.
  2. Exposes window.Rekomi, a small JavaScript object so your site can read the referral context (the affiliate's name and the campaign name, not just a slug) on page load. This is what you use to show "Referred by …", or to capture the referring affiliate on your signup form in real time.

Migrating from Rewardful?

This is the direct replacement for reading window.Rewardful.affiliate / window.Rewardful.campaign at signup. window.Rekomi now exposes the same referral / affiliate / campaign shape, see Capture the affiliate + campaign on load.

Install

Paste this on every page of your site, in <head>:

<script async
  src="https://api.rekomi.com/api/v1/r/loader.js"
  data-program-id="{your_program_id}"
  data-rkmi-email-capture="auto"></script>
<noscript><img src="https://api.rekomi.com/api/v1/r/c.gif" alt="" width="1" height="1" referrerpolicy="no-referrer-when-downgrade" /></noscript>

Rekomi records an email a referred visitor types into any email or text field on the pages where the tag runs (signup, login, checkout and other forms) so the sale can be credited even when your checkout passes no referral. Nothing is recorded without a referral. Remove the data-rkmi-email-capture attribute to turn this off; explicit Rekomi.convert() calls still work.

The <noscript> beacon records the click for visitors who have JavaScript disabled. It takes no query parameters; the beacon reads the referral from the attribution params in the referring page's URL (the Referer header). Copy the exact snippet (with your real data-program-id and any custom attribution params) from Dashboard → Settings → Tracking → Website snippet. If you have a verified custom domain, the snippet loads from your own subdomain instead of api.rekomi.com.

The window.Rekomi object

Once the script loads it defines window.Rekomi. The slug is available immediately; the affiliate and campaign objects are filled by one lightweight async lookup, so read them inside ready().

Properties

PropertyTypeDescription
referralstring | nullThe affiliate's referral slug, e.g. "b7pa99hvx7zx". null if the visitor wasn't referred.
affiliate{ id, name } | nullThe referring affiliate's id + display name once resolved. null if no referral.
campaign{ id, name } | nullThe campaign's id + name once resolved. null if no referral.
subIdstring | nullThe channel tag on the affiliate's link (?sub=yt), normalized, from this landing URL or the stored one from the click that brought the visitor. null when untagged. See Sub-IDs.
clickIdstring | nullThe id of the click that brought this visitor, once the click endpoint has answered (stored with the slug for later page views). null until then.

Methods

MethodDescription
ready(callback)Runs callback(window.Rekomi) once the referral context is resolved. Fires immediately when there is no referral (or it's already resolved). Use this to read affiliate / campaign reliably.
getReferral()Returns the slug synchronously (URL param → localStorage → cookie), or null. Available instantly, no wait.
clearReferral()Clears the stored slug, tag and click id (localStorage) and the resolved referral / affiliate / campaign / subId / clickId in memory. The tracking-host cookie and any attribution param still in the page URL are not removed, so getReferral() may pick the slug back up.
convert(email) / convert({ email, name })Records a free signup as a lead tied to the current referral (posts to /api/v1/r/lead/signup, once per session, with the current subId so a later sale inherits the tag). No-op when there is no referral or no email. This is lead capture only; it never records a sale.
identify(...)Alias of convert(...).

affiliate.name can be null when the affiliate has not set a display name.

You can also let the loader capture the email from a form automatically: add data-rekomi-email to your email input, or set a data-email-selector attribute on the script tag pointing at your input, and the loader reads that value when firing the lead.

The tag Rekomi hands out carries data-rkmi-email-capture="auto" (or capture=auto on the script URL). In that mode 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 also sweeps the inputs of any submitted form, which is what covers an in-page checkout or a login step that never submits a form (beehiiv is the common case). It still records nothing without a referral, and it never sends the same email twice in a session. Remove the attribute to turn it off: without it the loader falls back to capture, which only reads the input named by data-email-selector or data-rekomi-email when a form is submitted, and that is what a site that installed an earlier tag still runs. On beehiiv, Kit, MailerLite, Ontraport and GoHighLevel the platform connection under Integrations credits sales from the platform's own signup record without this script; the capture mode then only covers readers who were already subscribed before they clicked. See Leads and sales from your platform.

Settings. Every setting has a URL form as well as an attribute form. Use the URL form whenever a tag manager injects the script: Google Tag Manager rebuilds the tag and drops every data- attribute, so an attribute-only tag loads Rekomi with no program id and no capture mode.

SettingAttributeURL formDefaultWhat it does
Programdata-program-idprogram=none, requiredThe campaign the click and any lead belong to.
Email capturedata-rkmi-email-capturecapture=auto in the tag Rekomi hands out; capture is the loader's fallback when the attribute is absentauto records a lead as soon as a referred visitor finishes typing an email into an email or text field and sweeps submitted forms. capture only reads the input named by data-email-selector or data-rekomi-email on form submit.
Email selectordata-email-selectoremailSelector=noneCSS selector of the email input the loader reads on form submit.
Attribution paramsdata-rkmi-paramsparams=a,bthe built-in list (via, ref, fpr and the rest)Custom attribution params saved under Settings > Attribution; the dashboard adds this to your snippet for you.
Pixel keydata-rekomi-orgorg=noneYour pixel public key, when your install uses one; the dashboard adds it for you.

Capture the affiliate + campaign on load

This is the recommended pattern to capture who referred a signup, client-side, the moment the page loads, no backend integration required:

<script>
  window.Rekomi.ready(function (R) {
    if (!R.referral) return; // visitor was not referred

    // R.referral  -> "b7pa99hvx7zx"
    // R.affiliate -> { id: "...", name: "Milo Okha" }                (or null)
    // R.campaign  -> { id: "...", name: "Viraly Affiliate Program" } (or null)

    myApp.setReferral({
      referral:      R.referral,
      affiliateName: R.affiliate ? R.affiliate.name : null,
      campaignName:  R.campaign  ? R.campaign.name  : null
    });
  });
</script>

Then send those fields to your backend when the user signs up. Because ready() waits for the lookup, affiliate.name and campaign.name are populated even if you read them right after page load.

Read affiliate/campaign inside ready()

getReferral() and R.referral (the slug) are synchronous. R.affiliate and R.campaign are filled after a short async lookup, if you read them on the bare window.Rekomi object immediately, they may still be null. Always read them inside a ready() callback.

Server-side alternative

If you'd rather resolve a slug from your backend, the same data is available from a public endpoint:

GET https://api.rekomi.com/api/v1/r/resolve?via=SLUG[&program=PROGRAM_ID]
{
  "referral": "b7pa99hvx7zx",
  "affiliate": { "id": "6be0bba5-…", "name": "Milo Okha" },
  "campaign":  { "id": "cd1a591e-…", "name": "Viraly Affiliate Program" }
}

Returns 404 for an unknown or suspended slug. The optional program param is your data-program-id; include it so account-level slugs resolve to the right program.

What's exposed (and what isn't)

Exposed client-side: the affiliate's display name and the campaign name, the same info shown on your public signup / recruiting pages. Not exposed: the affiliate's email or any other PII. Fetch those server-side from the authenticated REST API (e.g. the conversions feed returns affiliateEmail and stripeCustomerId).

Single-page apps

window.Rekomi persists across client-side route changes, so it's initialized once on the first page load. If your signup form mounts after a route change, register a ready() callback when that component mounts (or cache the values in app state on first load) rather than relying on the script re-running.

Conversion tracking

This script handles click attribution and the referral context only. Sales are tracked automatically by your payment processor (Stripe, Paddle, Braintree, Shopify, Lemon Squeezy, Chargebee, Polar, Recurly, Gumroad, Creem, Dodo Payments, Mollie) or via the S2S API. Leads (free signups recorded before payment) are captured automatically for Stripe, Paddle, Chargebee, Recurly, and Creem, with no extra code; on Polar, an attributed trial start also records a $0 lead automatically. Use Rekomi.convert() for freemium / free-plan signups that never create a billing object, for the remaining processors (Braintree, Shopify, Lemon Squeezy, Gumroad, Dodo Payments, Mollie), and for non-trial Polar signups. It records a free signup as a lead so a later upgrade is still credited to the affiliate even if the click cookie is gone. On Mollie, also pass the same email as billingAddress.email on the payment, since Mollie's hosted checkout runs no script and the sale is credited from the webhook. See Track leads and signups. On beehiiv, Kit, MailerLite, Ontraport and GoHighLevel the script is optional for attribution: the platform connection credits sales from the platform's own signup record, and the script adds click counts.