Embedding the widget
Once the widget looks right, put it on your site. Open Dashboard → Widget → Install, copy the snippet, paste it into your pages, and add your domain to the allow-list. Five minutes, and only the last step is easy to forget.
🖼️ [Image] — The Install page with the Script Tag snippet, platform tabs, and the Allowed Domains editor.
Copy the embed code
Two variants, on two tabs:
- Script Tag (Recommended) — a floating launcher that opens into the chat window. This is what you want in almost every case.
- iFrame — the chat embedded inline in the page, for a dedicated "contact us" page or a support portal.
Copy copies whichever tab is active (the button reads Copied! for a moment afterwards). The script version looks like this, pre-filled with your own values:
<script
src="https://api.promptly-assistant.com/widget/embed.js"
data-tenant="your-tenant-slug"
data-api-key="pk_your-widget-key"
data-api-base="https://api.promptly-assistant.com"
data-widget-base="https://api.promptly-assistant.com/widget"
async
></script>| Attribute | What it's for |
|---|---|
data-tenant | Your workspace slug — which assistant to load. |
data-api-key | Your public widget key (pk_…). Public by design and safe in page source; it's scoped to the chat endpoints and enforced alongside the domain allow-list. See API keys & encryption. |
data-api-base | The Promptly API the widget talks to. |
data-widget-base | Where the widget's own assets are served from. |
The tag is async, so it never blocks your page from rendering.
Optional attributes you can add by hand:
data-auto-open="5000"— open the chat by itself after N milliseconds. Use sparingly.data-lang="sr"— force the widget's interface language instead of following the browser.data-on-disabled="hide"— when the widget is switched off, remove it entirely instead of showing an "unavailable" panel.
Note that data-style and data-position are honoured only until your saved configuration loads, at which point Dashboard → Widget wins. Style the widget there, not in the tag.
The iFrame variant carries the same key in its URL and comes with fixed positioning already applied; adjust its style attribute to place it where you want.
Where to paste it
Just before the closing </body> tag, on every page the widget should appear on.
The Install page carries step-by-step instructions for HTML, React / SPA, WordPress, Shopify, Wix, Squarespace, and Webflow. The React tab additionally generates a ready-made component — see React & SPA integration.
If someone else maintains the site, use Share with Developer: enter their email and an optional note, and Promptly sends them both snippets with installation instructions.
🎬 [Video] — Pasting the script before
</body>, adding the domain, reloading, and sending the first message.
Allowed Domains — the step everyone skips
The widget only loads on origins you've approved, so a fresh install on an unlisted domain looks exactly like a broken install. The editor sits on the same Install page and has two tabs:
- Production Domains — your real hostnames. Protocols, paths, and ports are stripped for you, so
https://example.com/shopbecomesexample.com. Wildcards work:*.example.comcovers every subdomain. - Local Testing —
localhost,localhost:3000,127.0.0.1,::1. Entries here get a DEV badge. Addinglocalhostwithout a port allows all ports.
Up to 20 entries across both tabs. Save Domains appears once you've made a change.
One nuance worth knowing: with no domains configured at all, the widget will load anywhere. That's convenient on day one and a bad idea by day two — anyone could embed your assistant on their own site and spend your provider credits. Add your domains. See Origin guard & rate limiting.
How it stays out of your CSS
The widget renders inside a Shadow DOM host (#promptly-widget-host) and the chat itself lives in an isolated iframe. Your stylesheets can't leak in and the widget's styles can't leak out, so what you designed in the customizer is what visitors get — on a Tailwind site, a WordPress theme, or a twenty-year-old stylesheet.
The host element is fixed-position, zero-size, and pointer-events: none until the launcher renders, so it never blocks clicks on your page.
Driving it from your own code
Once loaded, the embed exposes a small global you can call from your site:
Promptly.open(); // open the chat
Promptly.close();
Promptly.toggle();
Promptly.expand(); // expanded (wide) mode
Promptly.collapse();
Promptly.setColor('#0EA5E9');Handy for wiring your own "Chat with us" link or footer button to the widget instead of showing two entry points. There's no destroy() — to remove the widget, see the cleanup pattern in React & SPA integration.
Turning it on and off
The master switch is Dashboard → Settings → Widget enabled. Off means the widget doesn't load for anyone, immediately, with no site edit needed. The script tag can stay exactly where it is.
Troubleshooting: the launcher doesn't appear
In this order, because this is the order the causes actually occur in:
- Is the widget enabled? Check Settings → Widget enabled. If it's off, you'll see the "hidden from all visitors" banner there.
- Is the domain approved? Add the site under Allowed Domains — and
localhostunder Local Testing if you're developing. A blocked origin is the single most common cause. - Do you have a working AI key? A workspace with no verified key shows an unavailability message instead of a chat, because there's nothing to answer with. See Troubleshooting keys.
- Are the values right?
data-tenantmust match your slug anddata-api-basemust point at your Promptly host. - Any console errors? Open your browser's developer console and look for messages from
embed.js. A blocked origin says so explicitly there.