Affiliate tracking

How a partner's click becomes a referral, and how that referral follows the person into Stripe so the partner is paid for every invoice.

You need three things in place:

  1. The affiliate program turned on in the dashboard (Affiliates), with Stripe connected.
  2. The browser script on your marketing site and your app (the same one-line install as Instrument your product).
  3. One of the checkout hand-offs below.

No redirects and no link shortener: a partner's link is your own URL with ?via=<token>.


Every partner gets a link like:

https://yourapp.com/?via=jane

When someone lands on any page carrying ?via= (or ?ref=), the script records the click and remembers the referral in a first-party cookie for the campaign's window (60 days by default). Clicks from search engines and from domains you blocked are not counted.

  • Sub-ids: https://yourapp.com/?via=jane&sub=youtube tags the referral for the partner's own reporting.
  • Vanity links: a partner can have more than one token, each landing on a different page (/pricing?via=jane-yt). Create them in the dashboard or with POST /affiliates/{id}/links.
  • First or last click: set per program. With first click, a second partner's link does not take over a referral that is still inside its window.

Extra parameter names

Moving from another affiliate tool whose links use a different parameter? Keep old links working by listing the names on the script tag:

<script async src="https://app.ranla.ai/t.js?key=stxk_…" data-key="stxk_…"
        data-ref-params="fpr,aff"></script>

Several domains

Marketing site on yourapp.com and checkout on app.yourapp.io? List the other domains and the script adds ?referral=<id> to links pointing there, so the visit carries over:

<script async src="https://app.ranla.ai/t.js?key=stxk_…" data-key="stxk_…"
        data-ref-domains="app.yourapp.io"></script>

To credit a partner on a page they did not link to (a dedicated landing page, a partner-specific pricing page), call:

stx.referralSource('jane')

2. Record the signup

After someone signs up, tell the script who they are. This turns the anonymous click into a lead tied to their email:

stx.identify({ email: user.email })
// or, the same thing under the name other affiliate tools use:
stx.referralSignup(user.email)

Call it on signup (and on login, which is harmless). If the campaign pays a lead bounty, the partner earns it when this signup makes their first payment.

No browser in the loop — a mobile app, an invite flow, a form handled entirely on your server? Record the referral with the API instead:

curl -X POST https://api.ranla.ai/affiliate-referrals \
  -H "Authorization: Bearer $RANLA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"token":"jane","email":"[email protected]"}'

See Affiliates API → Server-side referral tracking.


3. Hand the referral to Stripe

Once the person pays, Stripe is where the commission comes from. Any one of these links a Stripe customer to the referral. They are checked in this order, and the first partner to claim a customer keeps them.

Links to https://buy.stripe.com/… on a page with the script get client_reference_id added for you. Nothing to wire.

Stripe Checkout — client_reference_id

window.stx.referral holds the current referral id (an empty string when there is none). Pass it when you create the Checkout Session. Wait for it with stx.ready:

stx.ready(async () => {
  const res = await fetch('/api/checkout', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ priceId, referral: window.stx.referral }),
  })
  window.location = (await res.json()).url
})
// server
const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  line_items: [{ price: priceId, quantity: 1 }],
  client_reference_id: referral || undefined,
  success_url: 'https://yourapp.com/welcome',
})

Custom subscriptions — metadata.ranla_referral

Creating customers or subscriptions yourself? Put the referral id (or the partner's link token) in metadata on the customer, subscription or invoice:

await stripe.customers.create({
  email,
  metadata: { ranla_referral: referral },
})

Server-rendered forms — hidden inputs

The script fills any input marked data-stx-referral with the referral id, so it arrives with the form post:

<form method="post" action="/signup">
  <input type="email" name="email" />
  <input type="hidden" name="referral" data-stx-referral />
  <button>Start free trial</button>
</form>

Store it and pass it to Stripe as client_reference_id or metadata.ranla_referral.

Same email

If none of the above is present, a Stripe customer whose email matches a lead's email is attributed to that lead.

Coupon codes

Each partner can have their own promotion code (JANE20). A customer who pays with it is attributed to that partner even without a click — useful for podcasts, videos and offline mentions. On a page the partner linked to, stx.coupon holds the partner's code as { id, code, label } (stx.coupon.code is the text to show) and stx.affiliate their name, so you can show "Jane's 20% discount is applied".


Excluding payments

Add metadata.ranla = "false" to a Stripe customer, subscription or invoice and it never earns a commission — for internal accounts, partner deals you pay separately, or refunds you settle by hand.


What gets flagged

A referral is still recorded, but earns nothing, when:

  • the person has the partner's own email, or the same company email domain (self-referral);
  • the customer is already attributed to another partner (duplicate);
  • the signup arrived after the cookie window ended (expired);
  • the partner is suspended.

Flagged referrals show in the dashboard for review.


Checking it works

  1. Open https://yourapp.com/?via=<a partner's token> in a private window.
  2. In the console, stx.referral should be a non-empty id.
  3. Sign up with a test email. The partner's page in the dashboard shows the lead within a few seconds.
  4. Pay with a Stripe test card. The commission appears after the next Stripe sync (every 15 minutes), pending until its hold ends.

Also see: Affiliates API · Webhooks