Iframe Embedding

Embed Otesse functionality directly in your website using iframes. This is the fastest way to offer booking capabilities without building a custom integration.

Booking Widget

The booking widget provides a complete booking flow that customers can use without leaving your site.

Basic Embed

<iframe
  src="https://book.otesse.com/embed?key=YOUR_PUBLIC_KEY&industry=cleaning"
  width="100%"
  height="700"
  frameborder="0"
  style="border: none; border-radius: 8px;"
  allow="payment"
  title="Book a Service"
></iframe>

Configuration Parameters

ParameterRequiredDescription
keyYesYour public embed key (not the secret API key)
industryNoPre-select an industry (cleaning, junk-removal, carpet-cleaning)
zipNoPre-fill the ZIP code
themeNolight (default) or dark
accent_colorNoHex color for buttons and accents (e.g., %23FF5500)
hide_headerNoSet to true to hide the Otesse branding header
redirect_urlNoURL to redirect after successful booking
localeNoLanguage code (default: en)

Example with All Options

<iframe
  src="https://book.otesse.com/embed?key=pk_live_abc123&industry=cleaning&zip=97401&theme=light&accent_color=%233B82F6&hide_header=true&redirect_url=https%3A%2F%2Fyoursite.com%2Fthank-you"
  width="100%"
  height="700"
  frameborder="0"
  allow="payment"
  title="Book a Cleaning Service"
></iframe>

Responsive Embedding

For responsive layouts, use a container with aspect ratio:

<div style="position: relative; width: 100%; max-width: 600px; margin: 0 auto;">
  <iframe
    src="https://book.otesse.com/embed?key=YOUR_PUBLIC_KEY"
    style="width: 100%; height: 700px; border: none; border-radius: 8px;"
    allow="payment"
    title="Book a Service"
  ></iframe>
</div>

Communication Between Iframe and Parent

The booking widget communicates with your page via postMessage:

Listening for Events

window.addEventListener('message', (event) => {
  // Verify origin
  if (event.origin !== 'https://book.otesse.com') return;

  const { type, data } = event.data;

  switch (type) {
    case 'otesse:booking_created':
      console.log('Booking created:', data.bookingId);
      // Track conversion, show thank you, etc.
      break;

    case 'otesse:step_changed':
      console.log('User moved to step:', data.step);
      // Track funnel progress
      break;

    case 'otesse:height_changed':
      // Adjust iframe height dynamically
      document.querySelector('iframe').style.height = data.height + 'px';
      break;

    case 'otesse:error':
      console.error('Booking error:', data.message);
      break;
  }
});

Sending Commands to the Widget

const iframe = document.querySelector('iframe');

// Pre-fill customer information
iframe.contentWindow.postMessage({
  type: 'otesse:prefill',
  data: {
    firstName: 'John',
    lastName: 'Smith',
    email: 'john@example.com',
    phone: '+15551234567',
  },
}, 'https://book.otesse.com');

// Navigate to a specific step
iframe.contentWindow.postMessage({
  type: 'otesse:goto_step',
  data: { step: 'schedule' },
}, 'https://book.otesse.com');

Security Considerations

  • The embed key (pklive) is a public key — safe to include in client-side code
  • Payment processing happens within the iframe on Otesse's domain (PCI compliant)
  • Always verify event.origin when listening for postMessage events
  • The allow="payment" attribute is required for Stripe payment processing within the iframe

Portal Embed

For a fuller experience, embed the entire customer portal:

<iframe
  src="https://portal.otesse.com/embed?key=YOUR_PUBLIC_KEY"
  width="100%"
  height="800"
  frameborder="0"
  allow="payment"
  title="Customer Portal"
></iframe>

This provides the full portal experience (bookings, invoices, subscriptions, payment methods) within your website.