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

# Agent Actions

> Custom browser events the Ringg agent can dispatch on the host page during a conversation.

<Note>
  **Looking for widget state events** (open/close, conversation start/end, feedback)? See [Widget Lifecycle Events](/get-started/guides/embedding-widget-events). This page covers events your agent fires on the page during a call.
</Note>

Your Ringg agent can dispatch custom browser events on your page during a conversation. Focus an input, open a modal, scroll to a section, anything your UI can do. You configure each action in the dashboard, then listen for it by **Event ID** on `window`.

<Info>
  **Where to set this up.** In the Ringg dashboard, open your agent and go to **Embed → Interactive Components → Execute DOM Action** (`execute_dom_action`). Each entry under **Actions** is one event the agent can dispatch.
</Info>

## How it works

Each action you add in the dashboard has three fields:

| Field                            | What it is                                                               |
| -------------------------------- | ------------------------------------------------------------------------ |
| **Event ID**                     | The event name your page listens for on `window` via `addEventListener`. |
| **Description**                  | Helps the agent decide when to fire the action.                          |
| **Default Payload** *(optional)* | A JSON object delivered as `event.detail` when the action fires.         |

At runtime:

1. The agent decides during a call when to fire one of its configured actions.
2. The widget dispatches a `CustomEvent` on `window` using the action's **Event ID** as the event name.
3. Your page's listener for that Event ID runs.

Actions only fire during an active conversation. If the user is not on a call, no events are dispatched.

## Listening for an action

Use the Event ID exactly as configured in the dashboard:

```javascript theme={null}
window.addEventListener("focus_search", (event) => {
  document.querySelector("#search-input").focus();
});
```

Whenever the agent fires the `focus_search` action during a call, your handler runs.

## Reading the payload

The Default Payload you configured arrives as `event.detail`. Destructure the fields you need:

```javascript theme={null}
window.addEventListener("show_promo_modal", (event) => {
  const { discount_pct, product_id } = event.detail;
  openPromoModal({ discount: discount_pct, productId: product_id });
});
```

If the action does not have a Default Payload configured, `event.detail` is `null`.

## React example

```javascript theme={null}
import { useEffect, useRef } from "react";

function SearchBar() {
  const inputRef = useRef(null);

  useEffect(() => {
    const listener = () => inputRef.current?.focus();
    window.addEventListener("focus_search", listener);
    return () => window.removeEventListener("focus_search", listener);
  }, []);

  return <input ref={inputRef} placeholder="Search…" />;
}
```

## More examples

```javascript theme={null}
// Open a promo modal when the agent suggests a discount
window.addEventListener("show_promo_modal", (event) => {
  showPromoModal({ discount: event.detail.discount_pct });
});

// Scroll to the pricing section
window.addEventListener("scroll_to_pricing", () => {
  document.querySelector("#pricing")?.scrollIntoView({ behavior: "smooth" });
});

// Pre-fill a form field
window.addEventListener("prefill_email", (event) => {
  document.querySelector("input[name=email]").value = event.detail.email;
});
```

## Show actions in the chat thread (optional)

Useful while you are wiring things up. Enable it on the widget config to see a small pill in the chat thread whenever an action fires.

```javascript theme={null}
loadAgent({
  agentId: "your-agent-id",
  // ...
  eventLogs: {
    enabled: true,   // off by default
    showIds: false,  // set true to also show the Event ID
  },
});
```

This is purely a visual aid. Actions fire the same way whether you enable it or not.

## Naming and conventions

<Tip>
  Pick distinctive Event IDs (for example `ringg_focus_search`, `shop_show_promo`) so your action names do not collide with other custom events on the page.
</Tip>

* **Multiple listeners work.** You can attach more than one handler to the same Event ID from different components, and all of them fire.
* **One listener, many actions.** Inside a single handler, use `event.type` to route on the Event ID if you want one place to handle several actions.
* **Listeners only run during a call.** Nothing fires when the user is idle.

## QA notes

<Check>Add an Event ID in the dashboard, attach a matching `addEventListener` on your page, and confirm it fires during a test call.</Check>
<Check>If you configured a Default Payload, verify `event.detail` contains those fields with the expected values.</Check>
<Check>Enable `eventLogs.enabled` during integration to visually confirm each action fires.</Check>
<Check>In single-page apps, remove listeners on unmount so navigation does not duplicate handlers.</Check>
