Skip to content

Programmatic API

The widget exposes a minimal global on window.LeFlux so you can drive it from your site’s own JavaScript.

Availability

window.LeFlux is populated AFTER the widget mounts. Wait for the leflux:ready event before calling anything:

window.addEventListener('leflux:ready', () => {
console.log('LeFlux ready', window.LeFlux);
});

If you reference window.LeFlux before mount it’ll be undefined.

Methods

LeFlux.open()

Opens the chat panel. No-op if already open.

window.LeFlux.open();

Useful for tying a custom button on your site to “open the chat” without using the launcher.

LeFlux.close()

Closes the chat panel.

window.LeFlux.close();

LeFlux.toggle()

Toggles open/closed.

LeFlux.send(text)

Sends a message AS THE VISITOR. Useful for deep-link CTAs (“Ask about pricing” buttons that pre-populate the chat).

window.LeFlux.send('Show me the pricing plans');

Behaves identically to the visitor typing + pressing Enter. The agent processes it the same way.

LeFlux.ask(question)

Like send() but explicitly framed as an ask — agent treats it as a question and prefers an inline answer over actions.

LeFlux.setVisitorData({ name, email, phone, ...custom })

Pre-populate the visitor’s data store so form-fills don’t ask for fields you already know.

window.LeFlux.setVisitorData({
name: 'Ahmed Khan',
email: 'ahmed@example.com'
});

Useful on authenticated pages — your app already knows the user, so pre-set the data to skip ask_user.

Values persist in localStorage with the same 30-day TTL as visitor-entered data.

LeFlux.dock() / LeFlux.undock()

Programmatically switch between floating mode and docked side-panel mode.

LeFlux.clearConversation()

Wipe the persisted chat history (localStorage) and start a fresh session. Useful for “Reset chat” buttons or post-logout cleanup.

LeFlux.showLauncher(visible)

Per-page override of the dashboard “Hide launcher” setting. Pass true to force-show the FAB, false to hide. Does NOT persist — refreshing the page returns to whatever the Firestore config says.

// Hide the launcher only on /checkout
if (location.pathname === '/checkout') {
window.addEventListener('leflux:ready', () => window.LeFlux.showLauncher(false));
}

LeFlux.reindex()

Force the agent to rescan the page for interactive elements. The widget already reindexes automatically on SPA route changes, modal opens, and DOM mutations — only call this manually if you mutated the DOM in a way the MutationObserver missed (rare, mostly debug).

LeFlux.destroy()

Tear down the widget. Closes WebSocket, removes the shadow root, removes all event listeners. Call this if you need to unmount the widget (e.g. in a SPA where chat is feature-gated by route).

After destroy(), calling other methods is a no-op. To remount, reload the page or re-attach embed.js.

State getters

Read-only introspection. All of these return synchronously.

MethodReturns
LeFlux.isReady()true once the widget has mounted + the session is established.
LeFlux.isOpen()true if the chat panel is currently open.
LeFlux.isExpanded()true if docked into side-panel mode.
LeFlux.getLanguage()Last detected reply language code — 'en', 'de', 'ar', 'es', 'roman-urdu', etc.
LeFlux.getSessionId()Current session UUID, or null before leflux:ready.
LeFlux.getState()Snapshot of everything below.

getState() returns:

{
ready: true,
open: false,
expanded: false,
conversation: 'idle', // 'idle' | 'typing' | 'processing' | 'navigating' | 'awaiting-input'
language: 'en',
sessionId: '...',
layout: 'floating',
host: 'example.com'
}

conversation is the high-level state machine you can wire UI off of (spinner, disabled CTA, analytics events). Listen to leflux:state-change for live transitions.

Subscriptions

LeFlux.on(name, handler) — thin sugar over window.addEventListener('leflux:' + name, handler). Returns an unsubscribe() function so you don’t have to keep a reference to the handler:

const unsub = window.LeFlux.on('reply', (e) => {
console.log('agent said:', e.detail.text);
});
// later:
unsub();

LeFlux.off(name, handler) — manual unsubscribe if you already have the handler reference.

Events

The widget dispatches CustomEvents on window you can listen to:

EventWhen
leflux:readyWidget mounted, API available. detail is the full getState() snapshot.
leflux:openChat opened. detail.source is 'click' | 'api' | 'restore'.
leflux:closeChat closed. detail.source same shape as above.
leflux:expandVisitor (or LeFlux.dock()) docked the chat into side-panel mode.
leflux:collapseUndocked back to floating.
leflux:messageVisitor sent a message. detail.text, detail.ts, detail.sessionId.
leflux:replyAgent finished a reply. detail.text, detail.ts, detail.isQuestion, detail.isError.
leflux:typing-startAgent started typing (dots appeared).
leflux:typing-endTyping dots cleared (reply landed OR agent moved to actions).
leflux:state-changeConversation state machine transitioned. detail.state, detail.prev, detail.ts.
leflux:actionAgent is about to execute an action. detail.type, detail.target, detail.description.
leflux:navigatingAn action plan includes a navigate step. detail.url, detail.method.
leflux:language-detectedThe reply language changed since the last message. detail.lang, detail.prev.
leflux:task_completeMulti-step task ended. detail.summary.
leflux:errorAn error surfaced. detail.message, optional detail.code.
leflux:destroyFires once when LeFlux.destroy() completes (window.LeFlux is unset immediately after).

Example — fire your analytics on every visitor message:

window.addEventListener('leflux:message', (e) => {
analytics.track('chat_message', { text: e.detail.text });
});

Embed-script data attributes

A few optional config knobs live on the <script> tag instead of the JS API (since they’re read before the widget mounts):

AttributeWhat
data-preview"true" skips server calls entirely — useful for visual testing without registering a site.
data-no-user-memory"true" disables the 30-day visitor data cache (no name/email recall across forms).
data-no-visitor-id"true" disables the anonymous visitor-id cookie.
data-no-spa-detect"true" disables History API patching (rare, mostly debug).
data-debug"true" re-enables verbose [LeFlux] console logs on a production hostname. By default, logs are silent on customer prod and loud on localhost / *.local / staging.* / dev.* / preview.* / test.*.

None of these are required. The widget mounts with safe defaults if you paste only the bare snippet.

Notes

The API is intentionally tiny — most config belongs in the dashboard, not in code. If you find yourself reaching for advanced JS API, the dashboard probably has a knob for it. Open an issue if you hit a real gap.

For server-side integrations (push events into Slack, log to your own analytics backend, custom action verification) see the WebSocket events reference.