> ## Documentation Index
> Fetch the complete documentation index at: https://sitegpt.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Widget SDK

> Reference for the window.$sitegpt commands that control the SiteGPT chat widget on your page.

The widget SDK is the `window.$sitegpt` command queue. The install snippet creates it. Use it to control the chat widget from JavaScript on your own page.

The SDK is part of the widget. There is nothing extra to install. To add the widget to your site, see [Add SiteGPT to your website](/docs/guides/install/add-to-website).

<Note>
  This page is about the chat widget in the browser. To manage chatbots, content, or conversations from a server, use [API v2](/docs/api-reference/v2/getting-started) or the [TypeScript SDK](/docs/developers/sdk-typescript).
</Note>

The dashboard also has an **SDK (Advanced)** page for each chatbot, with copy-ready examples.

## How commands work

Every command is an array that you push onto the queue:

```javascript theme={null}
window.$sitegpt.push(['open']);
```

* The first item is the command name. The other items are its arguments.
* Push commands after the install snippet. The snippet sets `window.$sitegpt` to a new, empty queue, so commands pushed before it are lost.
* After the widget script runs, `open`, `close`, `toggle`, `on`, `off`, `message:send`, and `message:text` run at once. Other commands wait until the chat window first loads. By default, that happens when the visitor first opens the chat.
* `window.$sitegpt` is shared by every SiteGPT chatbot on the page. Each chatbot also has its own queue, `window.$sitegpt_widget['YOUR_CHATBOT_ID']`, which takes the same commands.

## Command list

