> For the complete documentation index, see [llms.txt](https://docs.satisfilabs.com/resource-center/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.satisfilabs.com/resource-center/ai-agent-engine/features-and-integrations/features/web-injectors/agent-as-search-client-resource-guide/chat-as-search-technical-implementation-guide.md).

# Chat as Search — Technical Implementation Guide

This guide shows how to add a custom search bar (and optional quick-topic buttons) that opens your Satisfi AI agent with the visitor's question already asked. Each step includes an explanation and code.

<figure><img src="https://167344003-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsxN9AGLZMIc5C8dx3zU7%2Fuploads%2FI7JrERQCgAE1MfR6qOAq%2Fimage.png?alt=media&amp;token=2d5f54f8-fa53-4c72-aac2-091af46c6953" alt=""><figcaption><p>See live on <a href="https://nba.com/cavaliers">nba.com/cavaliers</a></p></figcaption></figure>

### Step 1: Add the Chat Widget Script

Add this `<script>` tag to your page. Replace `XXXX` with the client's `popupId` from the Satisfi console.

```html
<script id="satisfiScript"
  src="https://chat.satis.fi/popup/embedder?popupId=XXXX">
</script>
```

{% hint style="warning" %}
**One agent per page.** Load exactly one `popupId` on a page. If the site already loads a Satisfi agent site-wide, reuse it (skip this step) or remove it from this page at the source. Two embedders on one page share element IDs and `window.SatisfiApp`, and the chat will not open reliably. Do not rely on client-side scripts to remove the extra agent.
{% endhint %}

### Step 2: Create a Search Interface

Build an input field and button so visitors can type a question.

```html
<div class="chat-search">
  <input type="text" id="chatInput" placeholder="Ask us anything..." />
  <button id="chatBtn">Search</button>
</div>
```

### Step 3: Connect the Search to Chat

Use `SatisfiApp.Global.chatPopupOpen(query)` to open the chat with the visitor's question already asked. The chat API does nothing (and shows no error) until both `SatisfiApp.Global` and `#divSatisfiChat` exist, so the script below waits for both and holds any question asked before the chat finishes loading.

```html
<script>
(function () {
  function ready() {
    var g = window.SatisfiApp && window.SatisfiApp.Global;
    return (g && typeof g.chatPopupOpen === "function" &&
            document.getElementById("divSatisfiChat")) ? g : null;
  }

  var pending = null;
  function ask(text) {
    var q = (text || "").trim();
    var g = ready();
    if (!g) { pending = q; return; }       // hold until the chat loads
    if (q) g.chatPopupOpen(q);             // open with the question asked
    else g.chatPopupOpen();                // empty input: just open the chat
  }

  // Flush a held question once the chat is ready, then stop checking.
  var tries = 0, t = setInterval(function () {
    var g = ready();
    if (g && pending !== null) { var q = pending; pending = null; q ? g.chatPopupOpen(q) : g.chatPopupOpen(); }
    if (g || ++tries > 130) clearInterval(t);
  }, 150);

  var input = document.getElementById("chatInput");
  var btn = document.getElementById("chatBtn");
  btn.addEventListener("click", function () { ask(input.value); input.value = ""; });
  input.addEventListener("keydown", function (e) {
    if (e.key === "Enter") { ask(input.value); input.value = ""; }
  });
})();
</script>
```

### Step 4 (Optional): Add Quick-Topic Buttons

Buttons can send a question with one tap.

```html
<button onclick="SatisfiApp.Global.chatPopupOpen('What are today\'s hours?')">Hours</button>
<button onclick="SatisfiApp.Global.chatPopupOpen('Where do I park?')">Parking</button>
```

To send a button straight to a specific response, pass `response_name=<name>` as hidden text (`"1"`) and the question the visitor should see as the third argument. Replace `YOUR_RESPONSE_NAME` with the response's name from the Satisfi console.

```html
<button onclick="SatisfiApp.Global.chatPopupOpen('response_name=YOUR_RESPONSE_NAME', '1', 'Where do I park?')">Parking</button>
```

### Step 5 (Optional): Hide the Default Launcher

If the search bar should be the only entry point, hide the floating chat bubble **once** after the chat is ready (for example, inside the `ready()` check in Step 3), or hide it with CSS.

{% hint style="danger" %}
Never call `chatButtonHide()` on a timer or loop. Each call sends a request to Satisfi; calling it repeatedly can generate 100+ requests per page load.
{% endhint %}

### API Reference

| Call                                    | What it does                                                                      |
| --------------------------------------- | --------------------------------------------------------------------------------- |
| `chatPopupOpen()`                       | Opens the chat empty                                                              |
| `chatPopupOpen(text)`                   | Opens the chat and sends `text` as the visitor's question                         |
| `chatPopupOpen(text, "1")`              | Sends `text` without showing it as a visitor message (the text box stays visible) |
| `chatPopupOpen(text, "1", displayText)` | Sends `text` hidden and shows `displayText` in its place                          |
| `chatPopupClose()`                      | Closes the chat                                                                   |
| `chatButtonShow()` / `chatButtonHide()` | Shows or hides the floating launcher (call once)                                  |

Try every call live on the [Popup Injection Demo](https://d2.satisfi6.com/html/popup_injection_demo.html).

### Pre-Launch Checklist

* [ ] `popupId` is correct, and only one Satisfi embedder loads on the page (search DevTools > Elements for `popupId`)
* [ ] The search handler waits for `SatisfiApp.Global` and `#divSatisfiChat` before calling the API
* [ ] Questions open in the chat on the same page (no page reload or URL-parameter hand-off)
* [ ] DevTools > Network: `SavePopupInformation` fires once or twice per page load, not continuously
* [ ] Tap targets are at least 44px on mobile, and the search works with the keyboard (Tab + Enter)

### Related

* [Web Injectors](https://docs.satisfilabs.com/resource-center/ai-agent-engine/features-and-integrations/features/web-injectors): the full `chatPopupOpen()` reference, with buttons, links and images that open the chat. Chat as Search is one kind of injector.
* [Deep Links — Open Chat from Any Link (SFX Parameters)](https://docs.satisfilabs.com/resource-center/ai-agent-engine/features-and-integrations/features/web-injectors/deep-links-open-chat-from-any-link-sfx-parameters): open the chat from an email, QR code or SMS link, with no code on the page.
