10.2.0 - 3D Product Configurator Integrations Guide

Prev Next

Implementing On Your Website

The 3D Product Configurator front end code can be implemented on customer facing websites through several methods. Defined below are options an implementing developer can use to integrate with a website.

Front End Application Supported Browsers and Devices

Chrome

51+

Firefox

54+

Edge

14+

Safari

10+ (except 15.0; 15.1+ supported)

Opera

38+

Internet Explorer

Not supported

Edge iOS

Not supported

Front End Application URL Parameters

â—Ź ?config=<configId>

â—‹ The Id of the configurator to load, used for debugging purposes a developer should pass in the configurator id in the initialization functions of the API for production use.

â—Ź ?storeId=<storeId>

â—‹ Store Id used for Analytics

â—Ź ?sku=<sku>

â—‹ Sku of the current chair loaded, auto updated on swapping steps

â—Ź ?preview=<true/false>

â—‹ This parameter is for testing purposes only and will force the application to always load the latest version of the configurator.

Adding the library from the 3D Cloud CDN

Ask your account team for your specific CDN URLs.

  1. JS example:

    1. https://cdn.3dcloud.io/{client_specific_folder}/x.x.x/MxtProductConfigurator-x.x.x.js

  2. Minified JS example (should be used in production environments)

    1. https://cdn.3dcloud.io/{client_specific_folder}/x.x.x/MxtProductConfigurator-x.x.x.min.js

  3. CSS example:

    1. https://cdn.3dcloud.io/{client_specific_folder}/x.x.x/MxtProductConfigurator-x.x.x.css

  4. Initiating the application example:

<!DOCTYPE html>
<html>
<head>
    <title>MxtModularConfigurator Example</title>
    <link href="https://cdn.3dcloud.io/mxt-kongfigurator/10.2.0/MxtProductConfigurator-10.2.0.css" rel="stylesheet">
    <style>
        .mxt-full-modal-screen {
            width: 80%;
            height: 100%;
            position: absolute;
        }
    </style>
</head>
<body>
    <div id="spins-test-container" class="mxt-full-modal-screen"></div>
    <script src="https://cdn.3dcloud.io/mxt-kongfigurator/10.2.0/MxtProductConfigurator-10.2.0.min.js"></script>
    <script>
        async function initializeUnitConfig() {
            const unitConfig = new MxtProductConfigurator.MxtKongfigurator({
                spinCommon: {
                    apiKey: '{user api key provided by 3D Cloud}',
                    element: document.getElementById('spins-test-container'),
                    expandButton: {},
                    webArMode: "OnDemand"
                },
                spin3d:{
                    camera: {},
                    screenshot: {},
                },
                assetEnvironment: '{Active OR Stage}',
                configurationId:  '{configurator ID to load}',
                configurationBrowserId: '{configurator ID to browse from}',
            });
            await unitConfig.init();
        }
        initializeUnitConfig();  // Call the function
    </script>   
</body>
</html>

Initialization

When initializing, there are two things that MUST be true about the HTML element that you pass in (or the parent element for the viewer container, see the Components section below)

  1. It MUST have a defined height and width, whether that is an absolute value (like 600px) or a percentage of its parent that has an absolute value (for example 50% of the page width/height). This is because the 3d canvas has no defined size in and of itself, so we have no “size to build out”, so to speak. Additionally, if a size is NOT given, the 3d render engine will spin out of control attempting to render in a 0x0 space.

  2. (for 3d render type only) It MUST be not be display:none while the engine is running. By default, the engine starts running on init. IF you want to init the MxtKongfigurator in a hidden container, use the option spin3d.loadPaused. The 3d renderer will spin out of control when attempting to render to a non-visible container. By using the option spin3d.loadPaused, the renderer will start in a paused mode. In order to start the rendering engine when the container is made visible, call the run() method. To re-pause the renderer, call the stop() method.

Minimum Required Options

When constructing the class for the product configurator there are required options and optional options that you will set for the product configurator to function properly. These are the three required options that you must always set.

Option Name

Option Description

spinCommon.apiKey

API Key provided by 3D Cloud™(required)

configurationId

the unique id of the configurator to load (required)

spinCommon.element

The element that the Configurator will be built within. Some sort of specific height and width must be given, otherwise the app will not have any size. This is due to the fact that the rendering canvas has no inherent size. (required)

configuratorBrowserId

The unique id of the configurator browser step to load on startup inside the configurator when using a step type configurator browser and you want to override the default choice in the configurator data.

Basic Optional Options

These options are optional and are the most commonly set by developers implementing the product configurator on their website.

SpinCommon options

These options are applicable to the render view for both 2d and 3d renders, and live under spinCommon, i.e.

const configurator = new MxtProductConfigurator.MxtKongfigurator({
    spinCommon: {
        apiKey: '{user api key provided by 3D Cloud}',
        ...
    },
});

apiKey and element are covered above.

Option Name

Option Description

loadingIconColor

CSS string defining color of loading progress bar.

loadingIconBackgroundColor

CSS string defining color of loading progress bar background.

services?: {
        environment?: MSServiceEnvironment;
    };

The environment of services to hit. Defaults to production.

logging

Sets the log level which can be pulled from log.levels namespace;

TRACE: 0;
DEBUG: 1;
INFO: 2;
WARN: 3;
ERROR: 4;
SILENT: 5;

Defaults to WARN

AR Options

Part spinCommon options.

webArMode?: WebArMode;
webArOptions?: MxtSpinsWebArOptions;

WebArMode defaults to WebArMode.None.

  • WebArMode.Pregenerated will attempt to get an AR asset that has already been generated and stored based on the current sku(s). If none exists, then no web AR asset will be available.

  • WebArMode.OnDemand will look up an existing AR asset based on sku(s), but if one does not exist, a new one will be generated when a user requests one.

