Skip to content
Reference

Widget and JavaScript

One script tag to install, a handful of commands to control the chat from your own code, and signed identity for your logged in users.

Install

Add the script before the closing </body> tag on every page where the chat should appear. Your site ID is on the website's page in the dashboard.

index.html
<script
  src="https://api.recursivechat.dev/widget.js"
  data-site="wgt_your_site_id"
  async
></script>
  • The script is small, has no dependencies and loads without blocking your page.
  • The chat lives in a closed shadow DOM, so your CSS cannot affect it and its CSS cannot affect you.
  • Colours, position, avatar and header text are set in the dashboard, under the agent’s Settings, Appearance. Changes show the next time a page loads.

Calling the API before it loads

Commands are calls to window.RecursiveChat. Add this stub before your own code and you can call commands straight away: they are queued and run once the widget has loaded.

app.js
window.RecursiveChat = window.RecursiveChat || function () {
  (window.RecursiveChat.q = window.RecursiveChat.q || []).push(arguments);
};

Commands

CommandWhat it does
openOpens the chat panel.
closeCloses the chat panel.
toggleOpens the panel if closed, closes it if open.
sendMessageOpens the chat and sends a message as the visitor. Takes the message text.
setMetadataAttaches details to the visitor, such as their plan. See Visitor details.
identifyLinks the visitor to your signed in user. See Signed identity.
resetForgets the visitor in this browser and closes the chat. Call it when a user signs out.
hideRemoves the chat button and panel from the page until you call show.
showBrings the chat back after hide.
app.js
// Your own help button
document.querySelector('#help').addEventListener('click', () => {
  RecursiveChat('open');
});

// Start a conversation with a question
RecursiveChat('sendMessage', 'I need help with my invoice');

Visitor details

Details you attach are shown to your team next to the conversation in the Inbox. The AI sees only the fields you tick in the agent's Settings, under What the AI knows about the visitor.

app.js
RecursiveChat('setMetadata', {
  plan: 'Pro',
  is_trial: false,
  seats: 4,
});
  • Keys use letters, numbers and underscores, start with a letter and are up to 40 characters, such as plan or is_trial.
  • Values are text (up to 500 characters), numbers or true and false.
  • Up to 25 fields per call. Each call merges into what you sent before.
  • Metadata is not verified, so use it for context, never for decisions about access or money.

Signed identity

Identify links a visitor to a user in your own system. The same person then keeps one conversation history on every device, their name and email show in the Inbox, and the chat never asks them for their email.

To stop anyone pretending to be another customer, your server signs the user's ID with your site's identity secret using HMAC-SHA256, and RecursiveChat checks the signature. The secret is on the website's page in the dashboard.

server.js (Node.js)
import { createHmac } from 'node:crypto';

// Your site's identity secret, from Websites > your site in the dashboard.
// Keep it on the server: never send it to the browser.
const signature = createHmac('sha256', process.env.RECURSIVECHAT_IDENTITY_SECRET)
  .update(String(user.id))
  .digest('hex');
server.py (Python)
import hashlib, hmac, os

signature = hmac.new(
    os.environ["RECURSIVECHAT_IDENTITY_SECRET"].encode(),
    str(user.id).encode(),
    hashlib.sha256,
).hexdigest()
server.php (PHP)
$signature = hash_hmac(
    'sha256',
    (string) $user->id,
    getenv('RECURSIVECHAT_IDENTITY_SECRET')
);
app.js
// In the browser, once the user is signed in
RecursiveChat('identify', {
  externalCustomerId: String(user.id),
  signature,               // from your server
  name: user.name,         // optional
  email: user.email,       // optional
  metadata: { plan: user.plan },  // optional
});

// When they sign out
RecursiveChat('reset');
  • externalCustomerId is your user ID as text, up to 128 characters. Sign exactly the same string you send.
  • signature is the 64 character hex digest.
  • name, email, phone and metadata are optional.

Single page apps

In apps that change pages without a full reload, the chat stays on screen between routes. Use hide and show to keep it only where you want it.

router.js
// Show the chat on public pages, hide it inside your app
router.afterEach((to) => {
  RecursiveChat(to.path.startsWith('/app') ? 'hide' : 'show');
});

Privacy and security

  • The widget holds no secrets. It talks to our API with a short lived token that only works for that visitor’s own conversation.
  • Visitors are anonymous until they give an email or you call identify.
  • Page addresses are recorded so your team can see where a visitor is, with tokens and similar sensitive query parameters removed.
Next: REST API