> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/calcom/cal.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JavaScript Snippet Embed

> Embed Cal.com using vanilla JavaScript on any website

The vanilla JavaScript embed snippet is the lightest way to add Cal.com booking functionality to any website. It works with any tech stack and requires no build tools or dependencies.

## Installation

Add the embed snippet to your HTML page. This is all you need to get started:

```html theme={null}
<script>
  (function (C, A, L) {
    let p = function (a, ar) { a.q.push(ar); };
    let d = C.document;
    C.Cal = C.Cal || function () {
      let cal = C.Cal;
      let ar = arguments;
      if (!cal.loaded) {
        cal.ns = {};
        cal.q = cal.q || [];
        d.head.appendChild(d.createElement("script")).src = A;
        cal.loaded = true;
      }
      if (ar[0] === L) {
        const api = function () { p(api, arguments); };
        const namespace = ar[1];
        api.q = api.q || [];
        if (typeof namespace === "string") {
          cal.ns[namespace] = cal.ns[namespace] || api;
          p(cal.ns[namespace], ar);
          p(cal, ["initNamespace", namespace]);
        } else p(cal, ar);
        return;
      }
      p(cal, ar);
    };
  })(window, "https://app.cal.com/embed/embed.js", "init");
</script>
```

<Note>
  Replace `https://app.cal.com` with your Cal.com instance URL if you're self-hosting.
</Note>

## Quick Start Examples

### Inline Embed

Embed the calendar directly in your page:

```html theme={null}
<!-- 1. Add the embed snippet (shown above) -->

<!-- 2. Create a container -->
<div id="my-cal-inline" style="width:100%;height:100%;overflow:scroll"></div>

<!-- 3. Initialize the embed -->
<script>
  Cal("init");
  Cal("inline", {
    elementOrSelector: "#my-cal-inline",
    calLink: "organization/event-type"
  });
</script>
```

### Modal Embed (Button Click)

Open the calendar in a modal when a button is clicked:

```html theme={null}
<!-- 1. Add the embed snippet -->

<!-- 2. Add a button with data attributes -->
<button 
  data-cal-link="organization/event-type"
  data-cal-config='{"layout":"month_view","theme":"dark"}'
>
  Book a meeting
</button>

<!-- 3. Initialize -->
<script>
  Cal("init");
</script>
```

### Floating Button

Add a persistent floating button to your page:

```html theme={null}
<!-- 1. Add the embed snippet -->

<!-- 2. Initialize with floating button -->
<script>
  Cal("init");
  Cal("floatingButton", {
    calLink: "organization/event-type",
    buttonText: "Book a meeting",
    buttonPosition: "bottom-right",
    config: {
      theme: "dark"
    }
  });
</script>
```

## API Reference

### Initialization

Always initialize Cal before using it:

```javascript theme={null}
Cal("init", {
  origin: "https://cal.com",  // Optional: Cal.com instance URL
  debug: false,                // Optional: Enable debug logging
  uiDebug: false              // Optional: Enable UI debug mode
});
```

### Inline Method

Embed the calendar inline in a container:

```javascript theme={null}
Cal("inline", {
  elementOrSelector: "#my-cal-inline",  // Required: CSS selector or element
  calLink: "organization/event-type",   // Required: Booking link
  config: {                              // Optional: Configuration
    name: "John Doe",
    email: "john@example.com",
    notes: "Initial discussion",
    theme: "dark",
    layout: "month_view"
  }
});
```

### Modal Method

Open the calendar in a modal programmatically:

```javascript theme={null}
Cal("modal", {
  calLink: "organization/event-type",
  config: {
    theme: "dark",
    layout: "month_view"
  }
});
```

### Floating Button Method

Create a floating action button:

```javascript theme={null}
Cal("floatingButton", {
  calLink: "organization/event-type",
  buttonText: "Book a meeting",          // Button text
  buttonPosition: "bottom-right",         // Position: bottom-right, bottom-left, etc.
  config: {                               // Optional: Configuration
    theme: "dark"
  }
});
```

