konfigra | Embed SDK Docs
Add ?tenant=your-store-id to the URL to personalize all code examples for your store. — e.g. https://konfigra.com/docs?tenant=acme

konfigra Embed SDK

Add the 3D configurator to your website with a single line of JavaScript

The konfigra Embed SDK lets you integrate an iframe-based 3D product customizer directly into your website. Your customers can configure products, save their designs, and continue to checkout — without ever leaving your store.

One-line setup

Integrate in under a minute with a script tag

PostMessage API

Control colors, products, and capture screenshots

E-commerce ready

Modal mode + design URL injected into your cart form

Your SDK URL
https://{your-store}.konfigra.com/embed/konfigra-embed.js

Quick Start

Add the script tag to your page — that's it.

<!-- 1. Widget container -->
<div id="konfigra-widget"></div>

<!-- 2. SDK script -->
<script
  src="https://{your-store}.konfigra.com/embed/konfigra-embed.js"
  data-container="#konfigra-widget"
  data-product="5"
  data-mode="simple">
</script>

Replace 5 with a real product ID from your store.


Method 1

Script Tag

No JavaScript knowledge required. All options are set via HTML attributes.

<div id="konfigra-widget"></div>

<script
  src="https://{your-store}.konfigra.com/embed/konfigra-embed.js"
  data-container="#konfigra-widget"
  data-product="5"
  data-template="12"
  data-mode="simple"
  data-height="600px"
  data-width="100%">
