| 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%"
  data-lang="auto">
</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%
data-lang No Studio language, e.g. en, tr, de, or auto to follow your page's <html lang>. See Studio Language.

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',
  lang:       'auto',      // optional: 'en' | 'tr' | 'de' | 'auto'
  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
lang string null Studio language code (en, tr, de). 'auto' uses the first two letters of your page's <html lang>. Omit to use your store's default studio language.
on object {} Shorthand event listeners: { 'konfigra:ready': fn, ... }

Studio Language

Open the studio in the same language as your page with lang (or data-lang).

// Fixed language
konfigraEmbed.init({ container: '#konfigra-widget', productId: 5, lang: 'de' });

// Follow the host page: <html lang="tr-TR"> opens the studio in Turkish
konfigraEmbed.init({ container: '#konfigra-widget', productId: 5, lang: 'auto' });
  • The code is sent to the studio as ?lang=<code>. Supported codes: en, tr, de.
  • 'auto' takes the first two letters of document.documentElement.lang. If your page has no lang attribute, nothing is sent.
  • Only languages enabled for your store in the studio settings are honoured. Any other value is ignored and your store's default studio language is used, so an unsupported page language never breaks the widget.
  • The language is fixed when the widget is created. To switch it, call embed.destroy() and init() again with the new lang.

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-colors—Reset 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>