Get started

Install tracking

With Stripe connected, the script is the only install step. It records affiliate clicks, keeps the referral in a first-party cookie, catches signups from your forms, and hands the referral to Stripe checkouts. It is under 5 KB and has no dependencies.

Add the script#

Put this tag on every page of your marketing site and your app, ideally in the <head>. Copy your own from Settings → Install; it already has your public key in it.

HTML

<script async src="https://kickrail.com/api/kr.js?k=YOUR_PUBLIC_KEY"></script>

The public key (pk_kr_...) only identifies your program. It is safe in page source. Never put your server key (sk_kr_...) in the browser.

An affiliate link is any page on your site with the affiliate's token in the query string:

https://yourapp.com/?via=jane
https://yourapp.com/pricing?via=jane
https://yourapp.com/blog/launch?ref=jane&utm_source=youtube

Kickrail listens for via and ref by default. Change the list in Settings → Program → Link parameters; the first one is used when Kickrail builds links for affiliates. Tokens are matched without regard to case.

Affiliates can also make extra links with their own tokens and landing pages from their portal, if you leave "Let affiliates create extra links" on. Those resolve to the same affiliate.

What happens on a click#

  1. The script generates a click id like kr_7Hq2... (20 random characters after kr_).
  2. It stores two cookies, kr_ref (the click id) and kr_via (the token), plus a copy in localStorage. Cookies are set on the widest domain your browser allows, so www.yourapp.com and app.yourapp.com share them.
  3. It sends the click to Kickrail with the page URL and the HTTP referrer, using sendBeacon so it survives an immediate navigation.
BehaviourDefaultNotes
Cookie lifetime60 daysSettings → Program → Cookie window (1 to 365 days). A return visit refreshes it.
Two affiliatesfirst touchBefore signup the last click wins. Once they sign up, the first affiliate keeps them. Switch Settings → Program to last touch and a newer link click or code moves them to that affiliate, until their first payment; after that they stay put. A move sends referral.updated.
Cookie flagsSameSite=LaxPlus Secure on https pages.

Where the referral goes#

Once a visitor has a referral, the script attaches it automatically, including to elements added later (it watches the page for changes).

Every <a href="https://buy.stripe.com/..."> gets client_reference_id=kr_... appended. Stripe passes it to the checkout session, and Kickrail credits the purchase. Nothing to change on your side.

Pricing tables and buy buttons

<stripe-pricing-table> and <stripe-buy-button> get a client-reference-id attribute.

Signup forms, automatically

When a referred visitor submits any form with an email field, like your signup form, the script reports that email to Kickrail. When that person later pays in Stripe with the same email, the affiliate earns the commission. You don't write any code for this.

  • Only visitors who arrived through an affiliate link are reported, once per email.
  • Login forms (a password field with autocomplete="current-password") are skipped.
  • A signup caught this way only takes a Stripe customer created after it. An existing customer who clicks an affiliate link and then logs in is not credited.
  • It never pays a lead bounty, since the form could be a newsletter box. Report signups yourself (below) if you pay per signup.
  • Add data-kickrail-ignore to a form to leave it out.

Your own forms, by hand

Add data-kickrail to a signup or checkout form and the script adds a hidden field named kickrail_referral. Read it on your server and pass it to the referrals API or to Stripe.

HTML

<form action="/signup" method="post" data-kickrail>
  <input name="email" type="email">
  <button>Create account</button>
  <!-- added by Kickrail: <input type="hidden" name="kickrail_referral" value="kr_..."> -->
</form>

Checkout sessions you create (optional)

If your server creates Stripe Checkout sessions or customers, you can pass the cookie value along. This is the most exact match and wins over the automatic email match. Kickrail reads all of these:

Node

stripe.checkout.sessions.create({
  client_reference_id: req.cookies.kr_ref,
  // or: metadata: { kr_ref: req.cookies.kr_ref }
  // ...
});

stripe.customers.create({
  email,
  metadata: { kr_ref: req.cookies.kr_ref }, // kr_via (token) and kr_code (creator code) also work
});

Who referred them, in Stripe

Once a referral is tied to a Stripe customer, Kickrail writes the referrer onto that customer's metadata, so you can see it in the Stripe dashboard and read it in your own code. It is updated if the referral moves to another affiliate.

KeyExampleValue
kickrail_referralref_8Kd2...The referral id
kickrail_affiliateaff_3Xp9...The affiliate id
kickrail_affiliate_tokenjaneThe affiliate's link token, the jane in ?via=jane
kickrail_campaigncmp_Q7f1...The campaign id

With a restricted key this needs Customers: Write. Keys made before this was added only have Read, so the metadata is skipped; everything else keeps working. Connecting with Stripe (OAuth) covers it.

The browser API#

The script defines window.Kickrail:

MemberTypeDescription
referralstring | nullThe click id (kr_...), or null when the visitor was not referred.
tokenstring | nullThe affiliate token from the link.
attach()functionRe-run the Payment Link, pricing table and form tagging by hand.
convert({ email })PromiseReport a signup from the browser by hand, for signups that aren't a plain form submit. Unlike the automatic capture it isn't limited to new Stripe customers. Ad blockers can stop it, so the server call is the most reliable.
ready(fn)functionCalls fn with the Kickrail object.

Because the script loads with async, queue calls that may run before it arrives:

JavaScript

window.Kickrail = window.Kickrail || { q: [] };
function withKickrail(fn) { Kickrail.loaded ? fn(Kickrail) : Kickrail.q.push(fn); }

withKickrail((k) => {
  if (k.referral) document.querySelector("#ref").value = k.referral;
});

Serve tracking from your own domain#

Some ad blockers stop requests to third-party tracking hosts. To avoid that, proxy a path on your own domain to Kickrail and tell the script to use it:

  1. Forward https://yourapp.com/kr/* to https://kickrail.com/api/* (a rewrite in Next.js, Vercel, Netlify, Cloudflare or nginx).
  2. Load the script through it with api=/kr.

next.config.js

async rewrites() {
  return [{ source: "/kr/:path*", destination: "https://kickrail.com/api/:path*" }];
}

HTML

<script async src="/kr/kr.js?k=YOUR_PUBLIC_KEY&api=/kr"></script>

Add kr_test=1 to any affiliate link (?via=jane&kr_test=1). The click is recorded and marked as a test, so you can confirm the script works without inflating the affiliate's numbers. Affiliates have a "test my link" button in their portal that does the same.

Cookies are not enough on their own

Safari limits script-set cookies to 7 days and some browsers block them outright. The cookie only has to survive until signup, but for reliable numbers report signups from your server. After that, payments are matched by the Stripe customer, so cookies no longer matter.