### UI Method

Update UI configuration dynamically:

```javascript theme={null}
Cal("ui", {
  theme: "dark",
  styles: {
    branding: {
      brandColor: "#000000"
    }
  },
  hideEventTypeDetails: false,
  cssVarsPerTheme: {
    light: {
      "cal-border-booker": "#e5e7eb",
      "cal-text-emphasis": "#111827"
    },
    dark: {
      "cal-border-booker": "#374151",
      "cal-text-emphasis": "#f9fafb"
    }
  }
});
```

## Configuration Options

The `config` object supports the following properties:

### Prefill Fields

```javascript theme={null}
config: {
  name: "John Doe",
  email: "john@example.com",
  notes: "Meeting notes",
  guests: ["guest1@example.com", "guest2@example.com"],
  smsReminderNumber: "+1234567890"
}
```

### UI Configuration

```javascript theme={null}
config: {
  theme: "dark",                         // "light" | "dark" | "auto"
  layout: "month_view",                  // "month_view" | "week_view" | "column_view"
  "ui.color-scheme": "dark",
  "ui.autoscroll": "false",             // Disable auto-scroll
  useSlotsViewOnSmallScreen: "true"     // Use slots view on mobile
}
```

### Iframe Attributes

```javascript theme={null}
config: {
  iframeAttrs: {
    id: "my-cal-iframe",
    title: "Cal.com Booking"
  }
}
```

## Event Handling

Listen to booking events to integrate with your application:

### Listen to Events

```javascript theme={null}
Cal("init");

// Listen to booking success
Cal("on", {
  action: "bookingSuccessfulV2",
  callback: (e) => {
    const booking = e.detail.data;
    console.log("Booking created:", {
      title: booking.title,
      startTime: booking.startTime,
      endTime: booking.endTime,
      attendees: booking.attendees
    });
    
    // Track in analytics
    analytics.track("Booking Created", {
      eventType: booking.title,
      duration: booking.duration
    });
  }
});
```

### Available Events

```javascript theme={null}
// Listen to all events
Cal("on", {
  action: "*",
  callback: (e) => {
    console.log("Event:", e.detail.type, e.detail.data);
  }
});

// Listen to specific events
Cal("on", {
  action: "bookerReady",
  callback: (e) => {
    console.log("Booker is ready");
  }
});

Cal("on", {
  action: "bookingCancelled",
  callback: (e) => {
    console.log("Booking cancelled:", e.detail.data);
  }
});
```

### Remove Event Listeners

```javascript theme={null}
const callback = (e) => {
  console.log(e.detail.data);
};

// Add listener
Cal("on", {
  action: "bookingSuccessfulV2",
  callback: callback
});

// Remove listener
Cal("off", {
  action: "bookingSuccessfulV2",
  callback: callback
});
```

## Using Namespaces

Namespaces allow multiple embeds on the same page without conflicts:

```html theme={null}
<div id="cal-1"></div>
<div id="cal-2"></div>

<script>
  // Initialize namespaces
  Cal("init", "namespace1");
  Cal("init", "namespace2");
  
  // Use namespaced embeds
  Cal.ns.namespace1("inline", {
    elementOrSelector: "#cal-1",
    calLink: "team/event-1"
  });
  
  Cal.ns.namespace2("inline", {
    elementOrSelector: "#cal-2",
    calLink: "team/event-2"
  });
  
  // Namespaced event listeners
  Cal.ns.namespace1("on", {
    action: "bookingSuccessfulV2",
    callback: (e) => console.log("Booking from namespace1")
  });
</script>
```

## Performance Optimization

### Prerendering

Preload the booking page for faster modal opening:

```javascript theme={null}
Cal("init");

// Prerender when user hovers over CTA
document.querySelector(".book-button").addEventListener("mouseenter", () => {
  Cal("prerender", {
    calLink: "organization/event-type",
    type: "modal",
    pageType: "team.event.booking.slots"
  });
});
```

### Preloading with Router

For routing forms, prerender with routing parameters:

