Skip to main content
After this guide, the widget mounts once in your single-page app and disappears cleanly when the component that owns it unmounts. There is no npm package: every framework loads the same hosted script and calls window.LuaPop.init() once it is on the page. For plain HTML, the quickstart is enough; if you are replacing Intercom, Zendesk, or Drift, the option mapping is under Migrating from another widget. Before you begin
  • Your agent ID, and the widget working on a plain page per the quickstart.
  • environment: "production" in every call: it is inferred only when admin dashboard settings are found for the domain.
1

Load the script and initialize once

Create a component that appends the script on mount, calls init() when it loads, and calls window.LuaPop.destroy() on unmount. Render it once, near the root of the app.
src/components/ChatWidget.tsx
init() replaces any instance that is already mounted, so a second call during hot reload is harmless.
2

Type the global

The script declares nothing for TypeScript. Add a declaration file so window.LuaPop type-checks; the option types match the deployed widget.
src/types/lua-pop.d.ts
3

Verify

Run the app, open a route that renders the component, then one that doesn’t. The button appears on the first and is gone on the second, and document.getElementById("lua-shadow-root") returns null after the unmount.

Options you may need

Hide the widget on some routes

Instead of unmounting, pass excludedPaths; the widget removes itself when the router moves to a matching path and returns on the next init().

Keep one conversation per signed-in end user

Pass a sessionId your backend issues per end user and run init() again when the end user changes, as the React example does. The value is a bearer secret, because whoever presents it resumes the conversation, so make it unguessable: customer-${user.id} is not, and every new value starts a new conversation. The widget stores it under the localStorage key lua_pop_session_id, and destroy() doesn’t clear it, so clear it on sign-out or the next end user on that browser resumes the conversation.
How this end user appears to your tools is on Identify users.

Next steps

Widget configuration

Every option and what init() returns.

Troubleshoot the widget

When the button is missing or the chat won’t open.