Embeddable Widgets
Gravity Rail ships several widgets you can embed in your own site or application.
Each one is a small async loader script that creates a sandboxed iframe — one
<script> tag, no build step, no SDK.
The widgets
| Widget | Slug | Audience | Guide |
|---|---|---|---|
| Chat | chat | Your customers — an anonymous visitor starts an AI conversation | Chat Widget |
| Operator | operator-tools | Your staff — an operator works the member, chat, and live-call queue | Operator Widget |
| Chat app | chat-app | Signed-in members — a full multi-conversation chat inbox | Not yet documented. It embeds the same way; ask us if you need it |
operator | — | Retired. Do not embed |
operator is the retired predecessor of operator-tools. Its route and loader
have been removed; it remains in the widget registry — and therefore in generated
client types and the domain-settings checkbox list — only for backwards
compatibility. Embedding it produces a blocked frame, not a widget. Use
operator-tools.
Chat and operator are different products, not two configurations of one. Chat is a customer-facing entry point with no sign-in. Operator is a staff console behind a member sign-in. They are enabled separately per domain, and enabling one does not enable the other.
What every widget shares
One script tag. https://app.gravityrail.com/widgets/<slug>.js, configured
with data-* attributes. data-wid (your workspace UUID or slug) is always
required.
Three embed modes, selected with data-mode: floating (a launcher button in
the corner), inline (a trigger button you place yourself), and embedded (the
panel rendered directly into your layout).
A fail-closed verified-domain gate. Which parent origins may embed a widget is
decided per (workspace, domain, widget) and is self-service in the app: verify
the domain at the organization level with a DNS TXT record, then enable the
specific widget on it under Settings → Widgets. Until that is done, every
external origin is denied — with an HTTP 403 and a frame-ancestors policy that
blocks the frame outright. Each widget is a separate tick box; authorizing one does
not authorize another.
Verification is organization-wide; enablement is per workspace. You verify
example.comonce for your whole organization, but you enable a widget on it inside one workspace — anddata-widin your snippet selects that workspace. If your organization has several workspaces, make sure the workspace you enabled the domain on is the workspace your snippet names. Enabling on one and embedding another is the most common reason a correctly-verified domain is still blocked. Copying your snippet from Settings → Widgets → Widgets in the right workspace gets this right automatically.
Subdomain coverage only ever adds. Each enabled domain can Allow subdomains.
With it off, only the exact host is authorized. With it on, the apex and its
subdomains are — https://example.com and https://*.example.com. It cannot take
away the apex, so it is safe to switch on when you need preview hosts such as
pr-123.example.com. The wildcard covers a single label, and it is set per
workspace-and-domain, so the same verified domain can be exact-host for one
workspace and wildcard for another.
HTTPS everywhere. Only HTTPS origins can be authorized, and the browser requires a secure context for microphone access and for the widget's session storage.
No cross-site cookie requirement. Widgets that need a signed-in member authenticate with a bearer session established by an inline sign-in inside the iframe, held in the iframe's own partitioned storage. There is no cookie configuration to do on either side, and third-party cookie blocking does not affect them.
A narrow cross-frame protocol. The only postMessage traffic between your page
and the widget is control and status signals — panel open/close and resize for
every widget, plus badge counts, presence, and incoming-interaction alerts for the
operator widget. No conversation content or member data is readable by the host
page, and origin checks run in both directions.
A code generator in the app. Settings → Widgets → Widgets is an embed studio: pick a widget, configure it, preview it live, and copy the snippet as HTML, React, or Next.js.
Where to go next
- Chat Widget — the full chat embed reference, plus the local HTTPS development setup that applies to any widget
- Operator Widget — the operator console embed, including the host control API, notifications, and the domain-gate troubleshooting matrix