Skip to main content
Cover Placeholder Voiceflow’s web chat API gives you programmatic control over the widget’s behavior. You can customize how conversations persist, pass in user data, trigger intents, send proactive messages, and listen for events.

Understanding the default snippet

When you copy the widget code from Widget in the sidebar, you get a snippet like this:
<script type="text/javascript">
  (function(d, t) {
      var v = d.createElement(t), s = d.getElementsByTagName(t)[0];
      v.onload = function() {
        window.voiceflow.chat.load({
          verify: { projectID: 'YOUR_PROJECT_ID' },
          url: 'https://general-runtime.voiceflow.com',
          versionID: 'production',
          voice: {
            url: "https://runtime-api.voiceflow.com"
          }
        });
      }
      v.src = "https://cdn.voiceflow.com/widget-next/bundle.mjs";
	  v.type = "text/javascript"; s.parentNode.insertBefore(v, s);
  })(document, 'script');
</script>
The chat.load() function initializes the widget. You can extend it with additional configuration options described in this guide.

Setting the agent version

The versionID property specifies which version of your agent to load. The snippet from the Voiceflow UI defaults to production, but you can also use development or staging to test changes before publishing.
window.voiceflow.chat.load({
  verify: { projectID: 'YOUR_PROJECT_ID' },
  url: 'https://general-runtime.voiceflow.com',
  versionID: 'development' // or 'production'
});
When using development, click the Run button or press R from your agent’s canvas to push your latest changes. If versionID is set to production or staging before you’ve published your agent, the widget won’t render any messages.

Setting the runtime URL

This feature is only available to Enterprise customers who are hosted on a Private Cloud.
The url property defines the runtime endpoint the widget communicates with. Private Cloud customers should replace the default URL with their dedicated runtime endpoint provided by Voiceflow.
window.voiceflow.chat.load({
  verify: { projectID: 'YOUR_PROJECT_ID' },
  url: 'https://your-private-cloud-endpoint.com',
  versionID: 'production'
});

Configuring chat persistence

Chat persistence determines whether users return to an ongoing conversation or start fresh when they reload the page, open a new tab, or come back later. Configure this with the persistence property inside the assistant object.
window.voiceflow.chat.load({
  verify: { projectID: 'YOUR_PROJECT_ID' },
  url: 'https://general-runtime.voiceflow.com',
  versionID: 'production',
  assistant: {
    persistence: 'localStorage'
  }
});
OptionBehavior
localStorageDefault. Conversations persist across page reloads and browser sessions.
sessionStorageConversations persist across page reloads but reset when all tabs are closed.
memoryConversations reset on every page reload or new tab.

Passing a custom user ID

You can assign a unique ID to each user with the userID property. This ID becomes available in your agent as the built-in {user_id} variable, which is useful for identifying users across sessions and personalizing interactions.
window.voiceflow.chat.load({
  verify: { projectID: 'YOUR_PROJECT_ID' },
  url: 'https://general-runtime.voiceflow.com',
  versionID: 'production',
  userID: 'user_12345'
});

Passing custom variables

You can pre-fill variables when the widget loads using the launch.event.payload field. These values populate the last_event system variable and can be accessed using Code step.
window.voiceflow.chat.load({
  verify: { projectID: 'YOUR_PROJECT_ID' },
  url: 'https://general-runtime.voiceflow.com',
  versionID: 'production',
  launch: {
    event: {
      type: 'launch',
      payload: {
        user_name: 'Mary',
        user_email: '[email protected]'
      }
    }
  }
});
These values can be accessed using a Code step in the format shown below. Many users use an initialization workflow to run logic based on these values.
user_name = last_event.payload.user_name
user_email = last_event.payload.user_email
Note that the Code step can’t create new variables. You’ll need to create user_name and user_email as variables in your project first. Also, last_event is updated on each user interaction (eg: when the widget loads, an intent triggers, or a button is clicked), so capture these values at the start of the conversation.

Annotating transcripts with metadata

You can pass user profile information that appears in your Transcripts. This metadata is for labeling conversations in the UI only and isn’t available to your agent’s logic.
window.voiceflow.chat.load({
  verify: { projectID: 'YOUR_PROJECT_ID' },
  url: 'https://general-runtime.voiceflow.com',
  versionID: 'production',
  user: {
    name: 'Mary',
    image: 'https://example.com/avatar.jpg'
  }
});

API methods

