Roxels/ docs
embed

Persistent launcher

The persistent launcher is the floating button that appears on your page and opens a Roxels conversation when clicked. It's the default UX for embeds — drop in a script, the button shows up.

Most embeds use the launcher. If you want a button you fully control, skip the launcher and call Roxels.start() from your own UI — see Headless mode or Install.

What it looks like

A small circular button anchored to a corner of the page. The label, position, and appearance are configured on the template.

When the user clicks it, Roxels opens the conversation in the display mode you configured (modal by default).

Enabling the launcher

The launcher is configured on the template, not on the page. From the dashboard:

  1. Open the template's embed settings.
  2. Enable the persistent launcher.
  3. Set the position (bottom-right is the default), the label, and any visibility rules.
  4. Save.

Pages that include embed.js for this template's embed key will now render the launcher automatically.

Configuration options

Option Description
mode "persistent" for the launcher, "manual" for no launcher (you call start() yourself).
position Corner anchor. One of bottom-right, bottom-left, top-right, top-left.
label Text shown next to the button (e.g. "Get help", "Chat with us"). Optional; the button works without one.
visibility An object with include and exclude arrays of path globs. See Visibility rules.

Anchoring the button

By default, the launcher floats in the viewport corner. You can anchor it to a specific element instead — useful when your page has a fixed footer or a chat widget that overlaps the default position.

From your code:

Roxels.init({
  templateKey: "rk-your-embed-key",
  fabAnchor: "#help-button-slot",
  // or: fabAnchor: document.getElementById("help-button-slot")
});

The button mounts inside the anchor element instead of in a floating overlay.

Visibility rules

The launcher can show on some pages and hide on others. Configure include and exclude path globs in the template:

visibility:
  include:
    - "/app/*"
    - "/dashboard/*"
  exclude:
    - "/app/billing/*"
    - "/dashboard/admin/*"

The rules use simple glob matching. A page is shown the launcher if its path matches at least one include and no exclude. With no rules configured, the launcher shows everywhere the script loads.

Updating the current path from your code

For single-page apps, the URL changes without a full page reload. Tell the launcher about it:

// In your router's after-navigation hook
router.afterEach((to) => {
  Roxels.setView(to.path);
});

Or use data-view:

<script
  src="https://app.roxels.ai/embed.js"
  data-template-key="rk-your-embed-key"
  data-view="/dashboard"
></script>

The launcher re-evaluates visibility rules on each setView call.

Hiding the launcher temporarily

Hide and show from your code:

Roxels.hideFab();
Roxels.showFab();

Useful when your UI takes over the screen (a fullscreen modal, a video player) and you don't want the launcher floating on top.

Opening from your own button

If you want a custom button somewhere on the page that opens the conversation, leave the launcher enabled (for the default UX) AND add your own:

<button id="open-chat">Talk to us</button>
<script>
  document.querySelector("#open-chat").addEventListener("click", () => {
    Roxels.open(); // opens the conversation in the configured display mode
  });
</script>

Or skip the persistent launcher entirely (set mode: "manual" in the template config) and use only your own button.

Personalization

Pass identity to the embed; the launcher carries it forward when opened:

<script
  src="https://app.roxels.ai/embed.js"
  data-template-key="rk-your-embed-key"
  data-person-name="Ada Lovelace"
  data-external-id="user_123"
></script>

Or from your code:

Roxels.setPerson({ name: "Ada Lovelace", externalId: "user_123" });

If your user signs in mid-page, call setPerson after sign-in to update the identity before the conversation starts.

When to skip the launcher

The launcher is great for general "talk to us" surfaces. Skip it when:

  • The conversation is part of a specific flow (form submission, onboarding step). Trigger it from that flow instead.
  • You're building a headless integration with your own UI for everything.
  • You want one specific button on your page that doesn't look like the Roxels default.

In those cases, set mode: "manual" on the template and call Roxels.start({ display: "modal" }) from your code.