> ## 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.

# Tracking events

> Track chatbot activity in Google Tag Manager, GA4, or any analytics tool

The SiteGPT widget emits JavaScript events on your website whenever a visitor
interacts with the chatbot. Use them to track chatbot engagement and conversions
in **Google Tag Manager**, **Google Analytics 4 (GA4)**, or any custom analytics
tool, with no extra configuration on the SiteGPT side.

The same events fire whether you install the widget with the script snippet or
the [WordPress plugin](/setup/integrating-with-your-website) (the plugin loads
the same widget).

<Note>
  **Where does this run?** Your analytics setup never goes inside the SiteGPT
  widget. The install snippet (`https://sitegpt.ai/widget/YOUR_CHATBOT_ID.js`) runs
  on **your own page**, alongside the GTM or GA4 you already have there. The chat
  widget posts each event from its iframe to your page, and that snippet forwards
  it to your `dataLayer`, a `window` event, and any `$sitegpt` callback. So you
  wire everything up on your own site, using the tracking that already lives there.
</Note>

## Events

Every event is delivered in three ways at once (see [How to listen](#how-to-listen)):
a `dataLayer` push for GTM, a `window` `CustomEvent`, and a `$sitegpt` callback.

| Event                  | Fires when                                                                                                                    | Payload                                                                          |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `chat_opened`          | The chat window is opened                                                                                                     | `chatbotId`                                                                      |
| `chat_closed`          | The chat window is closed                                                                                                     | `chatbotId`                                                                      |
| `conversation_started` | The visitor sends their first message in a new conversation                                                                   | `chatbotId`, `threadId`                                                          |
| `message_sent`         | The visitor sends any message                                                                                                 | `chatbotId`, `threadId`                                                          |
| `lead_submitted`       | The visitor submits the lead / contact form                                                                                   | `chatbotId`, `threadId`                                                          |
| `human_handover`       | The conversation is handed over to a human agent                                                                              | `chatbotId`, `threadId`                                                          |
| `booking_link_clicked` | The visitor clicks a scheduling link (Calendly, Cal.com, HubSpot Meetings, Google/Microsoft Bookings, and similar) in a reply | `chatbotId`, `threadId`, `url` (provider host only, e.g. `https://calendly.com`) |

<Note>
  Payloads are intentionally free of personal data (no name, email, phone, or
  message text), so they are safe to forward to GA4, which prohibits sending
  personally identifiable information. The lead details themselves stay in your
  SiteGPT dashboard and any connected CRM.
</Note>

## How to listen

Pick the method that matches your stack. You can use more than one.

<Tabs>
  <Tab title="Google Tag Manager">
    Each event is pushed to `window.dataLayer` with the event name
    `sitegpt_<event>` (for example `sitegpt_conversation_started`). The payload
    fields are added to the same object.

    Example pushed object:

    ```javascript theme={null}
    {
      event: 'sitegpt_lead_submitted',
      chatbotId: 'YOUR_CHATBOT_ID',
      threadId: 'abc123'
    }
    ```

    To use it in GTM:

    <Steps>
      <Step title="Create a Custom Event trigger">
        In GTM, add a **Trigger → Custom Event** and set the **Event name** to
        the event you want, e.g. `sitegpt_lead_submitted`. Use
        `sitegpt_.*` with **Use regex matching** to capture every SiteGPT event
        in one trigger.
      </Step>

      <Step title="Read the payload (optional)">
        Create **Data Layer Variables** named `chatbotId`, `threadId`, or `url`
        to pass those values into your tags.
      </Step>

      <Step title="Fire your tag">
        Attach a **GA4 Event** tag (or any tag) to the trigger to record the
        conversion.
      </Step>
    </Steps>

    <Note>
      The widget pushes to `dataLayer` directly, so it works even if GTM loads
      after the widget. You do not need to pre-declare `window.dataLayer`.
    </Note>
  </Tab>

  <Tab title="Google Analytics 4 (gtag)">
    If you use GA4 directly (the `gtag.js` snippet, not GTM), listen for the
    matching `window` event named `sitegpt:<event>` and forward it to GA4. The
    payload is on `event.detail`.

    Add this once, anywhere after your `gtag` snippet:

    ```html theme={null}
    <script>
      [
        'chat_opened',
        'chat_closed',
        'conversation_started',
        'message_sent',
        'lead_submitted',
        'human_handover',
        'booking_link_clicked',
      ].forEach(function (name) {
        window.addEventListener('sitegpt:' + name, function (e) {
          gtag('event', 'sitegpt_' + name, e.detail);
        });
      });
    </script>
    ```

    The events then appear in GA4 under **Reports → Engagement → Events** as
    `sitegpt_conversation_started`, `sitegpt_lead_submitted`, and so on. Mark the
    ones you care about as **Key events** (conversions) in GA4 admin.
  </Tab>

  <Tab title="Custom JavaScript">
    Register a callback through the `$sitegpt` SDK with `['on', '<event>', fn]`.
    Your function receives the payload object. You can register callbacks before
    the widget finishes loading; they are queued and attached automatically.

    ```javascript theme={null}
    window.$sitegpt = window.$sitegpt || [];

    window.$sitegpt.push(['on', 'lead_submitted', function (data) {
      console.log('Lead captured in thread', data.threadId);
      // e.g. fire your own analytics, Facebook Pixel, etc.
    }]);

    window.$sitegpt.push(['on', 'booking_link_clicked', function (data) {
      console.log('Booking link clicked:', data.url);
    }]);
    ```

    To stop listening, keep a reference to the function and pass it to `off`:

    ```javascript theme={null}
    function onOpen(data) { /* ... */ }
    window.$sitegpt.push(['on', 'chat_opened', onOpen]);
    // later
    window.$sitegpt.push(['off', 'chat_opened', onOpen]);
    ```

    You can also listen with the native DOM API instead of the SDK:

    ```javascript theme={null}
    window.addEventListener('sitegpt:chat_opened', function (e) {
      console.log(e.detail); // { chatbotId: '...' }
    });
    ```
  </Tab>
</Tabs>

## Multiple widgets on one page

If you run more than one SiteGPT chatbot on the same page, every event payload
includes the `chatbotId` it came from. In GTM/GA4, filter on the `chatbotId`
data layer variable; in a callback or DOM listener, check `data.chatbotId`.

## Reference

* **dataLayer event name:** `sitegpt_<event>` (e.g. `sitegpt_chat_opened`)
* **DOM event name:** `sitegpt:<event>` (e.g. `sitegpt:chat_opened`), payload on `event.detail`
* **SDK callback:** `window.$sitegpt.push(['on', '<event>', fn])`, payload passed to `fn`

<CardGroup cols={2}>
  <Card title="JavaScript SDK" icon="js" href="/developers/sdk">
    Control the widget programmatically
  </Card>

  <Card title="Webhooks" icon="webhook" href="/developers/webhooks">
    Receive server-side events (leads, messages, escalations)
  </Card>
</CardGroup>
