window.LuaPop is the global the hosted widget script defines. init() merges built-in defaults, the admin dashboard settings for the current domain, and the options you pass, then mounts the widget inside a shadow root on document.body (floating mode) or inside a container you name (embedded mode). The script is the only distribution; there is no npm package.
Quick example
Methods
init()
Mounts the widget and resolves once it is on the page.Partial<LuaPopConfig>
The options listed under Options. Omit it to use admin dashboard settings alone.
WidgetInstance whose only method is destroy(), or null when nothing was mounted: no admin dashboard settings were found and no options were passed, the current path matches excludedPaths, or displayMode is "embedded" and the container is missing. Calling init() again replaces the mounted instance.
Errors — logged to the console, never thrown: LuaPop: Invalid environment value "…" (the widget then uses "staging"), LuaPop: embeddedDisplayConfig.targetContainerId is required when displayMode is 'embedded', and LuaPop: Target container with id "…" not found.
destroy()
Unmounts the widget and removes its host element.window.LuaPop.destroy() does the same for whichever instance is mounted and is safe to call when none is.
Properties
config
window.LuaPop.config is the merged configuration the mounted widget is using. Read it to see what the admin dashboard supplied.
Options
Precedence, lowest to highest: built-in defaults, the admin dashboard settings for the domain (andagentId) the page loads on, and the object you pass to init(). Functions and regular expressions can only come from code.
Agent and environment
Inside a tool,Lua.request.channel is pop for a widget turn, and lua logs shows pop in metadata.channel. The Channel type spells this value web, so compare against both pop and web; see Lua.
string
The agent to talk to. Required unless the admin dashboard settings for the domain supply it; always pass it on a domain that hosts several agents.
"production" | "custom" | "staging"
default:"\"staging\""
Which platform the widget talks to. Use
"production". It is set for you only when admin dashboard settings are found, so pass it explicitly with any inline options. "custom" sends requests to customBaseApiUri. "staging" is Lua’s internal platform, where your agent does not exist.string
API base URL used when
environment is "custom".string
Free text sent to the agent with every message, for example the current page or the end user’s plan. Keep personal data out of it.
Identity
string
Identifies the end user’s conversation and is a bearer secret: whoever presents it resumes that conversation. When omitted, the widget generates a UUID on first load and stores it in
localStorage under lua_pop_session_id, so the same browser resumes the same conversation. A value you pass is stored the same way. Issue one unguessable value per signed-in end user from your backend, not a guessable one such as customer-<id>, and never log it or send it to analytics; every new value starts a new conversation. destroy() leaves the stored value in place, so on sign-out remove the key, then call destroy() and init() again. The widget end user is the current end user in User.get(); see Identify users.string
Replaces
sessionId as the end user’s identity on an agent that Lua has set up with a custom sign-in. On any other agent the token is ignored and, because the widget then sends no session ID, every page load starts a new anonymous conversation; leave it unset.Display
"floating" | "embedded"
default:"\"floating\""
"floating" shows a button that opens a chat window. "embedded" renders the conversation inside the container named in embeddedDisplayConfig: the chat is always open, and the floating-button and chat-window options have no effect.object
Required when
displayMode is "embedded"."light" | "dark" | "auto"
default:"\"auto\""
"auto" follows prefers-color-scheme; the other two pin the palette.(string | RegExp)[]
Paths where the widget must not appear. A string matches when
location.pathname contains it; a RegExp is tested against the pathname. The widget also removes itself when a single-page app navigates to an excluded path and stays away until the next init().Floating button
"bottom-right" | "bottom-left" | "top-right" | "top-left"
default:"\"bottom-right\""
Corner of the viewport.
boolean
default:false
Adds a grip so end users can drag the closed button elsewhere.
position is the starting corner; the chosen spot is remembered per agent in the end user’s browser.string
default:"\"Chat with us\""
Label on the button. Emoji are fine here.
string
Background color of the button. Defaults to the theme’s primary color.
string
URL of an image rendered at 16 × 16 px in place of the Lua logo. Not an emoji.
React.CSSProperties
Inline styles for the button: camelCase keys, plain values, no
!important. A background here overrides buttonColor.React.CSSProperties
Inline styles for the fixed container that holds the button and the chat window, for example
{ bottom: "24px", right: "24px" }.Chat window
string
default:"\"Lua Assistant\""
Title in the header.
React.CSSProperties
Inline styles for the header.
object
The “Powered by” line under the title. Shown by default with the brand name
Lua; clicking it opens a contact form.string | number
default:"\"500px\""
Height of the window on desktop, capped at 80% of the viewport height. Numbers are pixels. On screens narrower than 640 px, and on phones and tablets at any width, the window is full-screen instead.
string | number
default:"\"350px\""
Width of the window on desktop. Numbers are pixels. Ignored where the window is full-screen.
string
default:"\"👋 Welcome!\""
First agent message when the conversation has no history. It is saved to the conversation, so the agent sees it as its own opening line.
Composer and features
string
default:"\"Ask anything, about anything\""
Placeholder of the message box.
boolean
default:true
Shows the attachment button. Accepted types: images, video, audio,
.pdf, .doc, .docx, and .txt. Files upload to Lua’s CDN before the message is sent.boolean
default:true
Shows the microphone button, which records a voice message and sends it as audio together with any typed text.
boolean
default:true
Shows the waveform button, which starts a live voice conversation. See Voice chat in the widget.
boolean
default:false
Renders the URLs in a
::: links block as plain links instead of fetching previews.Navigation
Called when a reply contains a
::: navigate block, with the path and its parsed query parameters. The widget also reports to the platform that the page can navigate, but nothing adds the block to the prompt: include its syntax in the persona or a skill context. Code only.Types
LuaPopConfig is the object type made of every option on this page. A declaration file to paste into a TypeScript project is on Frameworks.
See also
- Add the chat widget to your website — quickstart
- Style the widget — theme, colors, and CSS inside the shadow root
- Track widget events — the
postMessageevents - Troubleshoot the widget — symptom-first fixes
- Channels — where the widget fits among channels

