iframe Embedding
Embed the Wedding Band Builder in an <iframe> for isolated, drop in integration. The viewer runs in its own context and you communicate with it via postMessage. Ideal for CMS platforms, Shopify stores, or any page where you can't add custom scripts.
Image
Screenshot showing a product page with the Wedding Band Builder embedded as an iframe, alongside the host page's own product description and Add to Cart button.
When to Use This
- You're on a CMS or e-commerce platform (Shopify, WordPress, Squarespace, etc.)
- You can't add custom
<script>tags to the page - You want full isolation between the viewer and your page
- You need cross-origin embedding
Quick Start
1. Host the Viewer Page
Create an HTML file that loads the mini-viewer inside the iframe. This page handles all the postMessage bridging automatically.
View full viewer page source and host this file on your server or CDN.
TIP
The viewer page reads ?manifest=, ?basePath=, and ?ui= from URL parameters, making it reusable across different product pages without code changes.
2. Embed on Your Page
<iframe
id="wbb-iframe"
src="https://your-site.com/wbb-viewer.html"
style="width: 100%; height: 600px; border: none;"
allow="camera; xr-spatial-tracking"
></iframe>The allow attributes enable the AR try-on feature inside the iframe.
WARNING
Without allow="camera; xr-spatial-tracking" on the iframe, the AR button appears but fails silently when tapped. Always include these attributes:
<iframe src="viewer.html" allow="camera; xr-spatial-tracking"></iframe>The page must also be served over HTTPS for camera access.
Image
Screenshot showing the iframe embedded in a simple page with the viewer filling the iframe area and the built-in panel visible.
3. Communicate via postMessage
const iframe = document.getElementById('wbb-iframe');
let requestId = 0;
// Send a command
function send(method, args = []) {
iframe.contentWindow.postMessage({
id: `req-${++requestId}`, method, args,
}, '*'); // Use your specific origin in production
}
// Listen for events
window.addEventListener('message', (e) => {
if (e.data?.event === 'ready') {
send('setProfile', [0]);
send('setMaterial', [1, 'Yellow', 'Polished']);
}
if (e.data?.event === 'price:updated') {
document.getElementById('price').textContent =
`$${e.data.data.pricing.totalUsd.toFixed(2)}`;
}
});View complete host page example for a full page with profile/material buttons and live price display.
Video
Video walkthrough showing the host page with the embedded iframe: clicking profile buttons changes the ring shape, clicking metal buttons changes the material, and the price updates in real time on the host page.
Headless Mode
Load the iframe with ?ui=false to hide the built-in panel and build all controls on the host page:
<iframe src="wbb-viewer.html?ui=false" style="width: 100%; height: 500px; border: none;"></iframe>Use postMessage to query the catalog and control everything from your page. See Custom UI (Headless) for a full guide on building custom controls.
Image
Side-by-side: Left shows the iframe with the built-in panel. Right shows the iframe in headless mode with custom-styled controls on the host page.
postMessage Protocol
Sending commands (all API methods are available):
// Command: { id: 'req-1', method: 'setWidth', args: [5.0] }
// Success: { id: 'req-1', result: null }
// Error: { id: 'req-1', error: { message: '...', source: 'api' } }Receiving events (forwarded automatically from the viewer):
// { event: 'price:updated', data: { bandName: 'her', pricing: { totalUsd: 1250.00, ... } } }Promise-based query helper
function query(method, args = []) {
return new Promise((resolve, reject) => {
const id = `req-${++requestId}`;
const handler = (e) => {
if (e.data?.id !== id) return;
window.removeEventListener('message', handler);
if (e.data.error) reject(new Error(e.data.error.message));
else resolve(e.data.result);
};
window.addEventListener('message', handler);
iframe.contentWindow.postMessage({ id, method, args }, '*');
});
}
// Usage
const price = await query('getPrice', ['her']);
const snapshot = await query('getSnapshot');E-Commerce Platform Examples
Ready-to-use integration examples for popular platforms. Each includes the iframe embed, live price display, and Add to Cart wiring.
| Platform | What You Get | Example |
|---|---|---|
| Shopify | Liquid section + cart integration | View example |
| WooCommerce | Shortcode + AJAX cart handler | View example |
| Magento | PHTML block + layout XML + controller | View example |
| BigCommerce | Stencil template + Storefront API | View example |
| Wix | HTML embed + Velo code | View example |
Image
Screenshot of a product page with the Wedding Band Builder iframe embedded, showing the Add to Cart button with live price below the viewer.
Security: Restrict Origins
In production, always replace '*' with your specific domain:
// In the viewer page
window.parent.postMessage({ event: 'ready' }, 'https://your-store.com');
// In the host page
iframe.contentWindow.postMessage({ id, method, args }, 'https://your-cdn.com');Responsive Sizing
.viewer-container {
position: relative;
width: 100%;
padding-bottom: 75%; /* 4:3 aspect ratio */
}
.viewer-container iframe {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
border: none;
}AR Support
The allow="camera; xr-spatial-tracking" attribute on the iframe enables AR try-on. Without it, the AR button will appear but fail silently.
Same-Origin Shortcut
If the iframe and host page are on the same origin, you can skip postMessage entirely:
const iframe = document.getElementById('wbb-iframe');
const viewer = iframe.contentWindow.ijewelViewer;
const api = viewer.getPluginByType('WeddingBandBuilder').controller;
api.setWidth(5.0);URL Parameters
The viewer page accepts these query parameters:
| Parameter | Default | Description |
|---|---|---|
manifest | wedding-band-project.json | URL to the manifest JSON file |
basePath | (viewer page directory) | Base URL for resolving asset paths |
ui | true | Set to false to hide the built-in panel (headless mode) |
<!-- Default: built-in UI shown -->
<iframe src="wbb-viewer.html"></iframe>
<!-- Headless: no built-in UI -->
<iframe src="wbb-viewer.html?ui=false"></iframe>
<!-- Custom manifest and base path -->
<iframe src="wbb-viewer.html?manifest=my-config.json&basePath=https://cdn.example.com/rings/"></iframe>Next Steps
- Custom UI (Headless) to build your own controls
- API Reference for complete method documentation
- Pricing Engine to configure the pricing engine