```javascript theme={null}
Cal("prerender", {
  calLink: "router?formId=123&department=sales",
  type: "modal",
  pageType: "team.event.booking.slots"
});
```

## Advanced Examples

### Dynamic Configuration

Update configuration based on user actions:

```javascript theme={null}
Cal("init");
Cal("inline", {
  elementOrSelector: "#my-cal",
  calLink: "organization/event-type"
});

// Update theme dynamically
document.querySelector("#dark-mode-toggle").addEventListener("click", () => {
  Cal("ui", {
    theme: "dark"
  });
});
```

### Integration with Forms

Prefill booking data from a form:

```html theme={null}
<form id="contact-form">
  <input type="text" name="name" placeholder="Name">
  <input type="email" name="email" placeholder="Email">
  <button type="submit">Book Meeting</button>
</form>

<script>
  Cal("init");
  
  document.querySelector("#contact-form").addEventListener("submit", (e) => {
    e.preventDefault();
    const formData = new FormData(e.target);
    
    Cal("modal", {
      calLink: "organization/event-type",
      config: {
        name: formData.get("name"),
        email: formData.get("email")
      }
    });
  });
</script>
```

### Auto-forward Query Parameters

Forward URL query parameters to the embed:

```html theme={null}
<script>
  Cal.config = Cal.config || {};
  Cal.config.forwardQueryParams = true;
  
  Cal("init");
  Cal("inline", {
    elementOrSelector: "#my-cal",
    calLink: "organization/event-type"
  });
</script>
```

Now parameters like `?name=John&email=john@example.com` will be forwarded to the embed.

## Element Click Embed

Use data attributes for zero-JavaScript modal embeds:

```html theme={null}
<!-- Add multiple booking buttons -->
<button 
  data-cal-link="organization/event-type-1"
  data-cal-config='{"theme":"light"}'
>
  Book Sales Call
</button>

<button 
  data-cal-link="organization/event-type-2"
  data-cal-config='{"theme":"dark"}'
>
  Book Support Call
</button>

<!-- Initialize once -->
<script>
  Cal("init");
</script>
```

### With Namespace

```html theme={null}
<button 
  data-cal-namespace="sales"
  data-cal-link="organization/sales-call"
>
  Book Sales Call
</button>

<script>
  Cal("init", "sales");
</script>
```

## Debugging

### Enable Logging

Add `cal.embed.logging=1` to your page URL:

```
https://example.com/booking?cal.embed.logging=1
```

This will log:

* Embed initialization
* Parent-iframe communication
* Event triggers
* Configuration changes

### Debug Mode

Enable debug mode during initialization:

```javascript theme={null}
Cal("init", {
  debug: true,
  uiDebug: true
});
```

## Package Information

The embed snippet is part of the `@calcom/embed-snippet` package:

```json theme={null}
{
  "name": "@calcom/embed-snippet",
  "version": "1.3.3",
  "description": "Vanilla JS embed snippet that loads @calcom/embed-core"
}
```

The snippet:

* Loads `@calcom/embed-core` dynamically
* Queues commands until the core library is ready
* Supports multiple namespaces
* Has zero dependencies
* Minimal file size (\~2KB)

## Best Practices

<AccordionGroup>
  <Accordion title="Initialize once per page">
    Call `Cal("init")` once, preferably near the closing `</body>` tag. Multiple initializations are safe but unnecessary.
  </Accordion>

  <Accordion title="Use CSS selectors carefully">
    Ensure your `elementOrSelector` targets exist in the DOM before calling inline embed methods.
  </Accordion>

  <Accordion title="Handle events early">
    Set up event listeners with `Cal("on", ...)` before triggering actions that might fire those events.
  </Accordion>

  <Accordion title="Clean up when needed">
    For single-page applications, remove event listeners when unmounting components to prevent memory leaks.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Customization Options" icon="palette" href="/embed/customization">
    Learn about themes, styles, and branding
  </Card>

  <Card title="React Component" icon="react" href="/embed/embed-react">
    Use the React wrapper for React apps
  </Card>
</CardGroup>
