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

# Add Call-to-Action Buttons to the ClientX Widget

> Configure CTA buttons inside the ClientX widget to book demos, open booking pages, send chat messages, or embed third-party forms in an iframe.

CTAs appear as a prominent button bar pinned above the chat input inside the widget. They drive visitors toward your most important conversion actions — booking a demo, signing up for a trial, or connecting with your sales team. The first CTA in your array is always shown as the primary button; clicking it triggers the action immediately without leaving the widget.

## CTA types

<Tabs>
  <Tab title="url — open a link">
    Opens the target URL in a new browser tab. Use this for destinations that cannot be embedded — your main website, LinkedIn, payment pages, or any URL that sets `X-Frame-Options: DENY`.

    ```json theme={null}
    {
      "label": "Visit our pricing page",
      "url": "https://example.com/pricing",
      "type": "url"
    }
    ```
  </Tab>

  <Tab title="embed — inline iframe">
    Loads the URL inside an iframe within the widget panel. The visitor never leaves your site — ideal for booking pages (Calendly, Cal.com), lead-capture forms (Typeform, Tally, HubSpot meetings), and video players. The iframe fills the widget panel with a lightweight header showing the domain and a close button.

    ```json theme={null}
    {
      "label": "Book a Demo",
      "url": "https://cal.com/yourcompany/demo",
      "type": "embed"
    }
    ```
  </Tab>

  <Tab title="chat — send a message">
    Opens the widget (if not already open) and sends a pre-written message on the visitor's behalf. Use this for soft-entry flows like "Talk to Sales" or "I have a question about Enterprise" — it starts a conversation with a specific intent without the visitor typing anything.

    ```json theme={null}
    {
      "label": "Talk to Sales",
      "type": "chat",
      "chatMessage": "I'd like to speak with someone on the sales team."
    }
    ```

    The `url` field is unused for `chat` type — set it to an empty string or omit it. If you do include a `url` value prefixed with `chat:`, the text after the colon is used as the message (URL-decoded).
  </Tab>
</Tabs>

## Example CTAs array

```json theme={null}
{
  "ctas": [
    {
      "label": "Book a Demo",
      "url": "https://cal.com/yourcompany/demo",
      "type": "embed"
    },
    {
      "label": "Talk to Sales",
      "type": "chat",
      "chatMessage": "I'd like to speak with someone on the sales team."
    },
    {
      "label": "Start Free Trial",
      "url": "https://app.example.com/signup",
      "type": "url"
    }
  ]
}
```

The first item (`"Book a Demo"`) becomes the pinned primary CTA button shown in the widget at all times. The AI can also surface any CTA from this list at the end of a relevant conversation turn.

## CTA field reference

<ParamField body="label" type="string" required>
  Button text shown to the visitor (e.g. `"Book a Demo"`, `"Talk to Sales"`). Also used as the fallback `chatMessage` when `type` is `"chat"` and no explicit `chatMessage` is provided.
</ParamField>

<ParamField body="url" type="string">
  The destination URL for `url` and `embed` types. For `embed`, this is the URL loaded in the iframe. For `chat`, you may omit this field entirely or use the `chat:Your message here` format. Pass `"demo"` as a shorthand — the widget automatically resolves it to your workspace's `demoUrl` setting.
</ParamField>

<ParamField body="type" type="string">
  Controls what happens when the visitor clicks the CTA.

  | Value     | Behavior                                   |
  | --------- | ------------------------------------------ |
  | `"embed"` | Loads `url` in an iframe inside the widget |
  | `"url"`   | Opens `url` in a new tab                   |
  | `"chat"`  | Sends `chatMessage` inside the widget chat |

  If `type` is omitted, the widget auto-detects: same-origin and relative URLs default to `embed`; external URLs check the embeddable-services list (see below) and fall back to `url`.
</ParamField>

<ParamField body="chatMessage" type="string">
  The message sent on the visitor's behalf when `type` is `"chat"`. If omitted, the button `label` is sent as the message.
</ParamField>

***

## Auto-embed behavior

When `type` is not specified, the widget automatically decides whether to embed or redirect based on the target domain.

**Services that embed automatically (iframe):**

<CardGroup cols={2}>
  <Card title="Booking" icon="calendar-check">
    Calendly · Cal.com · HubSpot Meetings
  </Card>

  <Card title="Forms" icon="file-lines">
    Typeform · Tally · JotForm · Paperform · Fillout · Airtable Forms · Google Forms
  </Card>

  <Card title="Documents" icon="file">
    Notion · Google Docs
  </Card>

  <Card title="Video" icon="play">
    Loom · YouTube · Wistia · Vimeo
  </Card>
</CardGroup>

**Services that always redirect (new tab):**

These services set `X-Frame-Options` headers that prevent embedding, so the widget opens them in a new tab regardless of your `type` setting:

* Payment pages (Dodo Payments)
* LinkedIn, Twitter / X, Facebook, Instagram
* GitHub
* `lemcal.com`
* Same-origin URLs (embedding your own site inside the widget loads the full site in a tiny iframe — never useful)

<Tip>
  Use `"type": "embed"` for all booking and form pages. It keeps visitors in context — they complete the booking without leaving your site — which significantly improves conversion compared to opening a new tab.
</Tip>