| Command                                     | What it does                                                                                                            |
| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `['open']`                                  | Opens the chat window.                                                                                                  |
| `['open', { reset: true }]`                 | Opens the chat window with a new conversation.                                                                          |
| `['open', { focus: true }]`                 | Opens the chat window and puts the cursor in the message box.                                                           |
| `['close']`                                 | Closes the chat window.                                                                                                 |
| `['toggle']`                                | Opens the chat window if it is closed. Closes it if it is open.                                                         |
| `['do', 'message:send', text]`              | Sends `text` as a visitor message. Opens the chat window if needed.                                                     |
| `['set', 'message:text', text]`             | Puts `text` in the message box without sending it. Opens the chat window if needed.                                     |
| `['do', 'conversation:reset']`              | Starts a new conversation.                                                                                              |
| `['do', 'widget:reload']`                   | Removes the widget from the page and loads it again. Use the per-chatbot queue for this command.                        |
| `['set', 'context', [before, after]]`       | Adds page or visitor context to the chatbot's answers. See [Add page or visitor context](#add-page-or-visitor-context). |
| `['set', 'user:email', [email, signature]]` | Signs in a known visitor. See [Identity verification](#identity-verification).                                          |
| `['set', 'css', cssText]`                   | Adds your CSS to the chat window.                                                                                       |
| `['on', eventName, callback]`               | Runs `callback` when a widget event happens.                                                                            |
| `['off', eventName, callback]`              | Stops running a callback that you added with `on`.                                                                      |

The SDK has no other commands. There is no `init`, `identify`, or `boot` command, and no `$sitegpt.open()` function.

## Open, close, and toggle

```javascript theme={null}
// Open the chat from your own button
document.getElementById('chat-button').addEventListener('click', function () {
  window.$sitegpt.push(['open']);
});

// Close it
window.$sitegpt.push(['close']);

// Toggle it
window.$sitegpt.push(['toggle']);
```

You can combine the `open` options:

```javascript theme={null}
window.$sitegpt.push(['open', { reset: true, focus: true }]);
```

* `reset: true` starts a new conversation as the window opens. Use it instead of `['open']` followed by `['do', 'conversation:reset']`. The visitor does not see the old conversation first.
* `focus: true` puts the keyboard cursor in the message box.

When the chat closes, by the visitor or by `['close']`, the widget remembers this in the browser. Auto-open does not run again until the chat is opened again. `['open']` still works.

On pages listed under **Settings** > **General** > **Excluded Pages**, `['open']` does not open the chat. The browser console shows a message that the page is excluded. This does not apply when you load the widget with `hideBubble=true` or `hideButton=true`. See [Control where the chat appears](/docs/guides/install/control-where-it-appears).

## Send or prefill a message

```javascript theme={null}
// Send a message for the visitor
window.$sitegpt.push(['do', 'message:send', 'What are your opening hours?']);

// Put text in the message box, and let the visitor edit it before sending
window.$sitegpt.push(['set', 'message:text', 'I have a question about my order']);
```

Both commands open the chat window if it is closed. You do not need to push `['open']` first.

## Start a new conversation

```javascript theme={null}
window.$sitegpt.push(['do', 'conversation:reset']);
```

To open the chat and start a new conversation in one step, use `['open', { reset: true }]`.

## Reload the widget

```javascript theme={null}
window.$sitegpt_widget['YOUR_CHATBOT_ID'].push(['do', 'widget:reload']);
```

This removes the chat window and launcher button that the widget created and loads them again. Your own inline containers stay on the page.

## Add page or visitor context

Use `set context` to give the chatbot facts about the current page or the signed-in visitor. For example, the product the visitor is looking at, or the visitor's plan in your app.

```javascript theme={null}
window.$sitegpt.push(['set', 'context', [
  'The visitor is on the product page for the Trail Runner 2 shoe.',
  'The visitor has a Pro account in our app.'
]]);
```

* The value is an array of two strings. SiteGPT adds the first string before your chatbot [instructions](/docs/guides/answers/write-instructions). It adds the second string after the content it found for the question. Use an empty string (`''`) for the part you do not need.
* The context applies to the visitor's next messages on this page load. SiteGPT does not save it. Push it again on each page load.
* In a single-page app, push new context when the visitor moves to another page. The new values replace the old ones.
* Do not put secrets in the context. It runs in the visitor's browser.

SiteGPT can also add the page URL, title, and meta description automatically. Turn on **Enable Page Context Awareness** in **Settings** > **General**. See [Settings reference](/docs/reference/settings).

## Identity verification

Identity verification signs in a visitor that your own site already knows. The widget then treats the visitor as that email address, without an email code. You need:

* The Growth plan or above. See [Plans and limits](/docs/reference/plans-and-limits).
* Your legacy API key. It is on the **Billing** page, in the line "Your API Key is ...". This is not an `sgpt_` token from the **Agents** page. See [Authentication](/docs/developers/authentication#legacy-api-key).
* A backend where you can keep the key secret.

The signature is the HMAC-SHA256 of the visitor's email address, keyed with your legacy API key, as a lowercase hex string.

<Warning>
  Make the signature only on your server. Never put your API key in browser code. Anyone with the key can sign in as any email address on your chatbots, and can call the legacy API.
</Warning>

Server example (Node.js):

```javascript theme={null}
const crypto = require('crypto');

// Keep the key in an environment variable. Never send it to the browser.
const apiKey = process.env.SITEGPT_API_KEY; // YOUR_API_KEY

function signEmail(email) {
  return crypto.createHmac('sha256', apiKey).update(email).digest('hex');
}

// Example endpoint that your page calls for the signed-in user
app.get('/api/chatbot-identity', (req, res) => {
  const email = req.user.email;
  res.json({ email, signature: signEmail(email) });
});
```

Browser example:

```javascript theme={null}
fetch('/api/chatbot-identity')
  .then((res) => res.json())
  .then((data) => {
    window.$sitegpt.push(['set', 'user:email', [data.email, data.signature]]);
  });
```

* Sign the exact email string that you send. A different spelling or letter case gives a different signature.
* If the signature does not match, the visitor stays anonymous. The widget shows no error.
* For the hosted chat link or the iframe embed, add the same values as the `user_email` and `user_email_signature` URL parameters.
* The legacy API key does not change on its own. If your key ever changes, old signatures stop working. Make new signatures with the new key.

## Add CSS

```javascript theme={null}
window.$sitegpt.push(['set', 'css', ':root { --chat-color: #155DEE; }']);
```

The CSS goes inside the chat window. You can target any element, but the widget's markup can change without notice. These CSS variables are the most stable way to change the look:

| Variable            | Controls                                        | Appearance field that sets it               |
| ------------------- | ----------------------------------------------- | ------------------------------------------- |
| `--chat-color`      | The primary color                               | **Primary Color**                           |
| `--chat-text-color` | Text on top of the primary color                | **Text Color**                              |
| `--chat-link-color` | Links, sources, and suggestion text in messages | **Link Color** (the primary color if empty) |
| `--chat-font-size`  | The base font size                              | **Font Size (in px)**                       |

For most visual changes, use the **Appearance** page instead. See [Change the widget appearance](/docs/guides/widget/appearance).

## Events

Use `on` and `off` to run your own code when something happens in the widget:

```javascript theme={null}
function handleLead(data) {
  console.log('Lead submitted in conversation', data.threadId);
}

window.$sitegpt.push(['on', 'lead_submitted', handleLead]);

// Later, to stop listening
window.$sitegpt.push(['off', 'lead_submitted', handleLead]);
```

To remove a callback, pass the same function that you added. The widget sends seven events: `chat_opened`, `chat_closed`, `conversation_started`, `message_sent`, `lead_submitted`, `human_handover`, and `booking_link_clicked`. [Tracking events](/docs/developers/tracking-events) lists the payloads and shows how to send them to Google Tag Manager or GA4.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Commands do nothing">
    * Make sure the install snippet is on the page. It creates `window.$sitegpt`.
    * Check the command spelling. Unknown commands show a `SiteGPT: Unknown command` warning in the browser console.
    * Check the browser console for a message that the page is listed under **Excluded Pages**, or that the domain is not in **Allowed Domains**.
  </Accordion>

  <Accordion title="The chat does not appear at all">
    * The widget does not load when the chatbot is disabled, or when the account owner's subscription or trial has ended.
    * If you set **Allowed Domains** in **Settings** > **General**, the current domain must be in the list.
    * See [Add SiteGPT to your website](/docs/guides/install/add-to-website) for install checks.
  </Accordion>

  <Accordion title="The visitor is not signed in after set user:email">
    * Make the signature with the legacy API key from the **Billing** page, not an `sgpt_` token.
    * Sign exactly the same email string that you push.
    * Check that the signature is a hex string, not Base64.
  </Accordion>

  <Accordion title="My CSS does not apply">
    * Check that the CSS is valid.
    * Use a more specific selector, or `!important`, to override the widget's own styles.
  </Accordion>
</AccordionGroup>
