The balance widget shows a signed-in shopper their points, tier and anything about to expire, on any web page, with one <div> and one script tag. It has no dependencies, sets no cookies and does no tracking. An API key never reaches the browser: your server mints a short-lived member session token and renders it into the page.
How it works
- The shopper signs in to your site as usual.
- Your server, which knows who they are, mints a member session token with
POST /v1/members/{id}/session-tokens. The token is read-only, names one member and expires after 15 minutes. - Your page puts that token on the widget's
<div>asdata-token. - The script calls
GET /v1/public/memberwith the token (the one endpoint that allows cross-origin calls) and draws the card. The response carries points, tier and referral code, never contact details.
Mint a token on your server
Needs a key with the read scope. Name the member by your own customer id (ref:…), their phone (phone:…) or our member id:
curl -X POST https://stickytier.com/v1/members/ref:CUST-1001/session-tokens \
-H "Authorization: Bearer $KEY"
# → 201 { "data": { "token": "smt_…", "expires_at": "…", "member_id": "M-…" } }A 403 means the member's account is suspended, deleted or erased — no token is issued, so leave the widget out. A 404 means the customer is not a member yet: leave data-token out (the widget then asks them to sign in) or show your own "Join" prompt and enrol them from the server with POST /v1/members.
Mint the token when you render the page. Never cache one across shoppers, and never put an API key (sticky_live_… or sticky_test_…) in a page — the widget and GET /v1/public/member only accept session tokens.
Embed it
<div data-stickytier-widget data-token="smt_…"
data-portal-url="https://rewards.yourstore.com" data-accent="#0f766e"></div>
<script src="https://stickytier.com/widget/stickytier-widget.js" async></script>Every element with the data-stickytier-widget attribute becomes a widget, so one script serves several on a page. The script reads these attributes:
| Attribute | Required | What it does |
|---|---|---|
data-stickytier-widget | yes | Marks the element the widget draws into. |
data-token | yes, for a signed-in shopper | The member session token from your server. Without one the widget shows "Sign in to see your rewards." |
data-portal-url | no | An https:// address for a "View rewards →" link, such as your hosted rewards page. Other schemes are ignored. |
data-accent | no | Any CSS colour value for the balance and the link. Defaults to indigo. |
data-locale | no | A BCP 47 locale for number formatting, such as en-GB. Defaults to the programme's own locale. |
The script talks to the site it was loaded from, so load it from https://stickytier.com as shown.
Refreshing and expiry
A token lasts 15 minutes. The widget only fetches when the page loads and when you call refresh() — it does not poll — so an expired token shows up at the next redraw, where the widget asks the shopper to refresh the page. On long-lived pages (a single-page app, say), fetch a fresh token from your server, set it on the element and call:
document.querySelector("[data-stickytier-widget]").setAttribute("data-token", freshToken);
window.StickyTierWidget.refresh();refresh() redraws every widget on the page.
Events
The widget's element fires two DOM events that bubble, so you can react to them anywhere up the tree:
stickytier:loaded—event.detailis the member data fromGET /v1/public/member(program_name,currency_name,locale,tier,balancesand so on).stickytier:error—event.detail.reasonisexpiredfor any401— the token is invalid or has run out, or the programme is no longer active — otherwise a short message. The widget has already shown the shopper a neutral message.
document.addEventListener("stickytier:loaded", (e) => {
if (e.detail.balances.spendable_cents === 0) e.target.hidden = true;
});Your own design instead
The widget is a convenience. For a fully custom card, or in a mobile app, call GET /v1/public/member yourself with Authorization: Bearer smt_… — see A mobile app. For a "My rewards" button that opens your hosted rewards page already signed in, use POST /v1/members/{id}/portal-links from your server (see SDKs, widget & plugins).