Skip to main content
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

Example CTAs array

{
  "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

label
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.
url
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.
type
string
Controls what happens when the visitor clicks the CTA.
ValueBehavior
"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.
chatMessage
string
The message sent on the visitor’s behalf when type is "chat". If omitted, the button label is sent as the message.

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):

Booking

Calendly · Cal.com · HubSpot Meetings

Forms

Typeform · Tally · JotForm · Paperform · Fillout · Airtable Forms · Google Forms

Documents

Notion · Google Docs

Video

Loom · YouTube · Wistia · Vimeo
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)
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.