Once the widget script loads, it registers the API as window.voiceflow.chat. You can use these methods to control the widget programmatically.
MethodDescriptionAvailable in overlay modeAvailable in embedded mode
load({ config })Initializes the chat widget. Parses configuration, fetches remote assistant settings from the Voiceflow API. Nothing works until load is called.YesYes
open()Opens the chat window. If the session is idle, also triggers the launch event (starts the conversation). Emits a voiceflow:open broadcast event. Only effective in overlay mode.YesNo
close()Closes the chat window, interrupts audio, clears no-reply timeouts, and saves the session. Emits a voiceflow:close broadcast event. Only effective in overlay mode.YesNo
destroy()After calling this, all methods become no-ops until load is called again..YesYes
show()Shows the widget again after it was hidden with hide(). Only effective in overlay mode.YesNo
hide()Hides the entire widget (chat window AND launcher button) from view. Only effective in overlay mode.YesNo
showPopover()Shows the chat as a popover dialog. Only effective in overlay mode.YesNo
hidePopover()Hides the popover dialog with a closing animation. Only effective in overlay mode.YesNo
isPopoverShowing()Returns whether the popover is currently visible (including during close animation). Only effective in overlay mode.YesNo
interact({ action })Sends a simulated user action. Can trigger specific intents or events.YesYes
proactive.push(...messages)Pushes proactive messages (speech bubbles) that appear near the launcher button before the user opens chat. Only effective in overlay mode.YesNo
proactive.clear()Clears all proactive messages. Only effective in overlay mode.YesNo-op

Examples

Open the widget automatically after 3 seconds:
setTimeout(() => {
  window.voiceflow.chat.open();
}, 3000);
Trigger an intent when a button is clicked:
document.getElementById('support-btn').addEventListener('click', () => {
  window.voiceflow.chat.open();
  window.voiceflow.chat.interact({
    type: 'intent',
    payload: { intent: { name: 'support_request' } }
  });
});

Sending proactive messages

Proactive messages appear outside the chat window before users open it. They’re useful for prompting engagement, such as offering help or announcing promotions. These messages don’t appear in transcripts and don’t consume credits. Cover Placeholder

Pushing messages

Use window.voiceflow.chat.proactive.push() to send one or more messages:
// Single message
window.voiceflow.chat.proactive.push({
  type: 'text',
  payload: { message: 'Need help? Ask me anything!' }
});

// Multiple messages
window.voiceflow.chat.proactive.push(
  { type: 'text', payload: { message: 'Welcome back!' } },
  { type: 'text', payload: { message: 'Check out our new features.' } }
);

Clearing messages

Use window.voiceflow.chat.proactive.clear() to hide all proactive messages:
window.voiceflow.chat.proactive.clear();

Triggering messages based on user behavior

You can trigger proactive messages when users perform specific actions. For example, show a message when someone visits a certain page:
if (window.location.pathname === '/pricing') {
  window.voiceflow.chat.proactive.clear();
  window.voiceflow.chat.proactive.push({
    type: 'text',
    payload: { message: 'Have questions about our plans? I can help!' }
  });
}

Listening for events

The widget emits events you can listen for using the message event listener. Voiceflow events are stringified JSON objects with a type beginning with voiceflow:.
window.addEventListener('message', (event) => {
  if (typeof event.data === 'string' && event.data.startsWith('{"type":"voiceflow:')) {
    const data = JSON.parse(event.data);
    console.log(data.type);
  }
});
Event typeDescription
voiceflow:openThe widget was opened.
voiceflow:closeThe widget was closed.
voiceflow:interactThe assistant responded to an interaction.
voiceflow:save_sessionThe conversation state was cached.

Allowing dangerous HTML elements

Only enable dangerous HTML if you understand XSS risks and are using your own trusted code. Learn more about XSS vulnerabilities.
By default, certain HTML elements like <script> and <iframe> are blocked in messages for security reasons. You can enable them, but doing so introduces cross-site scripting (XSS) vulnerabilities.
window.voiceflow.chat.load({
  verify: { projectID: 'YOUR_PROJECT_ID' },
  url: 'https://general-runtime.voiceflow.com',
  versionID: 'production',
  allowDangerousHTML: true
});
The following elements are allowed by default:
a, audio, b, blockquote, br, code, dd, del, details, div, dl, dt, em, h1, h2, h3, h4, h5, h6, hr, i, img, input, ins, kbd, li, ol, p, picture, pre, q, rp, rt, ruby, s, samp, section, source, span, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, ul, var, video