Tracking script

Add aff.js to your site to capture referral codes and click ids, and read them back at signup.

Embed
Preview of the card
<a href="https://referalli.com/docs/tracking-script"><img src="https://referalli.com/docs/_api/public/orgs/07f432f4-34b9-46a7-aaad-c0e395d2e4f9/spaces/2bf4f614-3630-4fbf-85f9-5ecafa6b7d97/pages/63d83baf-f64f-4852-8a4f-578deed864cd/social-card.svg?v=3e7ae33eec8b" alt="Tracking script" width="600" height="315"></a>

The tracking script runs on your marketing site and app. It gives every visitor a stable anonymous id, captures the referral code and click id from the landing URL, and tells Referalli about the visit. At signup you read that context back and pass it to your server.

Install

Add one script tag to every page, replacing tk_... with your org's tracking token from GET /v1/org:

<script src="https://referalli.com/t/tk_.../aff.js" async></script>

The script is generated for your token and cached for five minutes. An unknown token returns 404.

What it does on each page load

  1. Reads the referral code from the first of the via, ref or aff query parameters, and the click id from ref_click_id.

  2. Loads any context saved from an earlier visit, then saves the merged result under the key referally_ctx in localStorage and in a first-party cookie (SameSite=Lax, plus Secure on https). The context lasts as long as your longest active program's cookieWindowDays (60 days by default, 400 at most).

  3. Keeps the existing anonymous id, or creates one like a_k3j9x0q7….

  4. Sends POST /t/{trackingToken}/visit with anonId, code, clickId and the page URL, to the origin the script was loaded from.

A new via or ref_click_id replaces the saved one (last touch), unless every active program uses first_click: then the first referral is kept until it expires. Otherwise the saved values carry over between visits.

Referral parameters

The script reads the referral code from the first of via, ref and aff it finds, in that order, then from any extra parameters your org adds.

This order is the contract. Anything else that reads a referral code from a URL (your server, or an auth platform that captures it at sign-up) must use the same order, or a URL carrying two different codes credits one partner in the browser and another at sign-up. GET /v1/org/referral-params returns it exactly: builtIn (["via", "ref", "aff"]) first, then your org's params. Add the parameter a previous tool used (for example fpr for FirstPromoter or ps_partner_key for PartnerStack) so links partners already shared keep crediting them. An import from another tool (see the migration guides under Guides) adds its tool's parameter for you.

curl -X PUT $BASE/v1/org/referral-params \
  -H "Authorization: Bearer $KEY" -H "content-type: application/json" \
  -d '{"params": ["fpr"]}'
# { "builtIn": ["via", "ref", "aff"], "params": ["fpr"] }

Names are lowercase letters, digits and _, up to 10 of them. GET /v1/org/referral-params returns the list; owners and admins can change it.

Set these attributes on the script tag:

Attribute

Effect

data-persist="referral-only"

Store nothing and send nothing unless the landing URL carries a referral (via, ref, aff or ref_click_id). Visitors who arrive without one are not tracked at all.

data-cookie-days="30"

How long the context is kept, in days (1 to 400). Overrides the program default.

data-attribution="first" or "last"

Whether a new referral replaces a saved one. Overrides the program default.

data-cookie-domain=".yourapp.com"

Share the cookie with your subdomains, so a sign-in page on auth.yourapp.com (for example an Atlas custom domain) can read the referral. Without it the cookie belongs to the exact host that set it.

<script src="https://referalli.com/t/tk_.../aff.js"
        data-persist="referral-only" data-cookie-days="30" async></script>

The context is a tracking cookie, so in many places it needs consent. You can load the script only after the visitor opts in, or load it in referral-only mode and call aff.forget() if they decline. aff.forget() deletes the cookie and the localStorage entry and stops the script sending anything else on that page.

Partners can link straight to your site with ?via=code instead of the /go link. When the visit call carries a code but no clickId, Referalli finds the link with that code and records the click at that point. Clicks recorded this way are not fraud-scored.

The window.aff API

Once loaded, the script defines window.aff:

Method

Returns

Use

aff.getReferral()

{ anonId, code, clickId, ts }

Read the current referral context. code and clickId are null when there is none; ts is when the visitor was first seen (milliseconds since epoch).

aff.identify({ customerRef, emailHash })

nothing

Link the anonymous visitor to a known customer id and/or a hashed email.

aff.forget()

nothing

Delete the stored context (cookie and localStorage), for example when consent is withdrawn. Afterwards getReferral() returns nulls and nothing more is sent.

Pass the context to your server at signup

The script does not create referrals. Your server does that by calling POST /v1/referrals/associate with its API key. Send the context along with your signup form:

<form id="signup" method="post" action="/signup">
  <input name="email" type="email" required />
  <input name="referally_anon_id" type="hidden" />
  <input name="referally_click_id" type="hidden" />
  <button>Create account</button>
</form>
<script>
  document.getElementById('signup').addEventListener('submit', function (e) {
    if (!window.aff) return;
    var ref = window.aff.getReferral();
    e.target.referally_anon_id.value = ref.anonId;
    e.target.referally_click_id.value = ref.clickId || '';
  });
</script>

Then, on your server, call associate with anonId and referralToken set from those fields.

Identify known visitors

Call identify when a visitor gives you something that identifies them, for example a newsletter signup before they create an account:

async function sha256Hex(text) {
  const bytes = new TextEncoder().encode(text);
  const digest = await crypto.subtle.digest('SHA-256', bytes);
  return [...new Uint8Array(digest)].map((b) => b.toString(16).padStart(2, '0')).join('');
}

const emailHash = await sha256Hex(email.trim().toLowerCase());
window.aff.identify({ emailHash });

emailHash is the lowercase hex SHA-256 of the lowercased email. Recording it gives attribution a fallback: a later associate call that sends the same emailHash can be matched to this visitor's earlier clicks even when the cookie is gone (see Attribution for the exact rule). identify never creates a referral by itself.

Public tracking endpoints

The script calls these endpoints. You can call them directly from a browser or app, for example from a native client.

Endpoint

Body

Response

POST /t/{trackingToken}/visit

anonId (required, max 80 chars), clickId, code, url, referer

{ "ok": true, "clickId": "clk_..." | null }

POST /t/{trackingToken}/identify

anonId (required), customerRef, emailHash

{ "ok": true }

GET /t/{trackingToken}/codes/{code}

none

{ "valid": true, "partnerDisplayName": "Jamie", "refereeReward": {...} | null }, or 404 { "valid": false }. For "Invited by …" on a sign-up page; see Auth platforms.

All are public and authenticated only by the tracking token. They record facts; none creates a referral or a commission.

Updated