Skip to main content

Session handling

Getting session handling right is the single most important part of a Fluid integration, and it is the most common source of first integration problems. This page explains what a session means to Fluid, the rules you must follow, and the mistakes that cause the support requests we see most often.

If you read only one thing: pass the real, current session ID of your authenticated user in session-id, initialise the widget once right after the user logs in, and keep that value stable for the life of the session. And if your platform refreshes or rotates the session ID at any point, update the session-id attribute with the new value: the attribute is observed even while the cashier is open, so the widget picks it up live.

What a session is

Fluid does not run its own login. It trusts the host site to authenticate the user, then represents that authenticated user through a small set of attributes on the widget element:

  • operator-id is your operator identifier, provided by Fluid Payments.
  • user-id is the identifier of the authenticated user.
  • session-id is the current session ID of the authenticated user.
  • locale, country and currency describe the user's locale (IETF BCP 47), country (ISO 3166-1 alpha-3) and currency (ISO 4217).

Together these identify the user to Fluid for the duration of their session.

Fluid does not own or interpret the session-id. It is your platform's session ID, passed through Fluid as is. It travels with the user's transactions and can reach back to your platform later in the payment lifecycle, for example when a payment provider presents it to you to attribute or verify the activity. Because it round trips through that lifecycle, keep it hygienic: pass the real, current session ID of the authenticated user, not a placeholder, not a stale value, and nothing your platform would fail to recognise when it comes back.

The session lifecycle

  1. The user authenticates on your site.
  2. You load the Fluid script and initialise the widget once, passing the identity attributes above.
  3. The widget stays mounted for the whole session. You update reactive attributes (such as balance or open) as needed, but you do not re-initialise.
  4. On logout or session end, you remove the widget from the DOM.

Golden rules

Initialise once, right after authentication. Initialise when the user logs in, not on page load before login, and not on every render. See Automatic Init and Programmatic Init.

Keep session-id stable. It must be the current session ID of the authenticated user, and it must not change on every render or route change. An empty, placeholder, stale, or constantly changing session-id is the number one cause of failed integrations.

Rotate a session by updating the attribute, not by tearing down. If your platform issues a new session ID for the same authenticated user, push the new value onto the session-id attribute.

Session refreshes while the cashier is open

session-id is one of the few attributes observed even while the widget is open. Whenever your platform refreshes or rotates the session ID, set the new value on the attribute immediately, mid transaction included. The widget adopts the new session live, without you removing and recreating the element. Forgetting this leaves the widget on a session your platform no longer recognises.

This applies to <fluid-widget> and <fluid-virtual>. The inline <fluid-quick-deposit> reads session-id once when mounted and does not adopt a rotated session; after a rotation, re-mount the Quick Deposit element with the new value.

Never change the other identity attributes on a mounted element. operator-id, user-id, locale, country and currency are read once when the element mounts and are not observed afterwards: setting a new value on a live element does nothing, and the widget silently keeps the identity it started with. For a genuine identity change (for example a real account switch), remove the element from the DOM and mount a fresh one with the new values.

Wait for initialised before opening. Never set open="true" before the widget emits the initialised event. Opening earlier shows an empty or broken wallet. See Events and errors.

Remove the widget on logout. Take <fluid-widget> out of the DOM when the session ends so it shuts down cleanly. You will see a destroyed event.

Keep exactly one widget in the DOM. More than one <fluid-widget> mounted at the same time causes unpredictable behaviour.

What to do when something changes

You need toDo thisWhy
Rotate the session IDSet the new value on the session-id attributeObserved live, even while the cashier is open; the widget adopts the new session without teardown
Change user, operator, locale, country or currencyRemove the element and mount a fresh one with the new valuesThese attributes are read once at mount; changing them on a live element does nothing
Open the walletSet open="true" after the initialised eventThe wallet is only ready to open once initialisation completes
End the session (logout)Remove the element from the DOMThe widget shuts down cleanly and emits destroyed

fluid.init() is a pre-warm, not a way to open the wallet

fluid.init() (Programmatic Init) prepares the widget ahead of time so it opens faster. It is an optimisation you call once per session, immediately after loading the script. It does not open the wallet, and it is throttled to roughly once every two seconds: a call made too soon after the previous one returns a promise that rejects with Error('Function call is throttled. Please wait.'), so handle the rejection if you cannot guarantee the spacing. The wallet is opened by the custom element through its open attribute, after initialised.

Watch the field names: fluid.init() takes countryCode and currencyCode, while the HTML attributes are country and currency. Mixing them up is a common slip.

Fluid handles its own authentication

After init, the widget authenticates to Fluid's services on its own, using an internal credential that is not a host concern. You never read, store, or refresh it. Three behaviours are worth designing around:

  • It is per browser tab. A new tab starts a fresh instance, so the widget initialises again in each tab. Do not try to share this state across tabs yourself.
  • It refreshes automatically. When the credential expires during a session, the widget renews it transparently. You do not need to do anything.
  • There is no "session expired" event. Because refresh is automatic, the widget does not emit a client side expiry notification, so do not build logic that waits for one. If a genuine problem stops the widget configuring itself, you receive a fluid-error with initialisation-failure instead.

This is separate from session-id, which is your platform's session ID: keeping that attribute current remains your responsibility, as described above.

Signals to handle

Subscribe to the widget's events and react to the session relevant ones. The full catalogue is on the Events and errors page. The ones that matter for session handling are:

  • fluid-info initialised: the widget is ready, and only now may you open it.
  • fluid-info destroyed: the widget has shut down.
  • fluid-error initialisation-failure: the widget could not configure itself (for example a bad session-id, or a network or backend problem).
  • fluid-error invalid-init-attributes or invalid-user-data: an attribute you passed did not validate, for example an invalid locale (the widget falls back to en) or malformed Sweepstakes data. The exact triggers are listed in Events and errors.

Common mistakes

The most frequent session mistakes, with their symptoms and fixes, are collected on the Common pitfalls page together with the other integration pitfalls.

Next steps