webArOptions.enableScaling - by default, scaling on USDZ is turned off. If you wish to enable, set this flag

Customizing Text and Icons Options

This only applies to spinCommon options:

To customize icons used in the renderer view:

icons: {
    about?: string;
    close?: string;
    collapse?: string;
    presetView?: string;
    presetViewActive?: string;
    download?: string;
    downloadInverse?: string;
    downloadActive?: string;
    expand?: string;
    rotateLeft?: string;
    rotateRight?: string;
    spinner?: string;
    webAr?: string;
    webArInverse?: string;
    zoomIn?: string;
    zoomOut?: string;
}

To customize text:

customText in the format {[language: string]: any;} where language is a language ISO code (https://www.metamodpro.com/browser-language-codes), for example:

customText : {
    en: {
      about: {
          appName: "My example app name"
      }
    }    
};

Rather than providing an exhaustive list of every available key, please contact us with the text you desire to override, and we will provide you with the appropriate key(s).

spin3d Options

These options are applicable to the render view for 3d renders only, and live under spin3d, i.e.

const configurator = new MxtProductConfigurator.MxtKongfigurator({
    spin3d: {
        camera: {}
        ...
    },
});

Option Name

Option Description

loadPaused

Use this if you dont want the 3d render loop to start immediately upon initialization. Use especially if you are initializing in a hidden div or one with no size. Call run() method to start the 3d render loop whenever the div becomes visible.

zoomDelta

Zoom Delta - in meters; defaults to .3

rotateDelta

Rotate Delta - in radians; defaults to .3

fitToScreenMultiplier

The amount of screen that a product should “fill” when initially loaded; essentially default zoom level but relative to product size

maxDistanceMultiplier

Effectively max zoom, relative to the default zoom level

showGuidance

If not provided, defaults to on if panning is turned on, and defaults to off if panning is turned off. If true, then will create guidance with panning guidance if panning is allowed, and guidance without panning if panning is not allowed

Camera Options

Part spin3d options. All nested within a “camera” options object, i.e.

spin3d: {
    camera: {
      allowPanning: true,
      ...
    }
},

Option Name

Option Description

allowPanning

If true, right click pans the camera rather than rotates the camera. Panning is limited to bounds of product.

defaultAlpha,

defaultBeta

lowerBetaLimit

Minimum camera angle that the camera can rotate vertically

upperBetaLimit

Maximum camera angle that the camera can rotate vertically

lowerAlphaLimit

Minimum camera angle that the camera can rotate horizontally

upperAlphaLimit

Maximum camera angle that the camera can rotate horizontally

Hotspot Options

Part spin3d options. All nested within a “hotspots” options object, i.e.

spin3d: {
    hotspots: {
      invisibleOnLoad: true,
      ...
    }
},

Option Name

Option Description

invisibleOnLoad

There is a hotspot toggle in the UI. By default, hotspots show up when there are hotspots and the UI toggle is on. This defaults the UI toggle to off so that the user has to manually toggle the hotspots on.

hotspotMeshBasePath

URL base path for a hotspot mesh; we provide a default hotspot mesh, but a custom one can be provided by using this + hotspotMeshFilename

hotspotMeshFilename

Filename of hotspot mesh. Must be a GLB/GLTF file. URL is created by doing hotspotMeshBasePath + hotspotMeshFilename.

Customizing 3D viewer Icon Options

This only applies to spin3d options:

To customize icons used in the 3drenderer view:

icons: {
    hotspotToggle?: string;
    hotspotToggleActive?: string;
    hotspotToggleInverse?: string;
    dimensions?: string;
    dimensionsActive?: string;
    dimensionsInverse?: string;
    panningGuidanceMouse?: string;
    panningGuidanceMousePan?: string;
    panningGuidanceDrag?: string;
    panningGuidanceTwoFingerDrag?: string;
}

Dimension Options

Part spin3d options. All nested within a “dimensions” options object, i.e.

spin3d: {
    dimensions: {
      enabled: true
      ...
    }
},

Option Name

Option Description

enabled

Enable/disable dimensions. Enabled by default

color

Color of dimension lines: { r: 0.5921, g: 0.5921, b: 0.5921, a: 1 } by default (light blue)

unitType

Unit type to display for dimensions; defaults to inches.

visibleOnLoad

If dimensions should be visible on load. Defaults to off, users must toggle it on

lineScale

Size of line

arrowScale

Size of arrows at the end of the line

Preset Views Options

Part spin3d options. All nested within a “presetViews” options object, i.e.

spin3d: {
    presetViews: {
      enabled: true
      ...
    }
},

Option Name

Option Description

enabled

Enable/disable preset views. Enabled by default

views

We supply default preset views. To override these, provide an array of objects in format:

{   
    id: string;
    displayName: string;
    icon: string;
    azimuth: number;
    elevation: number;
}

Screenshot Options

Part spin3d options. All nested within a “screenshot” options object, i.e.

spin3d: {
    screenshot: {
      width: 1024
      ...
    }
},

Option Name

Option Description

enabled

By default, enabled.

width

By default, screenshot 1024x1024. May specify a different width, or set to -1 to use size on screen. If using a value other than -1, note that cropping may occur if your aspect ratio on screen does not match the aspect ratio defined here

height

By default, screenshot 1024x1024. May specify a different height, or set to -1 to use size on screen. If using a value other than -1, note that cropping may occur if your aspect ratio on screen does not match the aspect ratio defined here

hiResWidth

By default, hi res screenshot 4096x4096. May specify a different width, or set to -1 to use size on screen. If using a value other than -1, note that cropping may occur if your aspect ratio on screen does not match the aspect ratio defined here

hiResHeight

By default, hi res screenshot 4096x4096. May specify a different height, or set to -1 to use size on screen. If using a value other than -1, note that cropping may occur if your aspect ratio on screen does not match the aspect ratio defined here

waterMarkPlugin

Provide a watermark for your screenshot downloads

downloadImagePlugins

By default, we provide certain downloads (jpg and png). If you want to provide more/different types, use these plugins to add more.

imageFilename

By default, the downloaded image gets a filename of the sku; override this to provide a custom imageFilename

spin2d options

These options are applicable to the render view for 2d renders only, and live under spin2d, i.e.

const configurator = new MxtProductConfigurator.MxtKongfigurator({
    spin2d: {
        zoomDisabled: true
        ...
    },
});

Option Name

Option Description

zoomDisabled

Use this to disable zoom controls and not allow the user to look at a zoomed in (higher resolution) render

backgroundColor

Default is white, format is {r:number, g:number, b:number, a:number} where each value goes from 0->1, inclusive

Configurator Level Options

These options are applicable to the configurator in general and live at the root level of options

const configurator = new MxtProductConfigurator.MxtKongfigurator({
    assetEnvironment: MxtKongfigAssetEnvironment.STAGING
    ...
});

Option Name

Option Description

renderType

2d or 3d or none. Defaults to 3d.

assetEnvironment

enum MxtKongfigAssetEnvironment {
    LATEST = "Latest",
    TEST = "Test",
    STAGING = "Stage",
    PRODUCTION = "Active"
}

Use PRODUCTION for your production environment and STAGING for your cert environment, and TEST for your test enviroment. LATEST includes works-in-progress configurators and shouldn’t be used generally by clients.

skuUrlParam

By default, we auto-update the URL parameter 'sku' with the current sku. Use this to change the url parameter to something other than 'sku'

initialSkus

If you want to load a particular sku that is different than the default sku that a configurator model would naturally load

colors?: {
    primary: IColor3;
    secondary: IColor3;
    dropShadow: IColor3;
};

Sets the primary color, secondary color, and drop shadow (used on certain buttons).

Secondary color is used for the pricing, as well as the gradient color on the main CTA

Many more color options can be set via css variables; see custom CSS section.

backgroundColor

Background color of the renderer only (not of the UI). Use any valid css string

backgroundColorOnScreenshots

Background color to use for screenshots; may be different than the normal background color

baseShareUrl

Ordinarily, for sharing, we share a link that points back to the current HTTP address of the page; override this to point to a custom page. Current URL search params are added to this url.

heading

Override the default camera heading in degrees, for 3d render type only

pitch

Override the default camera pitch in degrees, for 3d render type only

zoom

Override the default zoom, for 3d render type only

showStepNumber

By default, our UI does not show the step number next to steps; make this true to show step number

icons

{
    sif?: string;
    sifInverse?: string;
    bom?: string;
    bomInverse?: string;
    crm?: string;
    crmInverse?: string;
    atc?: string;
    atcInverse?: string;
    share?: string;
    shareInverse?: string;
    virtualAssistantButton?: string;
    missing?: string;
    paginationFirst?: string;
    paginationLast?: string;
    paginationRight?: string;
    paginationLeft?: string;
    blocked?: string;
    info?: string;
    back?: string;
    help?: string;
    sectionArrow?: string;
    close?: string;
    alert?: string;
    searchIcon?: string;
    chevronDown?: string;
    stepGroupArrow?: string;
}

maxFrameRate

    /** Max Frame Rate; the maximum frame rate for the renderer */
    maxFrameRate?: number;

renderQualityLevel

/** Quality Level; the desired quality level for the renderer, this locks to this value if provided
    0 (Low), 1 (Medium), 2 (High), 3 (Ultra) */
    renderQualityLevel?: QualityLevel;

Advanced Options, Plugins, and Callbacks

Plugins

There are number of different plugins available to override or add to Configurator.

Analytics: spinCommon.analyticsPlugin - Provide a custom analytics plugin; you would probably want to extends Kong3dSpinsAnalyticsPlugin or Kong2dSpinsAnalyticsPlugin depending on if it is a 2d or 3d render type.

All other plugins are passed in via spinCommon.plugins.

Plugins that are NOT provided by default:

  • KongPluginTypes.BOM - add a plugin that implements IConfiguratorBomPlugin and handles creating a bill of materials

  • KongPluginTypes.ATC - add a plugin that implements IConfiguratorAddToCartPlugin and handles adding to cart

  • KongPluginTypes.CRM - add a plugin that implements IConfiguratorCRMPlugin and handles doing CRM

  • PLUGIN_TYPE.CONFIG_PRICING - add a plugin that implements IConfiguratorPricingPlugin and handles doing CRM

Plugins that provide a default, but you may want to override:

  • RendererPluginType.SIF - add a plugin that extends SIFPlugin and provides custom behavior/SIF resolution

  • KongPluginTypes.HELP_ME_DECIDE - add a plugin that extends KongHelpMeDecidePlugin and provides custom UI for the help me decide modal

  • KongPluginTypes.OPTION_PAGE - add a plugin that extends OptionPagePlugin and provides custom UI for the options UI

  • KongPluginTypes.STEP_PAGE - add a plugin that extends StepPagePlugin and provides custom UI for the steps UI

  • KongPluginTypes.OPTION_POPOVER - add a plugin that extends OptionPopoverPlugin and provides custom UI for the tooltip on options

When creating a plugin, there is an id field that must be provided on the plugin (it is provided on all of our default plugins). If you want the same plugin to be used for every single configurator, use id = DEFAULT_PLUGIN_ID. If you want to use a different plugin for different configurators, then provide plugins with custom id fields, that match the plugin id field on the configurator model.

Changing Currently Loaded SKU programmatically

You can set the current SKU in the current configurator to load/show via this public function on the MxtKongfigurator class.

async setSkus(skus: string[], keepCameraAngle = false): Promise<void>

MxtKongfigurator.setSkus(...)

Functions for External Control of the Configurator

The IConfiguratorDataAPI interface exposes a simplified, read-only view of the configurator's current state. It is implemented by MxtKongfigurator and designed for programmatic (including AI) clients to query configurator data without needing to understand the full internal architecture.

Initializing MxtKongfigurator

Before you can use IConfiguratorDataAPI, you need to create and initialize an MxtKongfigurator instance.

Required Options

Property

Type

Description

spinCommon.apiKey

string

Your MXT API key

spinCommon.element

HTMLDivElement

The DOM element to render into (required if parentElements is not set)

assetEnvironment

MxtKongfigAssetEnvironment

One of: LATEST, TEST, STAGE, STAGING, PRODUCTION

Basic Initialization

import { MxtKongfigurator } from './kongfigurator/MxtKongfigurator';

import { MxtKongfigAssetEnvironment } from '@mxt/mxt-js-renderer-core/lib/configurable/model/MxtKongfigAssetEnvironment';

const parentElement = document.getElementById('configurator-container') as HTMLDivElement;

const configurator = new MxtKongfigurator({ spinCommon: { apiKey: 'YOUR_API_KEY', element: parentElement, }, assetEnvironment: MxtKongfigAssetEnvironment.PRODUCTION, initialSkus: ['SKU1', 'SKU2'], // optional: load specific SKUs on start configurationId: 'your-config-id', // optional: load a specific configuration });

await configurator.init();

Initialization with iframe Communication

When the configurator is hosted inside an iframe and you need the parent window to communicate with it via postMessage, pass an iframeCommunicator:

import { MxtKongfiguratorIFrameCommunicator } from './kongfigurator/ui/MxtKongfiguratorIFrameCommunicator';

const isInIframe = window.self !== window.top;

const configurator = new MxtKongfigurator({

spinCommon: {

apiKey: 'YOUR_API_KEY',

element: parentElement,

},

assetEnvironment: MxtKongfigAssetEnvironment.PRODUCTION, iframeCommunicator: isInIframe ? new MxtKongfiguratorIFrameCommunicator(targetOrigin) : undefined,

});

await configurator.init();

The targetOrigin should be the origin of the parent window (e.g., 'https://your-site.com'). When running in iframe context, this is typically read from a URL query parameter (targetOrigin), falling back to window.origin.

Lifecycle

// Create and initialize const configurator = new MxtKongfigurator(options);

await configurator.init();

// Use the Data API

const state = configurator.getConfiguratorState();

// Clean up when done

configurator.destroy();


Interface Definition

export interface IConfiguratorDataAPI {

getConfiguratorInfo(): MxtConfiguratorController;

getConfiguratorState(): {

[stepId: string]: {

selectedOptionId: string;

visible: boolean

}

};

getStepInfo(stepId: string): MxtConfiguratorStep;

getOptionInfo(stepId: string, optionId: string): MxtConfiguratorOption;

getAvailableSteps(): MxtConfiguratorStep[];

getAvailableOptions(stepId: string): MxtConfiguratorOption[];

}

MxtKongfigurator implements this interface directly, so all methods are available on any MxtKongfigurator instance after init() completes.


API Methods

getConfiguratorInfo

getConfiguratorInfo(): MxtConfiguratorController

Returns the full MxtConfiguratorController, which is the central controller managing all configurator state. Use this when you need access to the complete configurator model, current product, SKU information, or need to call controller methods like selectOption() or loadSKU().

Example:

const controller = configurator.getConfiguratorInfo();

// Access the current product

const product = controller.currentProduct;

// Access current SKUs

const skus = controller.currentSkus; // string[]

const sku = controller.currentSku; // combined string

// Access the full model

const allSteps = controller.model.steps;

getConfiguratorState

getConfiguratorState(): { [stepId: string]: { selectedOptionId: string; visible: boolean } }

Returns a serialized snapshot of the current configurator state as a map of step IDs to their current selection and visibility. This iterates over all steps (not just visible ones).

  • selectedOptionId can be undefined if the step is hidden or has no way to set a default due to current rules.

  • visible indicates whether the step is currently visible based on configurator rules.

Example:

const state = configurator.getConfiguratorState();

for (const [stepId, { selectedOptionId, visible }] of Object.entries(state)) {

console.log(`Step ${stepId}: selected=${selectedOptionId}, visible=${visible}`);

}

// Example output:

// Step color: selected=opt_red, visible=true

// Step size: selected=opt_large, visible=true

// Step accessory: selected=undefined, visible=false


getStepInfo

getStepInfo(stepId: string): MxtConfiguratorStep

Returns the full MxtConfiguratorStep object for a given step ID. Uses the model's internal stepMap for O(1) lookup.

Example:

const step = configurator.getStepInfo('color');

console.log(step.name); // "Color"

console.log(step.label); // Display label

console.log(step.options.length); // Number of options in this step

console.log(step.isVisible); // Base visibility flag

getOptionInfo

getOptionInfo(stepId: string, optionId: string): MxtConfiguratorOption

Returns the full MxtConfiguratorOption object for a specific option within a step. Internally calls getStepInfo(stepId) then looks up the option from the step's optionMap.

Example:

const option = configurator.getOptionInfo('color', 'opt_red');

console.log(option.name); // "Red"

console.log(option.label); // Display label

console.log(option.skuComponentCode); // SKU component code for this option

console.log(option.price); // Price value

console.log(option.image); // Thumbnail image URL


getAvailableSteps

getAvailableSteps(): MxtConfiguratorStep[]

Returns only the steps that are currently visible based on the configurator's rule engine. This delegates to the controller's getVisibleSteps() method.

Example:

const visibleSteps = configurator.getAvailableSteps();

for (const step of visibleSteps) {

console.log(`${step.id}: ${step.name}`);

}


getAvailableOptions

getAvailableOptions(stepId: string): MxtConfiguratorOption[]

Returns only the options that are currently visible for a given step, based on the configurator's rule engine. This delegates to the controller's getVisibleOptions() method.

Example:

const visibleOptions = configurator.getAvailableOptions('color');

for (const option of visibleOptions) {

console.log(`${option.id}: ${option.label} ($${option.price})`);

}


Using the Data API via iframe Messages

When the configurator runs inside an iframe, the parent window can access the Data API through postMessage. The MxtKongfiguratorIFrameCommunicator listens for incoming messages and responds with the corresponding data.

Message Protocol

Send a request from the parent window:

const iframe = document.getElementById('configurator-iframe');

iframe.contentWindow.postMessage(

{

type: 'MESSAGE_TYPE',

data: { /* optional parameters */ },

},

targetOrigin

);

Listen for the response in the parent window:

window.addEventListener('message', (event) => {

if (event.data.type === 'RESPONSE_TYPE') {

const result = event.data.data; // handle the result

}

});

Data API Message Types

Request type

Request data

Response type

Response data

'getConfiguratorInfo'

(none)

'getConfiguratorInfo'

MxtConfiguratorController

'getConfiguratorState'

(none)

'getConfiguratorState'

{ [stepId]: { selectedOptionId, visible } }

'getStepInfo'

{ stepId: string }

'getStepInfo'

MxtConfiguratorStep

'getOptionInfo'

{ stepId: string, optionId: string }

'getOptionInfo'

MxtConfiguratorOption

'getAvailableSteps'

(none)

'getAvailableOptions'

MxtConfiguratorStep[]

'getAvailableOptions'

{ stepId: string }

'getAvailableOptions'

MxtConfiguratorOption[]

Additional iframe Message Types

Beyond the Data API, the iframe communicator supports these operational messages:

Request type

Description

Response type

'screenshot'

Take a screenshot (optional: mimeType, color, horizontalAngle, verticalAngle, distance)

'screenshot'

'displayedSteps'

Get displayed/sorted steps

'displayedSteps'

'render-data'

Get render generation data (product, camera, sku, backgroundColor)

'render-data'

'start-bulk-sku-render'

Start bulk SKU rendering

'bulk-render-progress' / 'bulk-render-complete' / 'bulk-render-error'

'validate-sku'

Validate a SKU array ({ skus: string[] })

'validate-sku-response'

'allows-bulk-single-renders-request'

Check bulk render support

'allows-bulk-single-renders-response'

'update-init-options'

Merge partial MxtKongfiguratorOptions at runtime

(none)

// Parent window code

const iframe = document.getElementById('configurator-iframe');

const KONGFIG_ORIGIN = 'https://kongfigurator.example.com';

// Request the current configurator state iframe.contentWindow.postMessage({ type: 'getConfiguratorState' }, KONGFIG_ORIGIN);

// Request info about a specific step

iframe.contentWindow.postMessage( { type: 'getStepInfo', stepId: 'color', }, KONGFIG_ORIGIN );

// Request available options for a step iframe.contentWindow.postMessage( { type: 'getAvailableOptions', stepId: 'color', }, KONGFIG_ORIGIN );

// Listen for responses

window.addEventListener('message', (event) => {

if (event.origin !== KONGFIG_ORIGIN) return;

switch (event.data.type) {

case 'getConfiguratorState':

console.log('State:', event.data.data);

break;

case 'getStepInfo':

console.log('Step:', event.data.data);

break;

case 'getAvailableOptions':

console.log('Options:', event.data.data);

break;

}

});


Configurator Notifications

The MXT platform uses a global pub/sub system called NotificationCenter to broadcast configurator lifecycle events. The ConfiguratorMessageType enum defines typed notification names that fire when configurator state changes (option selected, step visibility changed, SKU calculated, etc.).

NotificationCenter API

NotificationCenter is a singleton imported directly from @mxt/mxt-services. It is not accessed via .Instance() -- you import and use it directly.

import { NotificationCenter } from '@mxt/mxt-services/lib/notifications/NotificationCenter';

Methods

Method

Signature

Description

subscribe

subscribe(notificationName: string, method: (arg: any) => void, once?: boolean): void

Subscribe a callback to a notification. Set once: true to auto-unsubscribe after the first call. If using a member function, use .bind(this).

unsubscribe

unsubscribe(notificationName: string, method: (arg: any) => void): void

Unsubscribe a callback. Must pass the same function reference used in subscribe.

post

post(notificationName: string, data?: Object): void

Post a notification to all subscribers. Data should be an object, not a primitive.

waitForOneNotification

waitForOneNotification(notificationName: string): Promise<any>

Returns a Promise that resolves the next time the notification fires (subscribes with once: true internally).

clearAll

clearAll(): void

Removes all subscribers for all notifications. Called internally by MxtKongfigurator.destroy().

Basic Usage

import { NotificationCenter } from '@mxt/mxt-services/lib/notifications/NotificationCenter';

import { ConfiguratorMessageType } from '@mxt/mxt-js-renderer-core/lib/configurable/interfaces/ConfiguratorNotifications';

// Subscribe to option selection changes

const onOptionSelected = (data) => {

console.log(`Step ${data.stepId}: ${data.prevOptionId} -> ${data.nextOptionId}`);

};

NotificationCenter.subscribe(ConfiguratorMessageType.AFTER_SELECT_OPTION, onOptionSelected); // Clean up when done

NotificationCenter.unsubscribe(ConfiguratorMessageType.AFTER_SELECT_OPTION, onOptionSelected);

Using once for One-Time Listeners

// Listen for the next SKU calculation only

NotificationCenter.subscribe(

ConfiguratorMessageType.AFTER_CALCULATE_SKU,

(data) => {

console.log(`New SKU: ${data.nextSku}`);

},

true // auto-unsubscribes after first call

);

// Or use the Promise-based version

const data = await NotificationCenter.waitForOneNotification(

ConfiguratorMessageType.AFTER_CALCULATE_SKU

);

console.log(`New SKU: ${data.nextSku}`);

Using with Class Methods

When subscribing with a class method, use .bind(this) and keep the bound reference for unsubscribing:

class MyComponent {

constructor() {

this.onOptionSelected = this.onOptionSelected.bind(this);

NotificationCenter.subscribe( ConfiguratorMessageType.AFTER_SELECT_OPTION, this.onOptionSelected );

}

onOptionSelected(data) {

console.log(`Selected: ${data.nextOptionId}`);

}

destroy() {

NotificationCenter.unsubscribe( ConfiguratorMessageType.AFTER_SELECT_OPTION, this.onOptionSelected );

}

}


ConfiguratorMessageType

All configurator lifecycle notifications follow a BEFORE_* / AFTER_* pattern. BEFORE_* fires before the state change is applied; AFTER_* fires after.

import { ConfiguratorMessageType } from '@mxt/mxt-js-renderer-core/lib/configurable/interfaces/ConfiguratorNotifications';

Enum Value

String

Description

BEFORE_SELECT_OPTION

"Configurator_Before_Select_Option"

Before an option is selected

AFTER_SELECT_OPTION

"Configurator_After_Select_Option"

After an option is selected

BEFORE_SET_SELECTED_OPTION

"Configurator_Before_Set_Selected_Option"

Before a selected option is set on the controller

AFTER_SET_SELECTED_OPTION

"Configurator_After_Set_Selected_Option"

After a selected option is set on the controller

BEFORE_SET_STEP_VISIBLE

"Configurator_Before_Set_Step_Visible"

Before step visibility changes

AFTER_SET_STEP_VISIBLE

"Configurator_After_Set_Step_Visible"

After step visibility changes

BEFORE_SET_STEP_ORDER

"Configurator_Before_Set_Step_Order"

Before step sort order changes

AFTER_SET_STEP_ORDER

"Configurator_After_Set_Step_Order"

After step sort order changes

BEFORE_SET_OPTION_OVERRIDE

"Configurator_Before_Set_Option_Override"

Before an option override (e.g. price) is applied

AFTER_SET_OPTION_OVERRIDE

"Configurator_After_Set_Option_Override"

After an option override is applied

BEFORE_SET_OPTION_VISIBLE

"Configurator_Before_Set_Option_Visible"

Before option visibility changes

AFTER_SET_OPTION_VISIBLE

"Configurator_After_Set_Option_Visible"

After option visibility changes

BEFORE_SET_OPTION_ORDER

"Configurator_Before_Set_Option_Order"

Before option sort order changes

AFTER_SET_OPTION_ORDER

"Configurator_After_Set_Option_Order"

After option sort order changes

BEFORE_SET_SELECTED_MESH

"Configurator_Before_Set_Selected_Mesh"

Before the selected mesh changes

AFTER_SET_SELECTED_MESH

"Configurator_After_Set_Selected_Mesh"

After the selected mesh changes

BEFORE_SET_SELECTED_MATERIAL

"Configurator_Before_Set_Selected_Material"

Before the selected material changes

AFTER_SET_SELECTED_MATERIAL

"Configurator_After_Set_Selected_Material"

After the selected material changes

BEFORE_SET_MATERIALS

"Configurator_Before_Set_Materials"

Before materials list changes

AFTER_SET_MATERIALS

"Configurator_After_Set_Materials"

After materials list changes

BEFORE_CALCULATE_SKU

"Configurator_Before_Calculate_SKU"

Before SKU recalculation

AFTER_CALCULATE_SKU

"Configurator_After_Calculate_SKU"

After SKU recalculation

BEFORE_LOAD_PRODUCT_ASSEMBLY

"Configurator_Before_Load_Product_Assembly"

Before a product assembly loads

AFTER_LOAD_PRODUCT_ASSEMBLY

"Configurator_After_Load_Product_Assembly"

After a product assembly loads

BEFORE_DESTROY

"Configurator_Before_Destroy"

Before the configurator is destroyed

AFTER_DESTROY

"Configurator_After_Destroy"

After the configurator is destroyed

BEFORE_SAVE_DEFAULT_PRODUCT_ASSEMBLY_IDS

"Configurator_Before_Save_Default_Product_Assembly_Ids"

Before default assembly IDs are saved

AFTER_SAVE_DEFAULT_PRODUCT_ASSEMBLY_IDS

"Configurator_After_Save_Default_Product_Assembly_Ids"

After default assembly IDs are saved

Notification Payloads

Each notification type carries a specific payload. The full type mapping is available via ConfiguratorNotificationPayloadMap.

Option Selection

Used by: BEFORE_SELECT_OPTION, AFTER_SELECT_OPTION, BEFORE_SET_SELECTED_OPTION, AFTER_SET_SELECTED_OPTION

interface ConfiguratorSelectOptionPayload {

stepId: string; prevOptionId: string; nextOptionId: string;

}

Step Visibility

Used by: BEFORE_SET_STEP_VISIBLE, AFTER_SET_STEP_VISIBLE

interface ConfiguratorStepVisiblePayload {

stepId: string; prevVisible: boolean | null; nextVisible: boolean;

}

Step Order

Used by: BEFORE_SET_STEP_ORDER, AFTER_SET_STEP_ORDER

interface ConfiguratorStepOrderPayload {

stepId: string; prevOrder: number | null; nextOrder: number;

}

Option Override

Used by: BEFORE_SET_OPTION_OVERRIDE, AFTER_SET_OPTION_OVERRIDE

interface ConfiguratorOptionOverridePayload {

stepId: string;

optionId: string;

prevOverride: MxtConfiguratorOverride | null;

nextOverride: MxtConfiguratorOverride;

}

// MxtConfiguratorOverride = { price?: number }

Option Visibility

Used by: BEFORE_SET_OPTION_VISIBLE, AFTER_SET_OPTION_VISIBLE

interface ConfiguratorOptionVisiblePayload {

stepId: string;

optionId: string;

prevVisible: MxtConfiguratorOptionVisibility | null; nextVisible: MxtConfiguratorOptionVisibility;

}

// MxtConfiguratorOptionVisibility: DO_NOT_SHOW = 0, VISIBLE = 1, UNAVAILABLE = 2

Option Order

Used by: BEFORE_SET_OPTION_ORDER, AFTER_SET_OPTION_ORDER

interface ConfiguratorOptionOrderPayload {

stepId: string;

optionId: string;

prevOrder: number | null;

nextOrder: number;

}

Mesh Selection

Used by: BEFORE_SET_SELECTED_MESH, AFTER_SET_SELECTED_MESH

interface ConfiguratorSelectedMeshPayload {

componentName: string;

prevMeshId: string | null;

nextMeshId: string | null;

}

Material Selection

Used by: BEFORE_SET_SELECTED_MATERIAL, AFTER_SET_SELECTED_MATERIAL

interface ConfiguratorSelectedMaterialPayload {

componentName: string;

prevMaterial: string | null;

nextMaterial: string;

}

Materials List

Used by: BEFORE_SET_MATERIALS, AFTER_SET_MATERIALS

interface ConfiguratorMaterialsPayload {

componentName: string;

prevMaterials: string[] | null;

nextMaterials: string[];

}

SKU Calculation

// BEFORE_CALCULATE_SKU interface ConfiguratorBeforeCalculateSkuPayload { prevSku: string | null; prevSkus: string[] | null; } // AFTER_CALCULATE_SKU interface ConfiguratorAfterCalculateSkuPayload { prevSku: string | null; prevSkus: string[] | null; nextSku: string; nextSkus: string[]; }

Product Assembly

// BEFORE_LOAD_PRODUCT_ASSEMBLY interface ConfiguratorBeforeLoadProductAssemblyPayload {

prevProductId: string | null;

}

// AFTER_LOAD_PRODUCT_ASSEMBLY interface

ConfiguratorAfterLoadProductAssemblyPayload {

prevProductId: string | null;

nextProductId: string | null;

}

Destroy

Used by: BEFORE_DESTROY, AFTER_DESTROY

interface ConfiguratorDestroyPayload {

prevProductId: string | null;

}

Save Default Assembly IDs

// BEFORE_SAVE_DEFAULT_PRODUCT_ASSEMBLY_IDS

interface ConfiguratorBeforeSaveDefaultAssemblyIdsPayload {

productId: string;

prevStepIds: string[] | null;

}

// AFTER_SAVE_DEFAULT_PRODUCT_ASSEMBLY_IDS

interface ConfiguratorAfterSaveDefaultAssemblyIdsPayload {

productId: string;

prevStepIds: string[] | null;

nextStepIds: string[];

}


Application-Level Notifications

In addition to the typed ConfiguratorMessageType notifications, the application posts several string-based notifications:

Notification Name

Payload

Description

'MxtKongfigurator_Config_Loaded'

MxtConfiguratorFile

Fired after a configuration file is loaded

'ConfiguratorSectionExpand'

{ section }

Fired when a configurator section expands

'HotspotLinkCallback'

{ step: MxtConfiguratorStep, hotspot: KongHotspot }

Fired when a hotspot link is clicked

Example -- listening for config load:

const onConfigLoaded = (configFile) => {

console.log('Configuration loaded:', configFile.id);

};

NotificationCenter.subscribe('MxtKongfigurator_Config_Loaded', onConfigLoaded);

// Clean up

NotificationCenter.unsubscribe('MxtKongfigurator_Config_Loaded', onConfigLoaded);


Key Types Reference

MxtConfiguratorStep

Property

Type

Description

id

string

Unique step identifier

name

string

Step name

label

string

Display label

isVisible

boolean

Base visibility flag

displayType

StepDisplayTypes

How the step is displayed in the UI

image

string

Step thumbnail image URL

camera

MxtConfiguratorCamera

Camera settings for this step

options

MxtConfiguratorOption[]

All options in this step

optionMap

Map<string, MxtConfiguratorOption>

O(1) lookup map for options by ID

skuComponentOrder

number

Order of this step's component in the SKU

filters

MxtConfiguratorFilter[]

Filters applicable to this step

help

MxtConfiguratorHelp

Help content for this step

properties

MxtConfiguratorOptionProperty[]

Custom properties

propertiesMap

Map<string, MxtConfiguratorOptionProperty>

Property lookup map

hotspots

KongHotspot[]

Hotspot definitions

MxtConfiguratorOption

Property

Type

Description

id

string

Unique option identifier

name

string

Option name

label

string

Display label

skuComponentCode

string

SKU component code for this option

price

number

Price value

image

string

Thumbnail image URL

components

MxtRenderComponent[]

Render components

filters

MxtConfiguratorFilterData[]

Filter data

tooltipHeader

string

Tooltip header text

tooltipBody

string

Tooltip body text

helpImage

string

Help image URL

helpLabel

string

Help label

properties

MxtConfiguratorOptionProperty[]

Custom properties

propertiesMap

Map<string, MxtConfiguratorOptionProperty>

Property lookup map

MxtConfiguratorController (key members)

callbacks?: {
    /** Allow for overriding of the error handling. Return false to prevent our default error handling, return true to continue our normal error handling */
    onError?: (e: PromiseRejectionEvent) => boolean;
};

By default, we handle errors by presenting an error modal to the user. If you want custom behavior, then override this method. To prevent our default modal, make sure you return false from the callback.

Custom Expand/Collapse

spinCommon: {
    expandButton?: {
        onExpand?: () => void;
        onCollapse?: () => void;
    };
},

The picker (if present) will automatically be hidden onExpand and restored onCollapse. However, if you want to take additional action on expand/collapse, hook into these callbacks

Components

Default Layout

By default, the configurator builds out all of the UI in the format below underneath the HTML element provided in the options:

However, we provide the ability for each UI components to be parented independently to best provide the needs for your custom UI. The list of components are:

Component Type

Component Typescript Class

Component CSS Class

Notes

CombinedComponentType.PICKER_CONTAINER

PickerContainerComponent

.mxt-canvas-picker

Contains the UI for picking steps/options, as well as the header/sku/pricing/etc (by default). Basically everything that isn’t the renderer

CombinedComponentType.VIEWER_CONTAINER

ViewerContainerComponent

.mxt-configurator-viewer

The container for the renderer. Contains both the renderer itself and the button bar for the renderer.

CombinedComponentType.PICKER_SCROLLABLE

PickerScrollableComponent

.mxt-configurator-scrollable

The scrollable section of the picker; see diagram above, depending on device contains different things.

CombinedComponentType.MODALS

ModalComponent

.mxt-modal-container

Container for all modals; by default overlays both the picker container and viewer container

CombinedComponentType.VIEWER

ViewerComponent

.mxt-canvas-container

Contains the actual renderer.

CombinedComponentType.BUTTON_BAR

ButtonBarComponent

.mxt-spin-button-row

Buttons for manipulating renderer (zoom/rotate/etc)

CombinedComponentType.WEB_AR

WebArComponent

.mxt-webAr-container

Button to trigger WebAR

CombinedComponentType.ABOUT

AboutComponent

.mxt-about-button

Button to trigger About modal

CombinedComponentType.DOWNLOAD

DownloadButtonComponent

.mxt-btn-download

Download screenshot button on button bar

CombinedComponentType.DIMENSIONS

DimensionsButtonComponent

.mxt-btn-dimensions

Toggle dimensions button on button bar

CombinedComponentType.HOTSPOTS

HotspotButtonComponent

.mxt-btn-hotspot

Toggle hotspots button on button bar

CombinedComponentType.PRESET_VIEW

PresetViewButtonComponent

.mxt-btn-preset-view

Show preset view modal button on button bar

CombinedComponentType.EXPAND_BUTTON

ExpandButtonComponent

.mxt-btn-expand

Expand/collapse renderer view

CombinedComponentType.STEPS

StepsComponent

.mxt-configurator-steps

Container to show steps; uses StepPagePlugin to build UI within it

CombinedComponentType.OPTIONS

OptionsComponent

.mxt-configurator-options

Container to show options; uses OptionPagePlugin to build UI within it

CombinedComponentType.HEADER

HeaderComponent

.mxt-configurator-header

Header label (name of configurator)

CombinedComponentType.SUBHEADER

SubheaderComponent

.mxt-configurator-subheader

Subheader label

CombinedComponentType.SKU

HeaderSkuComponent

.mxt-configurator-header-sku

Sku label

CombinedComponentType.PRICING

PricingComponent

.mxt-configurator-total-pricing

Pricing label

CombinedComponentType.CTAS

CTAContainerComponent

.mxt-configurator-ctas

CTA container

CombinedComponentType.CTA_SHARE

ShareComponent

.mxt-configurator-cta-share

Share button, only shows if enabled for configurator model

CombinedComponentType.CTA_ATC

ATCComponent

.mxt-configurator-cta-atc

Add to cart button, only shows if there is an Add to cart plugin

CombinedComponentType.CTA_SIF

SIFComponent

.mxt-configurator-cta-sif

SIF button, only shows if sif is enabled in app config

CombinedComponentType.CTA_CRM

CRMComponent

.mxt-configurator-cta-crm

CRM button, only shows if there is a crm plugin

CombinedComponentType.CTA_BOM

BOMComponent

.mxt-configurator-cta-bom

BOM button, only shows if there is a bom plugin

Components Diagram 1

Components Diagram 2

Customizing Component Locations

There is an option parentElements. This allows you to provide a different parent element for any given component type. You do not need to provide a parent element for each; you can pick and choose which ones you need to customize. For example, if you have your own section you want to put your CTAs, you could just provide:

parentElements: {
  ctas?: HTMLElement;
}

It is possible to provide custom parents for everything. However, a much more common use case is to just re-parent several smaller components (such as CTA_SHARE or WEB_AR). In that case, use both the spinCommon.element option to set the main parent over everything, and just define the parentElements that would not fall in their default location.

IF YOU DO NOT PROVIDE spinCommon.element (for example if you need to provide different parents for the picker container component and the viewer container component), then we will not create a root element to house everything else. This is a totally valid case, but If a root is not created, we cannot always automatically handle resize events. There are many edge cases where your parent elements may have been configured in a way that a resize event on one effects the size of the other. As a result, we turn off handling landscape vs portrait mode automatically. IF you believe you have a fairly standard setup, you may turn resizing back on via the option autoResizeAllParents.

Component parents may be updated at runtime via

  updateParentElement(key: string | SpinsComponentType | KongComponentType, newParent: HTMLElement, removeOldParent?: boolean): void {

or

  updateParentElements(newParentElements: MxtKongParentComponentOptions, removeOldParents?: Boolean): void {

Disabling Components

Components may be disabled via the option disabledComponents. It is possible to provide non-sensical situations, such as disabling the CTA container but not disabling the CTAs within it. An exception will be thrown in these cases.

In order to disable all picker components (for example if you are building the UI yourself and just using our MxtKongfigurator for the renderer), use the option disableAllPickerComponents.