Are you an LLM? You can read better optimized documentation at /docs/embedding/quickstart.md for this page in Markdown format
Quickstart
A visitor lands on Acme Store's product page. You want the Perfox chat bubble to appear, know who they are, and route their first message to the right agent — all without building a backend. You need one <script> tag and a few lines of JavaScript.
By the end of this guide you'll have a working widget on any page, with visitor identity wired up and the SDK connected.
0. Get your embed credentials
In Studio, open your agent, click its Web Chat trigger node and switch to the Install tab. Enter the origins your site is served from (for example https://www.example.com), then click Generate Credentials. Perfox shows your Site key (sa_site_live_…), your API host and a ready-to-paste snippet — plus a site secret, shown once, that you only need for Identity Verification.
Publish the agent: the embedded widget always runs your published version.
1. The embed snippet
Paste these two scripts into your page's <head> or just before </body>, in order:
html
<script>
(function(){var w=window;w.Perfox=w.Perfox||function(){(w.Perfox.q=w.Perfox.q||[]).push(arguments);};})();
</script>
<script
src="https://your-workspace-api.perfox.ai/widget/v1/widget.js"
data-site="sa_site_live_YOUR_SITE_ID"
defer></script>Two scripts, in order:
- The queue stub. It defines
window.Perfoxas a function that pushes each call ontowindow.Perfox.q. When the bundle loads, it replaces the stub with the real dispatcher and replays any buffered.qcalls — soPerfox('identify', …)fired before the bundle loaded is not lost. - The widget bundle (
defer, non-blocking), served from your API host at/widget/v1/widget.js. It carries thedata-*attributes the bundle reads on first load.
Two attributes matter here:
| Attribute | Required | Purpose |
|---|---|---|
data-site | Yes | The public Site key (sa_site_live_… / sa_site_test_…), sent as the X-Perfox-Site header on every request. Missing data-site logs a console error and every request is rejected. |
src | Yes | Your widget bundle URL on your API host (https://<slug>-api.perfox.ai/widget/v1/widget.js). The API origin is derived from this src. |
Site keys have the form sa_site_<env>_<52 chars> — sa_site_live_* for production, sa_site_test_* for testing. The widget resolves the site from data-site and routes the first message to the agent the site is bound to. See the full attribute set in the Embed Script Reference.
2. Identify the visitor
When you know who the visitor is, call identify so the agent can address them by name and the conversation attributes to the right customer:
js
window.Perfox('identify', {
name: 'Asha Iyer',
email: 'asha@example.com',
phone: '+919876543210',
external_id: 'cust_abc123', // your stable customer id — the best anchor
});identify replaces the whole user object — any field you omit is dropped. Use update for a partial patch. Identity travels with every request, so a late identify call applies as long as it lands before the next message send. The queue stub makes a pre-load call safe.
For verified production sessions, also pass an HMAC-signed user_hash; see Identity Verification.
3. Control the widget from JavaScript
window.Perfox(command, ...args) dispatches commands to the widget:
js
Perfox('show'); // bubble visible
Perfox('hide'); // bubble hidden
Perfox('open'); // panel expanded
Perfox('close'); // panel collapsed
Perfox('shutdown'); // log the visitor out of the widgetFire shutdown on logout. It clears the current user, disconnects any active voice call, forgets the conversation this browser was resuming, and emits user(undefined) + shutdown. Without it, the next visitor on the same browser resumes the previous user's conversation.
The full command list is in the SDK Reference.
4. React to widget events
js
Perfox('on', 'ready', (info) => {
console.log('widget ready', info.workflow_id, info.capabilities);
});
Perfox('on', 'message:received', (m) => {
analytics.track('chat_reply', { text: m.text });
});on(event, cb) subscribes; off(event, cb) with the same callback reference unsubscribes. Unknown commands emit a console.warn. Full event list → Events.
Worked example: identify then open
Setup — Asha signs into Acme Store. Your app has her name and email.
Action — On page load, you call:
js
window.Perfox('identify', {
name: 'Asha Iyer',
email: 'asha@example.com',
external_id: 'cust_abc123',
});
window.Perfox('open');Result — The chat panel opens. When Asha types "Where's my order?", the agent greets her as "Hi Asha" and looks up her order history using the context you passed.
What just happened — The queue stub captured both calls before the bundle loaded. When the bundle finished, it replayed them in order: first identify set Asha's profile on the session, then open expanded the panel. Your agent received her identity on the very first message send.
How a message flows
The embedded widget talks to Perfox's public widget API under /api/public/widget on your API host — POST /init, POST /send, GET /history, POST /conversations/new, POST /upload, POST /voice/start and a few more (the full list is in the Public Widget API). Every request carries your Site key and must come from one of the site's allowed origins; your data stays private to your workspace.
Where to next
You can now show the widget, identify visitors, and send commands from JavaScript. Here's what to explore next:
- Embed Script Reference — every
data-*attribute the bundle reads - SDK Reference — every SDK command with full parameter details
- Identity Verification — sign identity with HMAC for production trust
- Events — events the SDK emits so you can hook analytics or UI changes
- Voice & Dial-Out — add voice chat and outbound calls to the widget
- File Upload — let visitors attach files from the chat