Embedding
Embed booking pages and widgets in your application.
Overview
Embed Transactional Calendar booking experiences directly into your website or application. Multiple embedding options available for different use cases.
Embedding Options
| Method | Description | Best For |
|---|---|---|
| Inline Embed | Booking widget in your page | Full integration |
| Popup | Modal overlay | Call-to-action buttons |
| Link | Direct to hosted page | Email, external links |
| React Component | Native React integration | React applications |
Inline Embed
Basic HTML Embed
<!-- Container for booking widget -->
<div id="transactional-booking"></div>
<!-- Load embed script -->
<script src="https://cdn.usetransactional.com/sdk/calendar.min.js"></script>
<script>
TransactionalCalendar.init({
elementId: 'transactional-booking',
eventTypeSlug: 'demo',
organizationSlug: 'your-org',
});
</script>With Options
<script>
TransactionalCalendar.init({
elementId: 'transactional-booking',
eventTypeSlug: 'demo',
organizationSlug: 'your-org',
// Theming
theme: 'light', // 'light', 'dark', 'auto'
primaryColor: '#0066cc',
borderRadius: 8,
// Prefill attendee info
prefill: {
name: 'John Doe',
email: 'john@example.com',
responses: {
company: 'Acme Corp',
},
},
// Hide elements
hideEventTypeDetails: false,
hideHostInfo: false,
// Callbacks
onBookingComplete: (booking) => {
console.log('Booking created:', booking);
trackConversion(booking);
},
onSlotSelected: (slot) => {
console.log('Slot selected:', slot);
},
onError: (error) => {
console.error('Booking error:', error);
},
});
</script>Popup Embed
Trigger from Button
<button onclick="openBookingPopup()">Schedule a Demo</button>
<script src="https://cdn.usetransactional.com/sdk/calendar.min.js"></script>
<script>
function openBookingPopup() {
TransactionalCalendar.popup({
eventTypeSlug: 'demo',
organizationSlug: 'your-org',
theme: 'light',
onBookingComplete: (booking) => {
console.log('Booked:', booking);
},
});
}
</script>Auto-trigger on Page Load
<script>
// Show popup after 30 seconds on page
setTimeout(() => {
if (!sessionStorage.getItem('booking_popup_shown')) {
TransactionalCalendar.popup({
eventTypeSlug: 'demo',
organizationSlug: 'your-org',
});
sessionStorage.setItem('booking_popup_shown', 'true');
}
}, 30000);
</script>React Integration
Install Package
npm install @usetransactional/reactInline Component
import { CalendarEmbed } from '@usetransactional/react';
function BookingPage() {
const handleComplete = (booking) => {
console.log('Booking created:', booking);
router.push('/thank-you');
};
return (
<div className="booking-container">
<h1>Schedule a Meeting</h1>
<CalendarEmbed
eventTypeSlug="demo"
organizationSlug="your-org"
theme="light"
primaryColor="#0066cc"
prefill={{
name: user?.name,
email: user?.email,
}}
onBookingComplete={handleComplete}
/>
</div>
);
}Modal Component
import { CalendarModal } from '@usetransactional/react';
import { useState } from 'react';
function BookingButton() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>
Schedule a Demo
</button>
<CalendarModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
eventTypeSlug="demo"
organizationSlug="your-org"
onBookingComplete={(booking) => {
setIsOpen(false);
showSuccessMessage(booking);
}}
/>
</>
);
}Next.js Dynamic Import
import dynamic from 'next/dynamic';
const CalendarEmbed = dynamic(
() => import('@usetransactional/react').then(mod => mod.CalendarEmbed),
{ ssr: false }
);
export default function BookingPage() {
return (
<CalendarEmbed
eventTypeSlug="demo"
organizationSlug="your-org"
/>
);
}Direct Links
Basic Link
const bookingUrl = `https://calendar.usetransactional.com/${orgSlug}/${eventTypeSlug}`;With Prefill
const params = new URLSearchParams({
name: 'John Doe',
email: 'john@example.com',
'responses[company]': 'Acme Corp',
});
const bookingUrl = `https://calendar.usetransactional.com/${orgSlug}/${eventTypeSlug}?${params}`;For Specific Host
const bookingUrl = `https://calendar.usetransactional.com/${orgSlug}/${eventTypeSlug}?host=${hostSlug}`;iFrame Embed
For complete isolation:
<iframe
src="https://calendar.usetransactional.com/your-org/demo"
width="100%"
height="700"
frameborder="0"
allow="payment"
></iframe>Responsive iFrame
<div style="position: relative; padding-bottom: 100%; height: 0; overflow: hidden;">
<iframe
src="https://calendar.usetransactional.com/your-org/demo"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
frameborder="0"
></iframe>
</div>Customization
Theme Options
TransactionalCalendar.init({
elementId: 'booking',
eventTypeSlug: 'demo',
organizationSlug: 'your-org',
// Colors
primaryColor: '#0066cc',
backgroundColor: '#ffffff',
textColor: '#333333',
// Typography
fontFamily: 'Inter, sans-serif',
// Layout
borderRadius: 8,
padding: 24,
// Theme
theme: 'light', // 'light', 'dark', 'auto'
});Custom CSS
<style>
.transactional-calendar {
--tx-primary: #0066cc;
--tx-primary-hover: #0052a3;
--tx-background: #ffffff;
--tx-text: #333333;
--tx-text-muted: #666666;
--tx-border: #e0e0e0;
--tx-border-radius: 8px;
}
.transactional-calendar .slot-button {
/* Custom slot styling */
}
.transactional-calendar .confirm-button {
/* Custom button styling */
}
</style>CSS Classes Reference
| Class | Element |
|---|---|
.tx-calendar | Container |
.tx-header | Header section |
.tx-event-title | Event name |
.tx-host-info | Host details |
.tx-date-picker | Calendar picker |
.tx-time-slots | Time slot list |
.tx-slot-button | Individual slot |
.tx-form | Attendee form |
.tx-input | Form inputs |
.tx-confirm-btn | Confirm button |
Prefilling Data
From URL Parameters
// Your app generates link with parameters
const bookingLink = `/book/demo?name=${encodeURIComponent(user.name)}&email=${encodeURIComponent(user.email)}`;From JavaScript
TransactionalCalendar.init({
elementId: 'booking',
eventTypeSlug: 'demo',
organizationSlug: 'your-org',
prefill: {
name: userData.name,
email: userData.email,
phone: userData.phone,
responses: {
company: userData.company,
role: userData.role,
},
},
});Dynamic Prefill (React)
function BookingPage() {
const { user } = useAuth();
return (
<CalendarEmbed
eventTypeSlug="demo"
organizationSlug="your-org"
prefill={{
name: user?.name,
email: user?.email,
// Lock email if authenticated
lockEmail: !!user,
}}
/>
);
}Event Callbacks
TransactionalCalendar.init({
elementId: 'booking',
eventTypeSlug: 'demo',
organizationSlug: 'your-org',
// Lifecycle callbacks
onReady: () => {
console.log('Calendar widget loaded');
},
onDateSelected: (date) => {
console.log('Date selected:', date);
analytics.track('date_selected', { date });
},
onSlotSelected: (slot) => {
console.log('Slot selected:', slot);
analytics.track('slot_selected', slot);
},
onFormSubmitted: (data) => {
console.log('Form submitted:', data);
},
onBookingComplete: (booking) => {
console.log('Booking created:', booking);
analytics.track('booking_complete', {
bookingId: booking.uid,
eventType: booking.eventType,
});
// Redirect or show success
},
onBookingError: (error) => {
console.error('Booking failed:', error);
analytics.track('booking_error', { error: error.message });
},
});Responsive Design
The embed automatically adapts to container width:
/* Mobile-first responsive container */
.booking-container {
width: 100%;
max-width: 600px;
margin: 0 auto;
}
@media (min-width: 768px) {
.booking-container {
max-width: 800px;
}
}Security
Allowed Domains
Configure which domains can embed your calendar:
await client.calendar.settings.update({
embedding: {
allowedDomains: [
'yourapp.com',
'*.yourapp.com',
'localhost:3000', // For development
],
},
});Content Security Policy
If using CSP, add:
frame-src https://calendar.usetransactional.com;
script-src https://cdn.usetransactional.com;
Next Steps
- Webhooks - Handle booking events
- API Reference - Complete API docs
- Reminders - Configure notifications
On This Page
- Overview
- Embedding Options
- Inline Embed
- Basic HTML Embed
- With Options
- Popup Embed
- Trigger from Button
- Auto-trigger on Page Load
- React Integration
- Install Package
- Inline Component
- Modal Component
- Next.js Dynamic Import
- Direct Links
- Basic Link
- With Prefill
- For Specific Host
- iFrame Embed
- Responsive iFrame
- Customization
- Theme Options
- Custom CSS
- CSS Classes Reference
- Prefilling Data
- From URL Parameters
- From JavaScript
- Dynamic Prefill (React)
- Event Callbacks
- Responsive Design
- Security
- Allowed Domains
- Content Security Policy
- Next Steps