flowsjackpot
v2.10.0
Published
Flows Jackpot Library
Readme
FlowsJackpots
A TypeScript script for integrating jackpot functionality into web application. The script enables the display of a customizable UI widget with real-time event handling, and player opt-in management.
Installation
The FlowsJackpots script is hosted on Flows's own CDN (https://cdn.flows.world).
Flows hosts a staging and a production version of the script, where the former is connected to the staging FlowsPlay API and contains the latest code from the main branch, while the latter is the latest stable version, which is connected to the production FlowsPlay API.
There is no particular installation needed to utilize the script. One must simply reference the script via a <script> tag in their main HTML file.
<!-- Staging -->
<script type="text/javascript" src="https://cdn.flows.world/js/jackpot-v2-beta.js" id="flows-jackpot"></script>
<!-- Production -->
<script type="text/javascript" src="https://cdn.flows.world/js/jackpot-v2-latest.js" id="flows-jackpot"></script>This exposes flowsJackpots as a global object which should be used to start and interact with the widget.
Quick Start
Reference the script for the target environment as in the Installation section.
Call the
startJackpotWidgetfunction of the exposedflowsJackpotsobject, passing at least the first 3 parameters - orgId, gameId, and playerId:flowsJackpots.startJackpotWidget( "{{orgId}}", "{{gameId}}", "{{playerId}}", );
See the Examples section for more examples on how to use startJackpotWidget
Features
Core Functionality
Widget Management
startJackpotWidget()- Initialize and display the jackpot widgetcloseJackpotWidget()- Close widget and clean up resourceslock(), unlock(), minimize(), expand()- Control and limit frontend widget behaviourgameRoundStart(), gameRoundEnd()- Run control logic intended to run for the lifetime of a game round (e.g. spin)- Automatic positioning and responsive layout support
- Drag-and-drop widget repositioning
- Mobile-optimized modal display
Real-time Event Handling
Loading the jackpot widget using startJackpotWidget subscribes to server-sent events for jackpot value updates and win events. Events are of type JackpotEvent. There are two types of server-sent events that the widget subscribes to: user event, which listen to events on the channel user_${playerId}, and broadcast events, which listen to events on the channel broadcast_${baseData.jackpotGroupId}. Each event has its own reason property which is checked to determine what the event is about. Supported event reasons are linked with a callback function which is called every time that event is received
Below is a breakdown of the events:
User events: 1 event reasons is supported:
- When
event.reasonis'jackpot_won', this indicates that the current player has won one of the jackpots of the game they are playing. In this case, the widget appearance changes to notify and congratulate the user of the jackpot win and fireworks appear on screen which disappear after a few seconds or when the 'OK' button is clicked on the widget. Note: if the widget state is locked (lock()orgameRoundStart()have been called), this behaviour will not occur. Instead, the event is queued and the described behaviour only executes aftergameRoundEnd()has been called. If there were multiple wins, only the latest win will be shown to the user.
- When
Broadcast events: 3 event reasons are supported:
- When
event.reasonis'jackpot_won_other', this indicates that one of the jackpots of the game the current user is playing, has been won by another user. In this case, a small notification is shown on the widget which disappears after a few seconds. Note: if the widget state is locked (lock()orgameRoundStart()have been called), this behaviour will not occur. Instead, the event is queued and the described behaviour only executes aftergameRoundEnd()has been called and only if there is no'jackpot_won'event queued. If there were multiple wins, only the latest win will be shown to the user. - When
event.reasonis'jackpot_value', this indicates that the total amount of a particular jackpot has changed. In this case, the widget will update to display the latest total amount for that jackpot. - When
event.reasonisjackpot_closed, this indicates that a jackpot level is completed and further spins will not contribute to the level's pot. When this event is received, the widget re-retrieves the jackpot data and removes the closed jackpot level from the UI, i.e. if the widget is showing a jackpot with MEGA, MAJOR, and MINI jackpot levels, and ajackpot_closedevent is received for the MAJOR jackpot level, the widget will remove the details of the MAJOR jackpot level from view such that only MAJOR and MINI jackpot levels will be shown on the widget. Additionally, ifjackpot_closedevents have been received for all jackpot levels, then the jackpot is considered to be finished andcloseJackpotWidget()is called to shut down the widget. Currently, this event is only being sent when a jackpot is hosted on the Light & Wonder Development site (site ID UiET6N4gQkahyph3vW_2HQ).
- When
Calling closeJackpotWidget(), whilst removing the widget from the screen, also unsubscribes from all event streams.
Player Opt-in Management
The opt-in feature can be enabled via the FlowsPlay editor. When enabled, an Opt In/Opt Out button appears on the widget. Upon loading, the widget automatically checks the player's opt-in status; by default, player are opted out. Players can manage their participation by clicking the button, which opens a modal displaying a text description customizable via the FlowsPlay editor. From this modal, players can choose to opt in or opt out by clicking the appropriate button.
API Integration
The library includes a comprehensive API service with the following endpoints:
Game Data
- Retrieve jackpot game configuration
- Fetch localized appearance settings
Player Management
- Get player's opt-in status
- Update opt-in preferences
UI Components
Multi-level Jackpot Display
Supports 1-5 jackpot levels with customizable titles and styling:
- Level 1: Mega jackpot (primary display)
- Level 2: Major jackpot
- Level 3: Minor jackpot
- Level 4: Mini jackpot
- Level 5: Rapid jackpot
Navigation System
- Jackpot: Live jackpot values and participation status
- News: Announcements and updates
- Help: User guidance and terms
Visual Effects
- Fireworks animation on jackpot wins
- Winner announcements with customizable messaging
- Responsive animations and transitions
- Mobile-optimized interactions
Configuration Options
Language Support
- Automatic browser language detection
- Custom language specification
- Localized text assets for all UI elements
Positioning
e.g.
{
top: '20px', // Distance from top
bottom: '20px', // Distance from bottom
left: '20px', // Distance from left
right: '20px' // Distance from right
}Device Variants
The widget can be customized for 2 different screen sizes: Desktop and Mobile.
- Desktop: Renders jackpot desktop styles when viewport width exceeds
variantBreakingPoint - Mobile: Renders jackpot mobile styles when viewport width is equal to or below
variantBreakingPoint
The default variantBreakingPoint is 480px (this can be changed by passing the deviceBreakingPoint parameter in startJackpotWidget)
Jackpot Layout Variants
Each jackpot has an associated jackpot layout variant which can be set via the FlowsPlay editor. This variant determines the appearance of the jackpot widget when it is loaded in the browser:
- Small, Medium, Large: All of these 3 variants render a pop-up widget which is draggable and can be minimized and expanded. However, they differ in size and appearance in the closed version of the widget, the smallest closed widget of all being the Small layout variant.
- StickyTop: Fixed top positioning. Widget appears as an horizontally elongated bar, taking the width of its container. The default container is
document.body, thus by default the widget will appear at the uppermost part of the browser window. The target container for where the widget should appear can be customized using therootElementparameter instartJackpotWidget. - StickyLeft: Fixed left sidebar positioning. Widget appears as an vertically elongated bar, taking the height of its container. The default container is
document.body, thus by default the widget will appear at the uppermost part of the browser window. The target container for where the widget should appear can be customized using therootElementparameter instartJackpotWidget.
API Reference
Methods
startJackpotWidget(orgId, gameId, playerId, language?, brandId?, startingPosition?, deviceBreakingPoint?, rootElement?)
Initialize and display the jackpot widget.
Parameters:
orgId(string, required): Organization identifiergameId(string, required): Game identifierplayerId(string, required): Player identifierlanguage(string, optional): Language code (e.g., 'en', 'fr-FR')brandId- (string, optional) Brand/Sub-brand identifier, if organization supports sub-brandsstartingPosition(Position, optional): Initial widget positiondeviceBreakingPoint(number, optional): Mobile breakpoint in pixelsrootElement- (HTMLElement, optional) Root element for StickyLeft layout; if not provided, document.body is used.
Advanced Usage
- Start jackpot widget with brandId param
flowsJackpots.startJackpotWidget( "{{orgId}}", "{{gameId}}", "{{playerId}}", "en", '{{brandId}}', ); - Start jackpot widget with language and startingPosition params
flowsJackpots.startJackpotWidget( "{{orgId}}", "{{gameId}}", "{{playerId}}", "en", "", // Brand id parameter has been set to empty string to not use subbrands { bottom: "20px", right: "20px" }, );
closeJackpotWidget()
Close the widget and clean up all resources including event listeners and stylesheets.
showPreview(jackpotGame, jackpotGameAppearance, layout, deviceVariant, languageCode, optedIn?)
Renders the widget into view, whose data and appearance are passed through as parameters (rather than them being retrieved through API calls via startJackpotWidget), that has no functionality (cannot be expanded, does not react to events). The main use of this function is for embedding the widget in the FlowsPlay editor without exposing any functional aspects of it.
Parameters:
jackpotGame(JackpotGame): Jackpot data including org id, jackpot kind, jackpot values, and more.jackpotGameAppearance(JackpotGameAppearance): Jackpot appearance data including desktop + mobile stylesheets and text assets, and more.layout(JackpotLayoutVariant): The display variant of the jackpot widget e.g."Large" or "StickyTop".deviceVariant(BrowserVariant): Either "Desktop" or "Mobile". Renders the widget with Desktop or Mobile appearance.languageCode(string): Language code/locale e.g. "en-GB".optedIn(boolean, optional): If the jackpot has opt in enabled, this parameter controls the internal opted in state of the jackpot (in order to show different text assets of being opted in/out).
lock()
Locks the widget, preventing user interaction. If already locked, returns true without performing additional operations.
Behaviour:
- Sets internal widget locked state to true
- Prevents user from dragging, minimizing, or expanding the widget
- Hides the opt-in modal (if opt-in is enabled and opt-in modal is visible on screen)
- Returns true if:
- Widget was already locked
- Lock operation completed successfully
- Returns false if:
- Widget initialization verification fails
Requires the widget to be initialized – i.e. flowsJackpots.startJackpotWidget(...) has been previously called
unlock()
Unlocks the widget, restoring user interaction. If already unlocked, returns true without performing additional operations
Behaviour:
- Sets internal widget locked state to false
- Allows user to drag, minimize, and expand the widget
- Returns true if:
- Widget was already unlocked
- Unlock operation completed successfully
- Returns false if:
- Widget initialization verification fails
Requires the widget to be initialized – i.e. flowsJackpots.startJackpotWidget(...) has been previously called
minimize()
Minimizes the widget. If already minimized, returns true without performing additional operations. Behaviour:
- Closes any active winner message
- Updates widget appearance to minimized size
- Returns true if:
- Widget was already minimized
- Minimize operation completed successfully
- Returns false if:
- Widget is currently locked
- Widget initialization verification fails
Requires the widget to be initialized – i.e. flowsJackpots.startJackpotWidget(...) has been previously called
expand()
Expands the widget. If already expanded, returns true without performing additional operations. Behaviour:
- Updates widget appearance to expanded full size
- Returns true if:
- Widget was already expanded
- Expand operation completed successfully
- Returns false if:
- Widget is currently locked
- Widget initialization verification fails
Requires the widget to be initialized – i.e. flowsJackpots.startJackpotWidget(...) has been previously called
gameRoundStart()
Prepares the widget for a game round. Executes the following sequence:
- Unlocks the widget (calls
unlock()) - Minimizes the widget (if unlock succeeds) (calls
minimize()) - Locks the widget (if minimize succeeds) (calls
lock())
Behaviour:
- While locked, jackpot user wins do not get communicated to the user, i.e. fireworks and jackpot won message will not be shown, and the widget will not expand to full size. Instead, the latest jackpot user win gets quietly queued. gameRoundEnd() must be called in order to process queued jackpot user win and show regular jackpot user win behaviour.
Use Case: Call before initiating a game round to ensure the widget is in the correct state.
gameRoundEnd()
Finalizes a game round. Executes the following:
- Unlocks the widget (calls
unlock()) - If a jackpot win event is queued, processes it Use Case: Call after a game round completes to unlock the widget and handle any pending win notifications.
Event Types
Jackpot Events
jackpot_won: Player wins jackpot (triggers animations)jackpot_won_other: Another player wins jackpotjackpot_value: Live jackpot value updatejackpot_closed: A jackpot level has just been won and has been marked as closed
Custom Browser Events
The widget dispatches custom browser events that can be listened to using standard DOM event listeners:
flowsJackpotWidgetJackpotWonByUser: Dispatched when the current player wins a jackpot.event.detailcontains JackpotEvent data with win details.flowsJackpotWidgetLoaded: Dispatched whenstartJackpotWidget()successfully initializes. Use this to coordinate with other application logic.
Example:
document.addEventListener('flowsJackpotWidgetLoaded', (event) => {
console.log('Widget loaded and ready');
});
document.addEventListener('flowsJackpotWidgetJackpotWonByUser', (event) => {
console.log('Player won jackpot!', event.detail);
});Examples
Basic Implementation
<script type="text/javascript" src="https://cdn.flows.world/js/jackpot-v2-latest.js" id="flows-jackpot"></script>
<script>
flowsJackpots.startJackpotWidget("{{orgId}}", "{{gameId}}", "{{playerId}}", "{{locale}}");
</script>Advanced Configuration
<script type="text/javascript" src="https://cdn.flows.world/js/jackpot-v2-latest.js" id="flows-jackpot"></script>
<script>
// Custom language, positioning, and mobile breakpoint
flowsJackpots.startJackpotWidget("Sv5L9-UJTUeYPV7iQpoZ3A", "Golden Shamrock", "[email protected]", "fr-FR", "", { top: "50px", left: "50px" }, 768);
// Clean up when done
flowsJackpots.closeJackpotWidget();
</script>Development
This project uses Bun as its package manager. Before starting development:
Install Bun
Run the following commands in your terminal:
bun run dev-setup
Use bun for all commands:
bun add package-name
bun run buildTesting
First run:
bun run serve:stagingto build & host a local version of the script connected to the staging FlowsPlay API
or
bun run serve:productionto build & host a local version of the script connected to the production FlowsPlay API
This should open a Node.JS server on port 3001. Navigate to http://localhost:3001 and you should be greeted with a test page which will allow you to enter configurations for a particular jackpot, start, display, and control the widget, view live server-side event logs, and trigger game spins to demonstrate widget functionality.

Widget UI testing
After successfully opening the widget test page, go to the FlowsPlay admin panel (https://app.flowsplay.world/ - Production environment, https://stage-app.flowsplay.world/ - Staging environment). Use of the Production environment is highly recommended since the Staging environment has very limited capability to host jackpots.
Switch to the site/organisation you want to host your jackpot on (to successfully host jackpots, the site you choose must be linked to Flows. Please contact Flows support to link your organisation). It is recommended to use the 'Demo Casino' site (site id
Sv5L9-UJTUeYPV7iQpoZ3A). If you don't have access to this site please ask someone from the Flows team to invite you to it. You need the Editor or Owner role to create jackpots on sites.Take note of your site's name and site ID by going in the settings page.
Go to the home page by clicking on the FlowsPlay logo. A table displaying a list of jackpots should be visible. Click an existing jackpot in the jackpots list, or create a new one.
- To create a new jackpot, click the 'Create new' button. When prompted with creating a new jackpot, click the 'Use the FlowsPlay Widget' button then click 'Create'.
If the jackpot is in the 'Draft' state, fill in the required inputs in the jackpot forms with necessary and valid information. After doing so, click the 'Publish changes' button on the top right to publish your jackpot.
In the jackpot 'Target' tab, take note of the game ID(s) that has/have been set for this jackpot.
Go back to http://localhost:3001. Fill in the 'Jackpot Configuration' section on the left side of the test page:
- You can choose which version of the widget script to use from the 'Script source' dropdown.
- The 'Organisation' section allows you to select the organisation where your jackpot lives in. You can either select an organisation from the visible dropdown or enter the organisation id manually in the input box. In this example, a jackpot has been created in the 'Demo Casino' organisation, so that organisation has been selected from the dropdown list. (Note: selecting an organisation from the list populates some inputs under the 'Game Actions' section to facilitate triggering of game spins, which will be discussed in a future step.)
- The 'Player ID' input box allows you to associate jackpot events with a personal ID. This can be left as default or changed to any custom value
- The 'Locale' input box allows you to select the locale for which text assets for the widget should be displayed. By default this is 'en-gb'.
- The 'Brand ID' input box allows you to set the brand for which a jackpot is associated with. It should be noted that not all organisations have brands. To check if your organisation has brands, simply go back to the FlowsPlay admin panel and click on any jackpot in the jackpots list. Click on the 'Target' tab, and if a 'Sub-brands (operators)' dropdown is visible, then the organisation supports the use of sub-brands. You will need to acquire the underlying brand ID for the brand(s) listed in this dropdown and enter it in the 'Brand ID' input box in order to correctly render the widget. If this dropdown does not appear then your organisation does not use sub-brands and the 'Brand ID' input box should be left empty.
With the jackpot configuration complete, we can now move onto the 'Widget Controls' section.
- Click the green 'Start Widget' button under the 'Widget Controls' section. The widget should be visible now, in the minimized form. If the widget is not visible, make sure to rectify any errors that become visible via toast notifications on screen or via error messages in the browser console.
- To close/shut down the widget, simply click the red 'Close Widget' button.
- The 'Show widget preview' allows one to call the widget's
showPreviewfunction, though this function is particularly reserved for use within the appearance section of the jackpot editor on FlowsPlay. - The 'Lock', 'Unlock', 'Minimize', 'Expand', 'Game Round Start', and 'Game Round End' buttons execute functionalities detailed in the API Reference section.
The 'Live SSE Messages' section allows one to display a live server-side event log. This event log will display any events (detailed in the section Real-time Event Handling). To start displaying an SSE event log, perform the following steps:
- Open the browser console and navigate to the network tab. It may be useful to clear the network log.
- Start the widget by clicking the green 'Start Widget' button. Look for a GET HTTP call with the following URL https://api.flowsplay.world/game/v1.1/sites/{your_site_id}/jackpots/games/{your-jackpot-id} or https://api.flowsplay.world/game/v1.1/sites/{your_site_id}/jackpots/games/{your-jackpot-id}/brand/{your_brand_id} if your site uses brands.
- Click on it from the list and view the 'Response' tab to view the response body.
- Copy the value for the 'workspaceId' property and paste it into the 'Workspace ID' input box, and copy the value for the 'jackpotGroupId' property and paste it into the 'Jackpot Group ID' input box (both can be found under the 'Live SSE Messages' section on the widget demo web page).
- Finally, click the green 'Start SSE' button.
The 'Game Actions' section currently only contains 1 action - to trigger a game spin, as if it you were playing a real jackpot game. The 'Site ID', 'GameEndRound Flow ID', and 'x-api-key' input boxes in this section are populated by selecting an organisation from the 'Organisation' dropdown list from the 'Jackpot Configuration' section. The 'Site ID' in this case is the same as the jackpot's Organisation ID (same value as in 'Organisation' input box from the 'Jackpot Configuration' section). If you don't choose an organisation from the dropdown list, then you will need to acquire the necessary values for these inputs from someone at Flows (CSM team or possibly Backend team).
Testing the code
All unit tests can be found in the \_\_tests\_\_ directory.
Run these tests using bun run test which will run the TypeScript compiler to detect TypeScript errors because bun test does not natively check Typescript. Therefore any code changes in src/ that cause errors in unit tests will be caught before the tests even run.
Testing local CSS changes
To test local CSS changes, you need to override the base CSS URL:
- Open FlowsJackpots.class.ts
- Find the line:
baseCSS: WidgetConstants.baseCSSUrl, - Comment it out
- Uncomment the line:
baseCSS: './assets/css/baseStyle.css', //DEBUG ONLY
This bypasses the environment-based CSS URL and loads styles directly from assets/css/ for local development.
Browser Support
- Modern browsers with ES2015+ support
- Mobile Safari and Chrome for mobile optimization
- Automatic fallbacks for older browsers
License
ISC License
Contributors
- Julian Portelli ([email protected])
- Antoine Duhesme ([email protected])
Version: 2.0.0
Author: Flows LTD
