Convot Convot
Back to Installing the Widget
Installing the Widget

Widget JavaScript API

Full reference for the Convot JS API - open/close, identify, send messages, push commands, config keys, getters, and event listeners.

Updated June 11, 2026

After the widget loads, a global Convot object is available on window. You can call its methods from any JavaScript on your page to control the widget, identify the current user, pre-fill messages, and react to widget events.

ℹ️

All API calls must run after the widget-loader script has executed. Either place your calls after the snippet in the HTML, or wrap them in a CONVOT_READY_TRIGGER callback (see Ready state below).

Opening and closing the widget

Convot.open();   // Opens the chat window
Convot.close();  // Closes the chat window

Both are synchronous fire-and-forget calls. They post a message into the widget iframe.

Equivalent push forms:

Convot.push(["do", "chat:open"]);
Convot.push(["do", "chat:close"]);
Convot.push(["do", "chat:toggle"]);  // Toggle open/closed
Convot.push(["do", "chat:show"]);    // Make the launcher visible
Convot.push(["do", "chat:hide"]);    // Hide the launcher entirely

Opening the booking flow

If you use Scheduling, you can open the widget straight to the timeslot picker from anywhere on your page, for example a “Book a demo” or “Talk to sales” button.

Convot.openScheduling();                       // Opens the widget on the booking flow
Convot.openScheduling({ meeting_type_id: 3 }); // Preselect a specific meeting type

Equivalent push form:

Convot.push(["do", "scheduling:open"]);
Convot.push(["do", "scheduling:open", { meeting_type_id: 3 }]);

A common pattern is a plain button:

<button onclick="Convot.openScheduling()">Book a demo</button>

This works even if the booking tab is hidden in your widget appearance settings, so you can keep the widget tidy and still trigger booking on demand. It requires at least one meeting type to be configured.

Identifying users

Call Convot.identify to associate the current visitor with a known user in your system. This links conversations to a contact record in your inbox.

Convot.identify({
  email: "[email protected]",
  external_id: "user_123",
  name: "Jane Doe",
  company: "Acme Inc",
  phone: "+1234567890",
  avatar_url: "https://example.com/jane.png",
  user_hash: "SERVER_GENERATED_HMAC",
  custom_data: {
    plan: "pro",
    shopify_store: "acme.myshopify.com"
  }
});

The user_hash field is optional unless Require verification is turned on in your app’s Setup page. When required, it must be an HMAC-SHA256 of the user’s external_id (or email if no external_id is sent), computed on your server with your identity secret. See App Key and Identity Secret for server-side signing examples.

Keeping users identified in your help center

Convot.identify only identifies the visitor on the page where you call it. When a logged-in user follows a link from your app to your help center (a different domain, such as help.yourcompany.com or your .convot.help address), the browser treats it as a new origin and they arrive as an anonymous visitor again.

To keep them identified, pass a signed identity token in the link as ?convot_identity=.... The widget on the help center reads it, identifies the same person, and removes the token from the URL.

Links opened from inside the widget (the “Search for help” button, status page) already carry this automatically when the visitor is verified - you do not need to do anything for those.

For links rendered by your own app, add the token. Easiest in the browser, where the widget mints it for you:

// In your app's page, where the widget is already identified:
const token = await Convot.identityToken(); // null if the visitor isn't identified
const url = "https://help.yourcompany.com/en/article/getting-started" +
  (token ? "?convot_identity=" + token : "");

Or generate it on your server (recommended when you build links server-side) by signing a short-lived JWT with your identity secret:

# Ruby
require "jwt"
payload = { external_id: "user_123", email: "[email protected]", exp: Time.now.to_i + 600 }
token   = JWT.encode(payload, ENV["CONVOT_IDENTITY_SECRET"], "HS256")
url     = "https://help.yourcompany.com/en/article/getting-started?convot_identity=#{token}"
// Node.js
const jwt = require("jsonwebtoken");
const token = jwt.sign(
  { external_id: "user_123", email: "[email protected]" },
  process.env.CONVOT_IDENTITY_SECRET,
  { algorithm: "HS256", expiresIn: "10m" }
);

The token is signed with the same identity secret used for user_hash, expires quickly, and is only ever attached to your own help-center links - never forwarded to external sites. See App Key and Identity Secret.

Sending and pre-filling messages

// Pre-fill the visitor's compose box without sending
Convot.setMessageText("I'm having trouble with my order #1234");

// Send a message on behalf of the visitor immediately
Convot.sendMessage("Please help with my billing question");

// Same via push
Convot.push(["set", "message:text", "Pre-filled text"]);
Convot.push(["do", "message:send", { content: "Sent immediately" }]);

sendMessage accepts a plain string or { content: "..." }. Anything else (an Event object, an Element, etc.) is rejected with a console error.

push() - the main command interface

Convot.push(args) is the primary dispatch method. args is always an array whose first element is a verb.

Convot.push([verb, ...args]);

Verb: do

Trigger an action inside the widget.

Convot.push(["do", "chat:open"]);
Convot.push(["do", "chat:close"]);
Convot.push(["do", "chat:toggle"]);
Convot.push(["do", "chat:show"]);
Convot.push(["do", "chat:hide"]);
Convot.push(["do", "message:send", { content: "Hello" }]);
Convot.push(["do", "message:read"]);                        // Mark messages as read
Convot.push(["do", "session:reset"]);                       // Clear the session
Convot.push(["do", "session:reset", true]);                 // Clear session and reload
Convot.push(["do", "helpdesk:search"]);                     // Open help center search
Convot.push(["do", "helpdesk:query", "billing"]);           // Pre-fill help search query
Convot.push(["do", "helpdesk:article:open", { locale: "en", slug: "my-article" }]);
Convot.push(["do", "scheduling:open"]);                     // Open the booking flow
Convot.push(["do", "scheduling:open", { meeting_type_id: 3 }]); // Preselect a meeting type
Convot.push(["do", "message:show", { type: "text", content: "Hello visitor!" }]);

