Configurator – Two-Way Communication via postMessage

Introduction

To enable communication between the Configurator and the host website:

  1. Open the E-commerce Settings tab in the Alter Product app.
  2. In section Integration set the domain where the iframe will be embedded (e.g. https://yourwebsite.pl or http://localhost:3000 )

You can also add metadata keys to each variant in the design which will be included in product – in the Product Configuration tab.

Messages sent by the Configurator

TypeDescription
ALTER_CONFIGURATOR_ADD_TO_CARTClicking the “Add to Cart” button
ALTER_CONFIGURATOR_DATA_RESPONSEResponse to product data request

Full Example (HTML + JS)

1<!DOCTYPE html>
2<html lang="en">
3<head>
4  <meta charset="UTF-8" />
5  <title>Alter Product Configurator Integration</title>
6</head>
7<body>
8  <h1>My Product Page</h1>
9
10  <button id="getDataBtn">Get Configured Product</button>
11
12  <iframe
13    id="configuratorWidget"
14    src="https://alterproduct.com/app/configurator/1?nav=0&add_to_cart=1"
15    title="Alter Product Configurator"
16    width="100%"
17    height="600"
18    frameborder="0"
19    allowfullscreen>
20  </iframe>
21
22  <script>
23    const iframe = document.getElementById('configuratorWidget');
24    const getDataBtn = document.getElementById('getDataBtn');
25
26    // Send a request to fetch product data from the configurator
27    getDataBtn.addEventListener('click', () => {
28      iframe.contentWindow.postMessage(
29        { type: 'ALTER_CONFIGURATOR_GET_PRODUCT_DATA' },
30        'https://alterproduct.com' // Make sure to match the actual origin
31      );
32    });
33
34    // Listen for messages sent back from the widget
35    window.addEventListener('message', (event) => {
36      const allowedOrigin = 'https://alterproduct.com';
37      if (event.origin !== allowedOrigin) {
38        console.warn('Rejected message from untrusted origin:', event.origin);
39        return;
40      }
41
42      // Defensive parsing: event.data can be object OR string in some implementations
43      const data = event.data;
44      if (!data || (typeof data !== 'object' && typeof data !== 'string')) return;
45
46      const payloadObj = typeof data === 'string' ? (() => {
47        try { return JSON.parse(data); } catch { return null; }
48      })() : data;
49
50      if (!payloadObj || typeof payloadObj !== 'object') return;
51
52      const { type, payload } = payloadObj;
53      if (!type || typeof type !== 'string') return;
54
55      if (type === 'ALTER_CONFIGURATOR_ADD_TO_CART') {
56        console.log('Add to cart triggered from configurator:', payload);
57      }
58
59      if (type === 'ALTER_CONFIGURATOR_DATA_RESPONSE') {
60        console.log('Received configuration data:', payload);
61      }
62    });
63  </script>
64</body>
65</html>

Example payload

{
  "productItems": [
    {
      "model3d": { "id": 3 },
      "size": {
        "id": 9,
        "name": { "pl": "450ml (15oz)", "en": "450ml (15oz)" },
        "measureSize": { "D": 8.65, "H": 11.95 }
      },
      "material": { "id": 3, "name": { "pl": "Ceramika", "en": "Ceramic" } },
      "printType": { "id": 5, "name": { "pl": "Sublimacja", "en": "Sublimation" } },
      "color": { "id": 11, "name": { "pl": "Domyślny", "en": "Default" }, "hex": "#FFFFFF" },
      "variant": {
        "id": 11,
        "productGroupId": 1,
        "productModel3dId": 3,
        "sizeId": 9,
        "materialId": 3,
        "printTypeId": 5,
        "colorId": 11,
        "metadata": null,
        "minOrderQuantity": null,
        "processingTime": null,
        "stockQuantity": null,
        "volume": null,
        "weight": null
      },
      "unitPrice": { "value": 0, "currency": "EUR" },
      "totalPrice": { "value": 0, "currency": "EUR" },
      "quantity": 1
    }
  ],
  "designName": "Mug 450ml (15oz)",
  "productGroup": {
    "id": 1,
    "name": { "pl": "Kubek 450ml (15oz)", "en": "Mug 450ml (15oz)" }
  },
  "totalPrice": { "value": 0, "currency": "EUR" },
  "userDesignId": 10
}