# Client-side actions in the visitor's browser

> Run an action in the visitor's browser: register a JavaScript handler with IntoChatActions, or call an endpoint on your site that uses the visitor's session.

A client-side action runs on the page where your agent is embedded, not on intoCHAT's servers. Use it to reach what only the visitor's browser can reach: an endpoint on your site that relies on the visitor's login session, or data and functions on the page itself.

## When to use which

| You want to call | Use |
| --- | --- |
| A public API, or one that needs your secret key | A [server-side API action](/en/docs/api-actions) |
| An endpoint on your own domain that uses the visitor's cookies | A client-side action, no extra code needed |
| Something on the page, such as cart contents in JavaScript or a dialog to open | A client-side action with a registered handler |
| Nothing: you only want the visitor to open one of your pages | A [custom button](/en/docs/custom-buttons) |

## Set it up

1. On the **Actions** tab, create the action as described in [Custom API actions](/en/docs/api-actions): URL, data inputs and **When to use**.
2. In step **3. When the AI should use it**, select **Client-side action**.
3. Save the action.

> The request is assembled in the visitor's browser, so anything in it is visible to them. The credential from the **Authentication** tab is deliberately not sent. If the endpoint needs your secret key, make it a server-side action.

## How a call runs

When the agent calls a client-side action, the chat widget hands the call to the embed script on your page:

1. If your page registered a handler under the action's name, the handler runs and its return value goes to the agent.
2. If not, your page fetches the action's URL from your own domain, with the visitor's cookies included.

Each call has 20 seconds. After that it is reported to the agent as failed. The action still needs a valid public URL even if you only use a handler; with a handler registered, that URL is not called.

## Register a handler

The handler name is the action name with every character other than letters, digits, `_` and `-` replaced by `_`, so "Get cart" becomes `Get_cart`. The editor shows the exact name in its code sample.

`window.IntoChatActions` is available as soon as the snippet's script has run, before the chat widget itself has loaded. Handlers are looked up when the agent calls the action, so registering before or after the widget is ready works the same. Add a script anywhere after the snippet:

```html
<script src="https://www.intochat.ai/api/embed.js" data-chatbot-id="YOUR_AGENT_ID"></script>
<script>
  window.IntoChatActions.register("Get_cart", async function (args) {
    // args: the data inputs the agent filled in.
    // Return anything JSON-serializable. The agent sees it.
    return { items: window.myStore.cart.items };
  });
</script>
```

Code that may run before the snippet can push `[name, handler]` pairs to `window.IntoChatActionsQueue` instead; the embed script registers them when it loads. Most pages don't need this. With several agents on one page, all of them share the same handlers.

The handler receives the data inputs the agent filled in as `args`. If it throws an error, the message is passed to the agent as a failed call. `IntoChatActions.unregister(name)` removes a handler, and `IntoChatActions.registered()` lists the registered names.

## Test it

**Send test request** in the editor runs from intoCHAT's servers. It checks that the URL answers and shows the response shape, but it cannot see your visitors' sessions or any handler on your page. In the **Playground** there is no page of yours around the chat, so the URL is fetched by the widget itself, without your site's cookies or handlers. Test handlers and session-based endpoints on a page of your site where the widget is installed.

> Client-side actions need the chat bubble that the embed script adds to your page. In an inline iframe embed there is no embed script on the page to answer, so a call fails after 20 seconds.