Verb: set

Update visitor or session data.

Convot.push(["set", "user:email",    "[email protected]"]);
Convot.push(["set", "user:phone",    "+1234567890"]);
Convot.push(["set", "user:nickname", "Jane Doe"]);
Convot.push(["set", "user:avatar",   "https://example.com/avatar.png"]);
Convot.push(["set", "user:company",  "Acme Inc"]);
Convot.push(["set", "session:data",  { plan: "pro", store: "acme.myshopify.com" }]);
Convot.push(["set", "session:segments", ["paying", "enterprise"]]);
Convot.push(["set", "session:event", { name: "upgraded_plan", data: { plan: "pro" } }]);
Convot.push(["set", "message:text",  "Pre-filled text"]);

session:data is merged with any existing session data (not replaced). session:segments replaces the full segments array.

Verb: config

Apply configuration options that affect the widget’s outer chrome or behavior.

Convot.push(["config", "hide:on:mobile",  true]);    // Hide on screens < 768px
Convot.push(["config", "position:reverse", true]);   // Move widget to bottom-left
Convot.push(["config", "locale",          "fr"]);    // Force the widget language
Convot.push(["config", "sound:mute",      true]);    // Mute notification sounds
Convot.push(["config", "color:theme",     "#2563EB"]); // Override brand color
Convot.push(["config", "color:mode",      "dark"]);  // Force dark mode
Convot.push(["config", "container:index", 9999]);    // Set the iframe z-index

Config key reference:

💡
Key Values Effect
hide:on:mobile true / false Hides the widget on mobile devices (screen width below 768 px or mobile user agent).
position:reverse true / false Moves the widget to the bottom-left corner instead of bottom-right.
locale BCP 47 code, e.g. "fr", "es" Forces the widget UI language.
sound:mute true / false Mutes notification sounds for incoming messages.
color:theme hex string Overrides the brand color set in the dashboard.
color:mode "light" / "dark" Forces light or dark mode regardless of the visitor’s OS preference.
container:index integer Sets the z-index of the widget iframe.

Verb: on (subscribe to events)

Convot.push(["on", "session:loaded", function(payload) {
  console.log("Session ID:", payload.session_id);
}]);

Convot.push(["on", "chat:opened", function() {
  console.log("Widget opened");
}]);

Verb: off (unsubscribe)

var myHandler = function() { ... };
Convot.push(["on",  "chat:opened", myHandler]);
Convot.push(["off", "chat:opened", myHandler]);  // Remove specific handler
Convot.push(["off", "chat:opened"]);             // Remove all handlers for this event

get() - reading state synchronously

Convot.get(key) returns cached state that the loader maintains from widget events. All reads are synchronous.

Convot.get("chat:unread:count");         // Number of unread messages
Convot.get("message:text");              // Current text in the compose box
Convot.get("session:identifier");        // Session ID string
Convot.get("session:data");              // Full session data object
Convot.get("session:data", "plan");      // Single session data value by key
Convot.get("user:email");
Convot.get("user:phone");
Convot.get("user:nickname");
Convot.get("user:avatar");
Convot.get("user:company");

is() - boolean state checks

Convot.is(key) returns a boolean for common state questions.

Convot.is("chat:opened");       // true if widget is open
Convot.is("chat:closed");       // true if widget is closed
Convot.is("chat:visible");      // true if launcher is visible
Convot.is("chat:hidden");       // true if launcher is hidden
Convot.is("session:ongoing");   // true if a session has loaded and has an ID
Convot.is("website:available"); // true if at least one operator is online

Ready state

Convot.ready() returns true once the widget iframe has finished loading. For a callback pattern, set window.CONVOT_READY_TRIGGER before the loader runs:

<script>
  window.CONVOT_READY_TRIGGER = function() {
    // Safe to call any Convot API here
    Convot.identify({ email: currentUser.email });
  };
  window.Convot = { app_id: "app_YOUR_KEY_HERE" };
</script>
<script async src="https://app.convot.com/widget-loader.js"></script>

Event reference

Subscribe to these events with Convot.push(["on", name, fn]):

💡
Event name When it fires Payload
session:loaded The widget session is ready. { session_id }
chat:opened Visitor opens the chat window. none
chat:closed Visitor closes the chat window. none
chat:visibility Launcher is shown or hidden. true / false
message:sent Visitor sends a message. { unread_count }
message:received Agent sends a message. { unread_count }
user:email:changed Visitor’s email was set or updated. email string
user:phone:changed Visitor’s phone was set or updated. phone string
user:nickname:changed Visitor’s name was set or updated. name string
user:avatar:changed Visitor’s avatar URL was set or updated. URL string
website:availability:changed Operator online/offline status changed. true / false
preview:shown Notification preview card appeared. none
preview:hidden Notification preview card dismissed. none

Pre-loader queue

If you call Convot.push before the loader script has run, the calls are queued automatically and replayed once the loader initializes. This means you can safely push config and set calls anywhere in your page above the snippet.

<script>
  window.Convot = {
    app_id: "app_YOUR_KEY_HERE",
    _q: [
      ["config", "position:reverse", true],
      ["config", "locale", "es"]
    ]
  };
</script>
<script async src="https://app.convot.com/widget-loader.js"></script>

Next steps

Was this article helpful?