</script>
AttributeRequiredDescription
data-container Yes CSS selector for the widget container (e.g. #widget)
data-product No Product ID to load automatically. Omit to show the product list.
data-template No Template ID to pre-select
data-mode No simple (default) or full for the complete studio experience
data-height No iframe height — default: 600px
data-width No iframe width — default: 100%

Method 2

Programmatic

Load the SDK first, then initialize it with JavaScript. Gives full access to event listeners and control methods.

<script src="https://{your-store}.konfigra.com/embed/konfigra-embed.js"></script>

<div id="konfigra-widget"></div>

<script>
const embed = konfigraEmbed.init({
  container:  '#konfigra-widget',
  productId:  5,           // optional: open a specific product
  templateId: 12,          // optional: pre-select a template
  mode:       'simple',    // 'simple' | 'full'
  height:     '600px',
  on: {
    'konfigra:ready': () => {
      console.log('Studio is ready');
    },
    'konfigra:color-changed': ({ layerId, color, allColors }) => {
      console.log('Color changed:', layerId, '→', color);
    },
    'konfigra:design-saved': ({ designId, salt, shareUrl }) => {
      console.log('Design saved:', shareUrl);
    },
  }
});
</script>
Tip: If productId is omitted, the studio opens the product list and the user picks one. Pass a product ID to jump straight to that product.

Method 3

Modal

The studio opens in a centered overlay when the user clicks a button. Ideal for product detail pages.

<script src="https://{your-store}.konfigra.com/embed/konfigra-embed.js"></script>

<button id="customize-btn">Customize Product</button>

<script>
const embed = konfigraEmbed.init({
  mode:      'modal',   // no container needed — SDK builds the overlay
  productId: 5,
  on: {
    'konfigra:design-saved': ({ designId, salt, shareUrl }) => {
      document.querySelector('[name="konfigra_design_url"]').value = shareUrl;
      embed.close();
    }
  }
});

document.querySelector('#customize-btn').addEventListener('click', () => embed.open());
</script>

The SDK automatically creates the backdrop overlay and a close button. Clicking the backdrop or calling embed.close() dismisses it.


init() Options

All parameters accepted by konfigraEmbed.init(opts).

OptionTypeDefaultDescription
container string | Element CSS selector or DOM element. Optional when mode:'modal'.
mode string 'simple' simple — color-only lite studio
full — full studio experience
modal — studio inside a popup overlay
productId number null Product to open directly. Omit to show the product list.
templateId number null Template to pre-select. Used together with productId.
height string '600px' iframe height (any CSS unit)
width string '100%' iframe width
on object {} Shorthand event listeners: { 'konfigra:ready': fn, ... }

Control Methods

Called on the object returned by konfigraEmbed.init().

embed.setColor(layerId, color) Color

Changes the color of a UV layer. Layer IDs are defined in your product templates. Accepts any CSS color value.

embed.setColor('body',  '#ff0000');
embed.setColor('collar', 'rgb(0, 128, 0)');
embed.setColor('sleeve', 'navy');

// Method chaining
embed.setColor('body',  '#3b82f6')
     .setColor('collar', '#1e293b');
embed.setProduct(productId, templateId?) Product

Switches the displayed product and/or template. Useful for letting users switch between variants without reloading the widget.

embed.setProduct(7);       // switch product only
embed.setProduct(7, 23);   // switch product + template
embed.resetColors() Color

Resets all UV layer colors to the template defaults.

embed.getScreenshot() → Promise<string> Visual

Captures the current 3D view as a PNG. Returns a base64 data URI. Rejects after 10 seconds if no response arrives.

embed.getScreenshot().then(dataUri => {
  document.querySelector('#preview').src = dataUri;
}).catch(err => {
  console.error('Screenshot failed:', err.message);
});
embed.on(event, fn) / embed.off(event, fn)

Add or remove an event listener after initialization.

const handler = ({ layerId, color }) => console.log(layerId, color);
embed.on('konfigra:color-changed', handler);
// later…
embed.off('konfigra:color-changed', handler);
embed.open() / embed.close() Modal

Open or close the overlay. Only works when mode: 'modal'.

embed.destroy()

Removes the iframe from the DOM and cleans up all event listeners. Call this when unmounting the widget in single-page applications.


Events

The studio sends messages to your parent page on specific user actions. Listen via the on option or embed.on().

const embed = konfigraEmbed.init({
  container: '#widget',
  productId: 5,
  on: {
    'konfigra:ready':          ()        => console.log('Studio ready'),
    'konfigra:product-loaded': (payload) => console.log('Product loaded', payload),
    'konfigra:color-changed':  (payload) => console.log('Color changed', payload),
    'konfigra:design-saved':   (payload) => console.log('Design saved', payload),
  }
});
EventPayloadDescription
konfigra:ready The iframe has fully loaded and the studio is ready to use
konfigra:product-loaded { productId, templateId } A 3D model has been loaded and rendered
konfigra:color-changed { layerId, color, allColors } The user changed a layer color. allColors is a map of all active colors: { layerId: color }
konfigra:design-saved { designId, salt, shareUrl } The user clicked Save. Use shareUrl to reload the design later.
konfigra:screenshot { requestId, imageData } Internal — handled automatically by getScreenshot()

PostMessage API (advanced)

Communicate with the studio iframe directly via window.postMessage — useful when building custom wrappers or framework integrations.

Parent → iframe (commands)

typepayloadDescription
konfigra:set-color{ layerId, color }Change a layer color
konfigra:set-product{ productId, templateId? }Switch product/template
konfigra:reset-colorsReset all colors
konfigra:get-screenshot{ requestId }Request a screenshot — response arrives as konfigra:screenshot

iframe → Parent (events)

typepayload
konfigra:ready
konfigra:product-loaded{ productId, templateId }
konfigra:color-changed{ layerId, color, allColors }
konfigra:design-saved{ designId, salt, shareUrl }
konfigra:screenshot{ requestId, imageData }
const iframe = document.querySelector('iframe');

// Send a command
iframe.contentWindow.postMessage({
  type:    'konfigra:set-color',
  payload: { layerId: 'body', color: '#3b82f6' }
}, '*');

// Listen for events
window.addEventListener('message', (event) => {
  if (event.source !== iframe.contentWindow) return;
  const { type, payload } = event.data;

  if (type === 'konfigra:design-saved') {
    console.log('Design URL:', payload.shareUrl);
  }
});

E-commerce Flow

The user customizes a product in the modal, saves their design, and the share URL is automatically written into a hidden input so it travels with the cart form.

🛍️
Product Page
"Customize" button
🎨
konfigra Modal
User customizes
💾
Design Saved
URL written to input
🛒
Add to Cart
Form submitted
<form id="cart-form" method="POST" action="/cart/add">
  <input type="hidden" name="product_id" value="5">

  <!-- konfigra writes the design URL here automatically -->
  <input type="hidden" name="konfigra_design_url" id="design-url">
  <input type="hidden" name="konfigra_design_id"  id="design-id">

  <button type="button" id="customize-btn">Customize Product</button>
  <button type="submit" id="cart-btn" disabled>Add to Cart</button>
</form>

<script src="https://{your-store}.konfigra.com/embed/konfigra-embed.js"></script>
<script>
const embed = konfigraEmbed.init({
  mode:      'modal',
  productId: 5,
  on: {
    'konfigra:ready': () => {
      document.querySelector('#customize-btn').disabled = false;
    },
    'konfigra:design-saved': ({ designId, salt, shareUrl }) => {
      document.querySelector('#design-url').value = shareUrl;
      document.querySelector('#design-id').value  = designId;

      embed.close();

      const btn = document.querySelector('#cart-btn');
      btn.disabled    = false;
      btn.textContent = 'Add to Cart ✓';
    }
  }
});

document.querySelector('#customize-btn').addEventListener('click', () => embed.open());
</script>
Order management: When the form is submitted, konfigra_design_url is stored with the order. Click the URL from your admin panel to view exactly what the customer designed.

Full Example

Color panel synchronized with the studio + screenshot capture. Copy, paste, and run.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>konfigra Embed Example</title>
  <style>
    * { box-sizing: border-box; }
    body { font-family: sans-serif; margin: 0; background: #f8fafc; }
    .container { max-width: 1100px; margin: 2rem auto; padding: 0 1rem; }
    h1 { font-size: 1.5rem; font-weight: 700; color: #1e293b; margin-bottom: 1rem; }
    .toolbar {
      display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center;
      background: #fff; border: 1px solid #e2e8f0; border-radius: 12px;
      padding: 0.75rem 1rem; margin-bottom: 1rem;
    }
    .toolbar label { font-size: 0.875rem; color: #64748b; display: flex; align-items: center; gap: 0.4rem; }
    input[type=color] { width: 32px; height: 32px; border: none; border-radius: 6px; cursor: pointer; }
    .btn {
      padding: 0.45rem 0.9rem; border: none; border-radius: 8px; cursor: pointer;
      font-size: 0.875rem; font-weight: 500; background: #6366f1; color: #fff;
    }
    .btn-outline { background: transparent; border: 1px solid #e2e8f0; color: #64748b; }
    #status { font-size: 0.8rem; color: #94a3b8; margin-left: auto; }
    #widget { border-radius: 16px; overflow: hidden; box-shadow: 0 4px 24px rgba(0,0,0,.08); }
    #preview { margin-top: 1rem; max-width: 300px; border-radius: 12px; display: none;
               box-shadow: 0 4px 20px rgba(0,0,0,.12); }
  </style>
</head>
<body>
<div class="container">
  <h1>Product Customizer</h1>

  <div class="toolbar">
    <label>
      Body
      <input type="color" id="c-body" value="#3b82f6"
             oninput="embed.setColor('body', this.value)">
    </label>
    <label>
      Sleeve
      <input type="color" id="c-sleeve" value="#1e293b"
             oninput="embed.setColor('sleeve', this.value)">
    </label>
    <button class="btn btn-outline" onclick="embed.resetColors()">Reset</button>
    <button class="btn" onclick="screenshot()">Screenshot</button>
    <span id="status">Loading…</span>
  </div>

  <div id="widget"></div>
  <img id="preview" alt="Design preview">
</div>

<script src="https://{your-store}.konfigra.com/embed/konfigra-embed.js"></script>
<script>
const embed = konfigraEmbed.init({
  container: '#widget',
  productId:  5,
  mode:       'simple',
  height:     '580px',
  on: {
    'konfigra:ready': () => {
      document.querySelector('#status').textContent = 'Ready ✓';
    },
    'konfigra:color-changed': ({ layerId, color }) => {
      const el = document.querySelector('#c-' + layerId);
      if (el) el.value = color;
    },
    'konfigra:design-saved': ({ shareUrl }) => {
      alert('Design saved!\n' + shareUrl);
    }
  }
});

function screenshot() {
  document.querySelector('#status').textContent = 'Capturing…';
  embed.getScreenshot().then(dataUri => {
    const img = document.querySelector('#preview');
    img.src = dataUri;
    img.style.display = 'block';
    document.querySelector('#status').textContent = 'Ready ✓';
  });
}
</script>
</body>
</html>