Tracker JavaScript reference
Everything the Refficks browser script, refficks.js, offers a developer: the
attributes on its script tag, every function on window.refficks, what each
sends, and what the server refuses. For a first install, follow
Install the tracking script; this
page is the reference behind it.
How the script behaves
- It never breaks your page. Every function catches its own errors. A failed request is dropped, not retried, and nothing throws into your code.
- It never reports money, except an order your confirmation page sends
with
sendOrder()when Settings › Developer › Website orders is on. - It never says which partner earns. Refficks works that out from the visitor's own clicks and codes.
- It respects a refusal. A browser that sends Global Privacy Control, or a page without consent, gets nothing written and nothing sent. A partner's code seen in the address is held in memory for that page only.
- Its clock is Refficks's. Whatever time the script sends, the server records the moment each request arrived.
Authentication
The script authenticates with your publishable key, rk_pub_…, as a
bearer token on every request. Anybody can read it from your page, so it can
only record tracking. A secret key (rk_live_…) must never be in a page; the
script's address ignores one in ?a=.
The script tag
<script
src="https://go.refficks.com/refficks.js?a=<PUBLISHABLE_KEY>"
data-account="<PUBLISHABLE_KEY>">
</script>
| Attribute | Meaning |
|---|---|
src with ?a=<PUBLISHABLE_KEY> |
Serves the script with your workspace's settings inlined: your link parameters (current and old), your consent setting, your verified other sites, the checkout links of the guides you chose, and whether a WooCommerce store is connected. Cached for five minutes. Without a valid key, the plain script on the default parameter rfi, cached for an hour. |
data-account |
The publishable key. Required unless the key is in ?a=. |
data-endpoint |
Where to send. Defaults to the host that served the script. |
data-param |
An extra link parameter to read first, before your workspace's own list. It is added to the list, never replaces it. |
data-consent |
"false": wait for consent(true) before writing or sending anything. "true": consent assumed. Either beats Wait for consent before tracking on Settings › Partners and payouts › Partner links. Absent: the setting decides. |
data-auto-track |
"false": do not send a page view on load. Everything else still works. |
The script sets itself up from its own tag. The global is
window.refficks.
Not yet documented: the address your snippet loads from depends on the Refficks service you use. Copy the one on the Website tracking card, on Integrations › Connections;
go.refficks.comis the production address in the API reference.
What it does by itself
On every page, once consent allows:
- Claims a partner's code. If the address carries one of your link
parameters (
?rfi=dana), the code is written to therk_refcookie, most recent first, five at most. On the page the code arrived on, that page view counts as the click, unless Refficks's redirect already counted it. - Keeps a visitor id in the
rk_vidcookie on your site, for 365 days. A visitor arriving through Refficks's redirect brings the id Refficks made for your workspace in the address, and the script adopts it when the browser has none of yours yet. - Sends a page view (
tracking.visit) with the page's path, and on the first page of a visit, the referring site. - Carries the visitor between your sites. A link to another of your
verified sites gets
rk_vidadded as it is clicked. - Decorates checkout links for the guides you chose on Integrations ›
Where you sell: a Stripe Payment Link gets the partner's code as
client_reference_id, a Stripe Buy Button or Pricing Table gets theclient-reference-idattribute, a ThriveCart link getspassthrough[rk_vid], a Polar Checkout Link getsreference_id, a Memberstack checkout getsrefficks_visitorin its metadata, and a checkout on another address you named getsrk_vid. A link that already carries its own value is left as you wrote it. - Reports a WooCommerce order-received page, with the order key the page carries, when a WooCommerce store is connected.
A partner's link whose destination is the Stripe Payment Link itself
(buy.stripe.com) opens no page of yours, so the script never runs. For that
link Refficks's redirect adds the partner's code as client_reference_id as
it sends the visitor on, under the same choice of guide, and leaves a
client_reference_id you set yourself alone. It adds nothing for a browser
that sends Global Privacy Control, as the script would not.
Functions
Call these once the script has loaded: wait for window.refficks to exist,
as the short loop in the install guide does.
consent(granted)
window.refficks.consent(true); // the visitor agreed
window.refficks.consent(false); // they refused or withdrew
true, afterfalse: writes down this page's partner code and a visitor id, and sends the page view. Repeatingtruesends nothing twice.false: clears both cookies, and takes the script's additions back off your checkout links.
Returns nothing.
visitorId()
const id = window.refficks.visitorId(); // "01J9…" (26 characters) or null
Returns this browser's visitor id on your site, creating and storing one if
there is none. Returns null while consent is withheld or the browser sends
Global Privacy Control. Pass it to your server and on to Refficks as
visitor_id, or to Stripe as metadata.refficks_visitor, to join a sale to
the clicks. The id is your workspace's alone: another merchant sees a
different one for the same browser.
referral() and referrals()
window.refficks.referral(); // "dana" or null
window.refficks.referrals(); // ["dana", "lee"]: most recent first, at most five
The partner codes this browser arrived with. Refficks credits the most recent one that is a real code, so a word in one of your own links cannot bury a partner's.
identify(customer, properties)
window.refficks.identify(
{ external_id: "<YOUR_USER_ID>", email: "sam@example.com", name: "Sam Rivera" },
{ plan: "pro" }
);
Says who is at this browser, after a sign-up or a log-in. Sends
customer.created. customer takes external_id, email and name; send
at least one, and the same id or email your billing system uses. properties
is optional.
A browser's word is a browser's word: when the partner's click reaches a sale
only because the browser named a customer Refficks already knew before that
click, the commission waits for a person to approve it. Naming the customer
with the same visitor_id from your server, with your secret key, removes the
wait (Send events from your server).
Returns nothing.
lead(customer, properties)
window.refficks.lead({ email: "sam@example.com" });
Names the person at this browser without saying they made an account:
somebody who booked a call or sent a form. Sends lead.created. It ties them
to the partner the same way, so their later payment is credited, without
counting as a sign-up for a referral reward. Returns nothing.
track(eventType, properties)
window.refficks.track("trial.started", { plan: "pro" });
Sends one event. The browser may send only tracking.visit (the default),
customer.created, customer.updated, lead.created and trial.started.
Anything else is refused: "That event type cannot be reported from a
browser." Returns nothing.
reset()
window.refficks.reset();
Call it when somebody logs out. Clears rk_vid and rk_ref, so the next
person on that computer starts a journey of their own and is not credited to
the last person's partner. Takes the partner's code back off your checkout
links. Asks the server nothing; what was recorded stays recorded.
order(order), item(item), buyer(customer), sendOrder(options)
Reports an order from your confirmation page. Only works while Settings › Developer › Website orders › Let my confirmation page report orders is on.
window.refficks
.order({ order_id: "1001", currency: "USD", amount: 7200, coupon_code: "DANA20" })
.item({ sku: "MUG", quantity: 3, unit_amount: 2400 })
.buyer({ email: "sam@example.com" });
window.refficks.sendOrder({ signature: "<SIGNATURE_FROM_YOUR_SERVER>" })
.then((result) => console.log(result));
// { sent: true, status: 202, cookieless: false, signature_verified: true }
order() starts a new order and clears any earlier one; item() and
buyer() add to it. All three return window.refficks, so they chain.
| Field | Meaning |
|---|---|
order_id |
Required. Your own order number. One order is recorded once, however often the page is reloaded. |
currency |
Required. Three letters, such as USD. |
amount |
The total in the currency's smallest unit: 7200 is USD 72.00. |
total |
Instead of amount, the total as text, such as "72.00", for a page that only prints it |
net_amount or net_total |
What commission is paid on, without tax and shipping, as minor units or as text. With neither, commission is paid on the total. |
coupon_code |
The code the shopper typed |
is_subscription, subscription_id |
For a subscription's first order |
signature |
t=…,v1=… from your server, which marks the order verified. Also accepted in sendOrder({ signature }). |
item sku, quantity, unit_amount |
One line: unit_amount is per unit, not the line total. Three at USD 24.00 is 2400. |
buyer email, external_id, name |
Who bought |
sendOrder() returns a promise that always resolves:
| Result | Meaning |
|---|---|
{ sent: true, status: 202, signature_verified: true } |
Recorded and verified |
{ sent: true, status: 202, signature_verified: false } |
Recorded unsigned: its commission waits for a person |
{ sent: true, …, cookieless: true } |
The shopper had not consented, so the order went for its code alone, with no visitor and no buyer |
{ sent: false, reason: "no consent" } |
No consent and no code: nothing sent |
{ sent: false, reason: "no order" } |
order() was not called, or had no order_id |
{ sent: false, reason: "network" } or "error" |
It did not reach Refficks |
{ sent: false, status: 403 } |
Website orders are off, or on with no signing secret yet |
{ sent: false, status: 409 } |
Stripe or a connected Shopify store already reports your sales |
How to sign an order is in Install the tracking script. A signed report replaces an unsigned report of the same order, and an unsigned report after a signed one records nothing.
checkout({ reference, proof })
window.refficks.checkout({ reference: cart.id });
Says which visitor a store's cart belongs to, so the order the store reports
later is credited through the partner's link even without a code. The script
Refficks puts on a BigCommerce storefront calls it, and so does the script on
a connected WooCommerce store's order-received page (with the order key as
proof); nothing else needs to. A bare order number without its proof is
refused: "A storefront reports its cart. An order number from a browser is
not taken, because anybody could name the next one." Returns a promise that
resolves to { sent, status }, or { sent: false, reason } with "no reference", "no consent" or "already sent".
chargebee(instance)
window.refficks.chargebee(Chargebee.getInstance());
Hands Chargebee's checkout the visitor id, as the custom field
cf_refficks_visitor on the cart and on every checkout button, so the
subscription Chargebee makes says who the buyer was. Only the visitor id,
never a partner's code. Taken back off when consent goes or the person logs
out. Returns true when a visitor id was handed over.
init(options)
Runs by itself from the script tag. Call it yourself only if you load the
file in a way that cannot set its attributes, and pass at least account and
endpoint. Without ?a= in the address, the script does not have your
workspace's settings and reads only the default parameter rfi and any
params you pass.
What the server refuses
The script sends to /t (events), /t/order (orders) and /t/checkout
(carts). Each takes at most 1,200 requests a minute from one address.
| Answer | Message | Why |
|---|---|---|
| 401 | "An API key is required." or "That API key is not valid." | The key in the snippet is missing, shortened or mistyped |
| 401 | "That API key has expired." | The key was revoked or has lapsed |
| 422 | "Revenue must be reported from your server, not from a browser." | track() was sent an amount |
| 422 | "A partner can only be named from your server, not from a browser." | An event or order named a partner |
| 422 | "That event type cannot be reported from a browser." | track() with a type outside the five allowed |
| 422 | "A page view cannot name anybody. Name them with identify(), which sends customer.created." | A page view carried a customer |
| 422 | "Which partner earns is decided from this visitor's own clicks, not from the page." | An order carried a referral code |
| 422 | "Commission is worked out from the plan, never sent by a browser." | An order carried a commission |
| 403 | "This account does not accept orders reported from a browser." | Settings › Developer › Website orders is off |
| 409 | "Stripe already reports this account's payments, verified, so an order reported from a browser is not recorded, …" | A sale Stripe or Shopify reports, refused as a duplicate |
A repeat of the same event from the same browser within the same minute is
recorded once, and answered 200 with "status": "duplicate".
When the script names unusually many people in an hour (at least 100, and five times the usual for that hour), your team is emailed, at most once a day, with the partners those people would be credited to. Nothing is refused.
Limits
- Five partner codes per browser at most.
- No local storage; two cookies and one session-storage marker. See Consent and privacy.
- It does not run where an ad blocker stops it. Count clicks on our servers, on Settings › Partners and payouts › Partner links, records those clicks before the visitor reaches your site.
- It cannot backdate a click, a page view or a sign-up.
Related
- Install the tracking script: the
snippet,
identify(), consent and signed orders, step by step. - Consent and privacy: the cookies, their lifetimes, and what is never kept.
- Send events from your server: sales and customers with your secret key.
- API errors and limits: the error envelope and request ids.