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.
Affiliate links#
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#
- The script generates a click id like
kr_7Hq2...(20 random characters afterkr_). - It stores two cookies,
kr_ref(the click id) andkr_via(the token), plus a copy inlocalStorage. Cookies are set on the widest domain your browser allows, sowww.yourapp.comandapp.yourapp.comshare them. - It sends the click to Kickrail with the page URL and the HTTP referrer, using
sendBeaconso it survives an immediate navigation.
| Behaviour | Default | Notes |
|---|---|---|
| Cookie lifetime | 60 days | Settings → Program → Cookie window (1 to 365 days). A return visit refreshes it. |
| Two affiliates | first touch | Before 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 flags | SameSite=Lax | Plus 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).
Stripe Payment Links
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-ignoreto 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.
| Key | Example | Value |
|---|---|---|
| kickrail_referral | ref_8Kd2... | The referral id |
| kickrail_affiliate | aff_3Xp9... | The affiliate id |
| kickrail_affiliate_token | jane | The affiliate's link token, the jane in ?via=jane |
| kickrail_campaign | cmp_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:
| Member | Type | Description |
|---|---|---|
| referral | string | null | The click id (kr_...), or null when the visitor was not referred. |
| token | string | null | The affiliate token from the link. |
| attach() | function | Re-run the Payment Link, pricing table and form tagging by hand. |
| convert({ email }) | Promise | Report 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) | function | Calls 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:
- Forward
https://yourapp.com/kr/*tohttps://kickrail.com/api/*(a rewrite in Next.js, Vercel, Netlify, Cloudflare or nginx). - 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>
Testing a link#
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