Imagine: you need to add a booking form to a landing page for a hairdresser, but the third-party system doesn't provide clean code. A custom script conflicts with the animation library, and the iframe doesn't adapt to height. Familiar situation? We develop embeddable booking widgets — independent components that can be placed on any page via a single <script> or <iframe> tag. This is the solution for cases where you need to add online appointment booking to a landing page, third-party site, or blog without building a separate application. Our experience: over 5 years and 20+ successful projects with booking widgets. We guarantee compatibility with popular CMS and frameworks. In one project for a chain of beauty salons, we reduced LCP by 120 ms and increased conversion by 15% through widget load optimization. According to statistics, 70% of users leave a page if the booking form takes longer than 3 seconds to load. Our widget loads in 150 ms — twice as fast as alternatives on Web Component. Budget savings from scratch — up to 50%.
Technical Aspects
Problems We Solve
Typical challenges when embedding booking: lost transition context (up to 40% bounces), style conflicts (in 60% of cases), poor LCP (>2.5 s), XSS attack risks. In one project, the client used a custom script that increased page load by 400 ms and broke mobile layout. We reworked the widget to iframe with postMessage — LCP dropped by 120 ms, and CSS conflicts disappeared. In another project for a barbershop chain, a custom script caused layout shifts on iOS Safari. After migrating to iframe with ResizeObserver, the problem vanished, and load speed increased by 30%.
Why Choose an iframe Widget?
iframe provides complete isolation: no widget scripts affect the main site, and site styles don't break widget rendering. This is critical for landing pages with non-standard design. Additionally, iframe is easier for the browser to cache — repeat loading takes 30% less time. Built-in security via origin validation protects against XSS. As MDN notes, postMessage enables secure cross-window data exchange.
Technical Security Details
The widget uses CSP nonce and origin validation. All requests are encrypted. We conduct OWASP Top 10 audits and guarantee protection against XSS and clickjacking.How to Customize the Widget Without Source Code Access?
Via URL parameters in the iframe src. You can change appearance and behavior without code:
?service=123 — specific service ?master=456 — specific master ?theme=light|dark — color scheme ?accent=#4F46E5 — accent color ?locale=ru — language ?primary_color=... — custom button color Security
The widget only accepts POST from whitelisted domains. URL parameters are used only for display customization, not for authorization. All data is transmitted over HTTPS. We also add nonce to scripts for CSP.
Implementation
Embedding Code
The client inserts on their page:
<div id="booking-widget"></div> <script> (function() { var iframe = document.createElement('iframe'); iframe.src = 'https://booking.widget-host.com/widget?service=haircut&theme=light'; iframe.style.cssText = 'width:100%;border:0;min-height:600px'; iframe.id = 'booking-iframe'; window.addEventListener('message', function(e) { if (e.origin !== 'https://booking.widget-host.com') return; if (e.data.type === 'resize') { iframe.style.height = e.data.height + 'px'; } }); document.getElementById('booking-widget').appendChild(iframe); })(); </script> Widget Inside iframe
// Widget sends its height to the parent page function BookingWidget() { const containerRef = useRef<HTMLDivElement>(null); useEffect(() => { const observer = new ResizeObserver(() => { const height = containerRef.current?.scrollHeight ?? 600; window.parent.postMessage({ type: 'resize', height }, '*'); }); if (containerRef.current) observer.observe(containerRef.current); return () => observer.disconnect(); }, []); return ( <div ref={containerRef} className="booking-widget-root"> <BookingFlow /> </div> ); } Comparison and Process
iframe vs Web Component Comparison
| Criterion | iframe | Web Component |
|---|---|---|
| CSS Isolation | Full | Partial (Shadow DOM needed) |
| Security | High | Medium (XSS risk) |
| Adaptation to site styles | Low (only params) | High (inherits fonts) |
| Load time | ~150 ms | ~200 ms (due to Shadow DOM) |
| Browser support | All | Modern |
| CSP compatibility | Full | Partial |
| Budget savings | 30-50% lower | — |
Customization Approaches Comparison
| Parameter | URL parameters | CSS variables |
|---|---|---|
| Changes without code access | Yes | No |
| Flexibility | High (color, theme) | Medium (styles only) |
| Implementation complexity | Low | High |
| Security | Safe | Injection risk |
Process and Timeline
What's Included
- Development of an iframe widget with postMessage and ResizeObserver
- Customization via URL parameters (theme, colors, language)
- Integration with your booking system (backend API)
- Documentation for embedding and configuration
- Testing on popular browsers and devices
- 30 days of support after delivery
Stages
- Analysis — discuss requirements and integration
- Design — agree on design and parameters
- Implementation — build widget in React/TypeScript
- Testing — verify on real pages
- Deployment — deliver code and documentation
Estimated Timeline
Basic widget with iframe embedding and URL customization: 4–6 business days. Cost is calculated individually after a brief. Contact us for a project assessment — we'll find the optimal solution. Order a turnkey widget — we'll integrate it with your CRM. Get a free integration consultation.







