User Authentication & Enrollment Behavior
Controlling Loyalty Enrollment via the JWT
When a user is authenticated on your website, the Loyalty Web Kit (LWK) authenticates them automatically through the JWT (authToken) you generate server-side. The behavior of the LWK — whether it enrolls the user into your loyalty program, and whether it creates the contact in Splio — depends entirely on what you put in that JWT and on one configuration setting: block_auto_sub.
This article covers:
- Default behavior — automatically enroll any authenticated user.
- Controlling enrollment for opted-in users only — the two available options, and how they differ.
Default behavior: auto-enroll everyone
By default, the LWK is designed to automatically log in and enroll any authenticated user into your loyalty program the first time they access it.
Concretely, whenever the JWT you generate contains a contact_id (external_id in the JWT payload), the LWK will:
- Upsert the corresponding contact in your Splio universe (create it if it doesn't exist yet, update it otherwise).
- Check if that contact is already a member of the loyalty program.
- If not, automatically subscribe them to the program.
Keep in mind the following scenarios when adapting your website's user flow:
| Situation | LWK behavior |
|---|---|
| Authenticated, existing in Splio, already a member of your program | User is logged in and sees their loyalty data |
| Authenticated, existing in Splio, not yet a member of your program | User is logged in and automatically subscribed to the program |
| Authenticated, not existing in Splio | Contact is created in Splio and automatically subscribed to the program |
| Not authenticated | User goes through the sign-in / sign-up page you configured (unconnected.signin / unconnected.signup), and should be redirected back to the LWK once authenticated |
If this default behavior fits your use case (any logged-in user should join the loyalty program), you don't need any extra configuration: just make sure to always include thecontact_idin the JWT for every authenticated user.
Controlling enrollment for opted-in users only
If you manage your own internal opt-in flag (for example, a checkbox in your account settings or CRM) and only want opted-in users to join the loyalty program, you have two independent levers to achieve this. They act at different levels, don't block the same thing, and don't have the same operational cost — so it's important to understand how they differ before choosing one.
Omitting contact_id from the JWT | Enabling block_auto_sub | |
|---|---|---|
| Where it's controlled | In your backend, per request / per user, when you generate the JWT | In the LWK configuration, once, for all users of that configuration |
| Is the contact created/updated in Splio? | No — never, for that user | Yes — always, as soon as a contact_id is present, regardless of this setting |
| Is the loyalty enrollment blocked? | Yes, indirectly (the user is treated as anonymous) | Yes, but only if the contact isn't already a member |
| Who enrolls the user into the loyalty program? | Splio, automatically, the first time you send their contact_id | You — you must subscribe the contact to the program yourself (via API, or through whatever process feeds Splio) |
| What the user sees | The same experience as a non-authenticated visitor | A dedicated "not a member" screen, linking to your sign-up page, until Splio has recorded their enrollment |
| Scope | Per user, decided on your side | Global, applies to every user of this configuration |
In short: omitting contact_id decides whether this user is even allowed to exist in Splio at all. block_auto_sub decides whether a contact that already exists (or was just created) is allowed to automatically join the loyalty program — and shifts the responsibility of actually enrolling that contact from Splio to you.
Option A — Omit contact_id for non-opted-in users
contact_id for non-opted-in usersThe recommended approach if you want full control and don't want Splio to know about non-opted-in users at all: control it on the JWT generation side, based on your own opt-in flag.
- If the authenticated user is opted in: include their
contact_idin the JWT, as usual. The LWK will upsert the contact and enroll them into the loyalty program. - If the authenticated user is not opted in: do not include the
contact_idclaim in the JWT (or generate the JWT as if the user were anonymous). The LWK will then treat them as a non-authenticated visitor: no contact upsert, no enrollment, and they'll go through the sign-in / sign-up flow you've configured.
This requires your backend to know the opt-in status before generating the JWT, but gives you full control without needing any specific configuration on the Splio side, and without any enrollment delay: as soon as contact_id is sent, the LWK enrolls the user immediately.
Option B — Enable block_auto_sub
block_auto_subEnable the block_auto_sub property in your LWK configuration if you want the LWK to never auto-enroll a contact who isn't already a member of your loyalty program.
When block_auto_sub is enabled:
- If the contact is already a member of the loyalty program, they're logged in normally.
- If the contact is not a member yet, the LWK will not auto-enroll them. Instead, the user is treated as not connected and shown a dedicated "not a member" screen, redirecting them to the sign-up page you've configured (
unconnected.signup).
Important nuance:block_auto_subonly blocks the automatic loyalty program enrollment. It does not prevent the contact record itself from being created or updated in Splio: as soon as acontact_idis present in the JWT, the corresponding contact is upserted in your Splio universe, independently of their loyalty program membership status.
You become responsible for the enrollment. Withblock_auto_subenabled, Splio no longer auto-enrolls the contact — you need to subscribe them to the loyalty program yourself, through whatever process feeds membership data into Splio. Until Splio has actually recorded that enrollment, the user keeps seeing the "not a member" screen, even after they've opted in on your side.This matters if enrollment doesn't happen in real time. For example, if loyalty subscriptions are synced via a Datahub import running once every 24 hours, a user who opts in right after the last import will keep seeing "you're not a member" and won't access the LWK until the next import runs, up to 24 hours later.
We only recommend
block_auto_subif the enrollment is performed via direct, real-time API calls (e.g. right after the opt-in action, calling the loyalty subscription API synchronously). If your enrollment relies on a batch process (scheduled imports, Datahub, nightly syncs, etc.), prefer Option A instead: it enrolls the user instantly, with no dependency on your synchronization delay.
Which one should you use?
- Use Option A if you never want Splio to have any record of non-opted-in users, or if your enrollment process isn't real-time (batch imports, scheduled syncs, etc.). It enrolls the user immediately, with no synchronization delay.
- Use Option B only if it's fine for Splio to know about a contact (for other use cases, such as marketing automation) and your enrollment into the loyalty program happens through a direct, real-time API call. Otherwise, users may be stuck seeing the "not a member" screen until your next batch sync runs.
- You can combine both: send
contact_idonly for opted-in users (Option A), and additionally enableblock_auto_subas a safety net in case acontact_idis ever sent by mistake for a non-opted-in user — in that case, the contact would still be created in Splio, but at least would not be auto-enrolled into the program.
Updated 25 days ago
