Table of Contents

Integrating the VividWorks 3D Configurator

The VividWorks 3D Configurator is an embedded application meant to run inside other websites. Our main target are e-commerce sites so we do not have for example pricing in our application. We instead trust the e-commerce system to have pricing and add-to-cart functionalities. We also trust the e-commerce site to have SKUs set for products and their parts to support pricing and add-to-cart.

From this background we could say that the integration has two main aspects or phases to it:

  1. Preparing your site / e-commerce system to make sure it has the necessary data and functionalities.
  2. Embedding the Planner (which is the 3D product configurator) on a web site. Read more about embedding.

Preparing your e-commerce system

The "behind the scenes" part of integrating VividWorks 3D product configurator, supporting it with pricing and other features, can be simple or complex depending on the use-case. In the simplest case, where pricing and shopping cart are not necessary, all that is needed is the actual embed code described in the next section.

With pricing and shopping cart you may need to do a bit more work. The practical side is explained in the embedding section so here we will discuss what should be taken into consideration when planning the integration. Do consider at least the following:

Unfortunately we cannot give full example implementations as all systems and platforms are very different from each other.

How and where to show our embedded Planner

Embedding the planner is easy but for sites that have multiple products it may get more complicated. Consider adding meta data to the products that defines whether they have a VividWorks 3D product configurator associated and / or visible, and to which VividWorks product configuration they relate to.

Associating e-commerce products to VividWorks product logic works by using two ID strings that we will provide to you, or which you can find in our Manager back-end site. The two main IDs are Library ID and Product ID which together single out a product configuration logic in our platform. Our recommendation is to use these two IDs in your meta data to define the product configurator availability.

While our script tag has to be available on pretty much all pages of the shop front site, showing the actual Planner only requires adding a simple <div> tag exactly where the Planner is to be shown. This could be a separate page within the site or for example the product detail page. Just remember to only have one Planner embed per page.

SKUs and product parts

Our assumption is that products, and their various parts and options, have SKUs or other identifying codes defined in the e-commerce site. These codes are the main integration data when talking about pricing and shopping cart. Product configurations and their parts translate to SKUs, which in turn are used to add the said configurations to the cart, or query for price information.

For this topic we can divide products into two different camps: modular products with multiple separate parts, and simple one-piece products. For the simple products this is usually very easy in mostly all e-commerce systems. You would define the various variants and options for the product and then define the SKU for each variation.

The modular products may be more complicated to get set-up and this is still something fairly new in the e-commerce world. The most pragmatic approach could be to have the product itself set up as a product entity in the e-commerce backend and use that as what we could call a "container product". The various modules or parts of the product could then also be defined as product entities but hidden from the shop front UI by placing them into hidden categories. Now you could define their variants and options just like for the simple one-piece products and give them SKUs.

Remember that these codes, or SKUs, need to match to what you configure for the product in our Manager backend and / or communicate to VividWorks if the product logic is to be done by us.

APIs for pricing and the cart

Mostly the e-commerce platforms and systems have pretty good APIs built in out of the box, but sometimes you may need to do additional work. This additional work may include for example creating back-end functions / APIs or combining data available from existing APIs.

The two most important requirements are these:

  1. To be able to add products to the cart with SKUs and amounts.
  2. To be able to query prices for a list of SKUs.

For both of the above uses we send the shop front the same data model that boils down to SKUs and their respective amounts. See the following examples for adding to cart and price queries.

Embedding VividWorks planner

Embedding our planner on any website or web technologies based application out there is as simple as including one JavaScript file (called the Embed Tag) and one HTML tag with a few attributes. The code required to embed and run the planner will downloaded through the Embed Tag script. Our embedding is currently based on the iFrame and a separate embedding tag because of a couple reasons:

  • There will be no collisions between the technology you use on the hosting site and what we use for the planner. The planner is effectively sandboxed in its own context.
  • Style sheets are also sandboxed so the systems cannot interfere with each other
  • We can provide a single front-end API for communication between the systems
  • We can roll out fixes and new versions without you, the customer, having to do anything.

We are also actively looking out for alternative and arguably newer technologies such as the Web Components / Shadow DOM but as things stand now the iFrame is still the winner.

The principal use-case scenario of our embedded planner is to provide a product configurator for Product Detail Pages or similar contexts. Only one planner instance per page is supported. A product configurator in itself is a relatively involved experience for a user so we'd rather the user can focus on that. There is of course also the fact that the more 3D scenes there are on the screen or page, the more intensive it is for the users computer or device.

Note

Only one planner instance per page is supported

The Embed Tags

So, how does it work now? You need to have two HTML tags on your website.

  1. <script>...</script> tag that loads the planner runtime code
  2. <div>...</div> tag that places the planner on a webpage Note: you can only place one div tag (=planner instance) per webapge

The <script> tag

All the pages that will have our planner embedded need to have the following script tag somewhere in their markup, preferably on the bottom just before the ending </body> tag:

<script type="module">
    import vw3d from 'https://app.vividworks.com/embed/vividworks-frontend-embed.es.js';
    vw3d({}).
    then(resp => window.vw3d = resp);
</script>

This script tag downloads the 3D configurator javascript bundle that will handle the actual embedding and API communication.

The important part of this embedding script is the module vw3d that is run when the script tag is evaluated. This module accepts a JavaScript object as its only parameter to pass settings to our system. Currently the following settings are supported.

Name Type Default Description
addToBasketCallback function(data:object) => Promise null This setting parameter tells us that there is shopping cart integration. If the setting is defined then we will show an "Add to cart" button.

The funtion should accept one parameter. The data passed to this parameter will be the sales data and parts that the user has in their 3D plan. This data should then be used by the hosting website implementor to actually integrate to the shopping cart.

See the next section for details about the sales data format.
getPricesCallback function(data:object) => Promise null A setting telling VividWorks configurator to get price information from the embedding site / web shop. The function should return a JavaScript Promise that when resolved will return a list of price information objects.

The funtion should accept one parameter. The data passed to this parameter will be the sales data and parts that the user has in their 3D plan. This data should then be used by the hosting website implementor to actually integrate to the shopping cart.

See the next section for details about the sales data format.
mapSalesCodesCallback function(data:object) => Promise null Optional callback for mapping sales codes / SKUs to custom codes. The main use-case for this callback are sites that use different sales codes than the original ones used to configure the product. The assumption here is that the codes can be mapped one-to-one.
culture string null A language and region coded based on the RFC 4646 standard, which is composed of a two-letter language code and a two letter country / region code. For example "fi-FI" for Finnish or "en-US" for US english. When provided this language setting is used for the configurator language if the localizations are available.
taxesEnabled boolean null If this settings is present with true or false values,it will display in planner (below the price) and in pdf report, the "taxes included" or "taxes excluded" corresponding translations. The translations can be found in the translation view - planner tab:('including_taxes' and 'excluding_taxes' keys). In case the settings is not present at all,no text will be displayed below the price.
uploadThumbnail boolean null Enables the saving of the composition screenshot.
unitSystem string 'metric' The unit system used to display the measurements. Possible values: "metric", "imperial"
unitLength string 'mm' The unit length used to display the measurements. Depends on the unitSystem settings: For 'metric' the possible values are : "mm", "cm", "m", "km". For 'imperial' the possible values are : "in", "ft", "yd", "mi".

The SalesData object

The SalesData object includes all sorts of detailed information about the user's plan, big part of which is not necessarily useful for the integration purposes. Below is a stripped down example of the data, showing the most important parts:

{
    "id": "e5bf0f5e-1300-4517-87a3-6ac63e29723b",
    "compositions": [
        {
            "id": "e8e9a458-5ea4-4288-b1e1-a1c4e86d802f",
            "name": "Sample with Linear Structure",
            "totals": [
                {
                    "code": "LEG-ROUND",
                    "amount": 6
                },
                {
                    "code": "S1LYL01",
                    "amount": 1
                },
                {
                    "code": "S2LYL01",
                    "amount": 1
                },
                {
                    "code": "C30LYL01",
                    "amount": 1
                }
            ],
            "properties": {},
            "features": {},
            "tags": [],
            "modules": [],
            "materials": [],
            "position": [],
            "rotation": []
        }
    ],
    "readOnlyPlan": "3f64be26-5117-4498-91c6-41a80d08fe0c",
    "readOnlyLink": "https://app-dev.vividworks.com/?lib=77377983-39a6-4a0a-b2f7-87df2e4af06d&prod=cd243979-7a2b-4b25-b219-84143d80975a&vw-plan=3f64be26-5117-4498-91c6-41a80d08fe0c",
    "shareLink": "https://transparentsofas.com/share/embed.html?vw-plan=3f64be26-5117-4498-91c6-41a80d08fe0c"
}

This JSON object represents the plan the user is working on. Let's go through the structure level by level:

  • On the first level of the object there are two items: id which is the Plan ID, and compositions which is an array of product compositions in the plan. Currently there will always be only one composition.

  • The composition objects have the following items that important for the integration: id, name, totals. On top of the previous there are also other items such as: properties, features, tags, modules, materials, position, rotation.

  • The composition id and name should be quite self explanatory, one is the unique identification string and the other is its name.

  • The totals item is an array of SKU items and their total amount in the plan. This is the most important piece of data for integration purposes. Each object in the Totals array has code and amount items (and properties item when IntegrationDataProperties is being used). The code is most likely the SKU or other similar code. The amount is the total amount of that SKU / code in the composition. The properties appear in the Totals array only when IntegrationDataProperties are present. More about the summarization change in Integration Data used in properties.

  • The modules item is an array of modules in the plan and their details. See more about it in Modules section below.

  • The last three fields refer to the readonly plan used used in the cart. When using "Add to cart" or pressing "Summary" if the current plan is not already locked, a new read only (locked) plan will be created out of the current one.

    1. readOnlyPlan - The read only plan ID: Serves as a unique identifier for a specific plan within the system. It is essential for referencing and accessing the plan's data, particularly in scenarios like sales transactions and data retrieval. Immutability is a key characteristic of a read-only plan, meaning that the plan cannot be modified or altered in any way once it has been created. This ensures that the data within the plan remains unchanged and reliable for reference purposes. Immutable read-only plans provide a stable reference point for various operations, such as verifying the contents of a plan at a particular point in time or sharing the plan's data securely.

    2. readOnlyLink - Internal link: The share link provides access to read-only data of a specific plan. Mostly used internally. It is created and passed as part of the sales data over the embed API. The share link allows users to view the plan but not make any edits to it. It serves as a reference point for verifying the contents of the plan at the time of sharing. This is available even after the public link is broken (due to web shop side page not existing anymore etc.) Example: https://app.vividworks.com?lib=&prod=&vw-plan=

    3. shareLink - Public share link: The public share link is a specific type of share link intended for integration with web shops. It allows the web shop to display or send the link to their customers. The public share link follows a specific format containing the web shop product page address with a query parameter for loading the static plan. When loaded in a browser, the user is directed back to the web shop where the read-only plan loads. This link can be used for bundled shopping cart items as well. It can be shared to end users and can show prices. The link is in same format as used in summary page QR code. Same QR code is present also in the pdf report. Example: https://transparentsofas.com/products/build-your-dream-sofa/?vw-plan=

The hosting website implementor should be able to use this data to calculate total price and other necessary information, and integrate to shopping cart features of their system.

Modules

Modules array (compositions[0].modules) contains listing of root level modules that have been configured to the composition by the planner user. Modules correspond to root level Part's from Manger app.

For each module there are following details available:

  • codes: SKU(s) for the module (one of the SKU's from the compositions[0].totals)
  • totals: Similar totals summarization as in compositions[0].totals, but per module level, so includes SKU of the current module as well as any accessory (sub module) SKU's (e.g. legs of a sofa module)
  • index: This is index of the module, especially when configured to a linear structure, in left to right order. Index starts from zero.
  • name: Name of a module as defined in Manager app
  • key: Localization key matching to localizations as defined in the Manager app. thumbnail: Thumbnail of a module as defined in the Manager app (same thumbnail is also used in Planner application's summary view)
  • tags: Tags defined in Manager app for the module, but also includes default tag role:module for all the modules.
  • accessories: Array listing all the accessories associated with current module. See more details from Accessories section below.
  • materials: Array listing all the materials associated with current module. See more details from Materials section below.
  • measures: Measurements of the module (in meters). These are measurements of the 3D model unless explicitly overwritten in Manager app.

Accessories

Accessories (compositions[0].modules[].accessories[]) array items have following details available:

  • name: Name of an accessory as defined in Manager app
  • key: Localization key matching to localizations as defined in the Manager app.
  • thumbnail: Thumbnail of an accessory as defined in the Manager app (same thumbnail is also used in Planner application's summary view and menu view)
  • tags: Tags defined in Manager app for the accessory, but also includes default tag role:accessory for all the accessories.Can also include list: for the item list configured in Manager app as a container for the accessories.
  • measures: Measurements of the accessory (in meters). These are measurements of the 3D model unless explicitly overwritten in Manager app.
  • codes: SKU(s) for the accessory (one of the SKU's from the compositions[0].totals), if configured for the accessory
  • totals: Similar totals summarization as in compositions[0].totals, but per accessory level, so includes SKU of the current accessory as well as any child accessories' SKU's
  • materials: If accessories have materials configured to them there should be an array of materials here. See more details from below.

Example of accessories array for a module:

"accessories": [
    {
        "feature": "Leg_front",
        "name": "Leg_round",
        "thumbnail": "https://assets-dev.vividworks.com/productlibrarydata/c3de699e-5eb8-4c37-bdab-2aea83a81285/leg10.png",
        "alternatives": 3,
        "key": "c36c5ee6-44e1-405f-8c41-f808c8af8969-Leg_round",
        "codes": [
            {
                "code": "L01",
                "amount": 1
            }
        ],
        "totals": [
            {
                "code": "L01",
                "amount": 1
            }
        ],
        "tags": [
            "role:accessory",
            "list:StructureLegTypes"
        ],
        "measures": [
            0.05,
            0.1,
            0.05
        ],
        "showMeasures": false
    },
    {
        "feature": "Leg_back",
        "name": "Leg_round",
        "thumbnail": "https://assets-dev.vividworks.com/productlibrarydata/c3de699e-5eb8-4c37-bdab-2aea83a81285/leg10.png",
        "alternatives": 3,
        "key": "c36c5ee6-44e1-405f-8c41-f808c8af8969-Leg_round",
        "codes": [
            {
                "code": "L01",
                "amount": 1
            }
        ],
        "totals": [
            {
                "code": "L01",
                "amount": 1
            }
        ],
        "tags": [
            "role:accessory",
            "list:StructureLegTypes"
        ],
        "measures": [
            0.05,
            0.1,
            0.05
        ],
        "showMeasures": false
    }
],

Materials

Materials (compositions[0].modules[].materials[]) array for materials used for the module (or accessory) have the following details available:

  • name: Name of a material as defined in Manager app
  • key: Localization key matching to localizations as defined in the Manager app.
  • thumbnail: Thumbnail of a material as defined in the Manager app (same thumbnail is also used in Planner application's summary view and menu view)
  • tags: Tags defined in Manager app for the accessory, but also includes default tag role:material for all the accessories. Can also include list:<ItemListName> for the item list configured in Manager app as a container for the materials.

Example of materials array for a module:

"materials": [
    {
        "feature": "ImplicitSlot",
        "name": "Leather Yellow",
        "thumbnail": "https://assets-dev.vividworks.com/productlibrarydata/e642815c-3aba-4468-865e-81044f2dca34/leather_yellow_thumb.jpg",
        "alternatives": 8,
        "key": "a4a16053-c6fe-4210-8bce-f0d0f8a3c4c6-Leather Yellow",
        "tags": [
            "role:material",
            "list:Materials"
        ],
        "showMeasures": false
    }
],

Integration Data used in properties

The composition properties might include usage of IntegrationDataProperties propertyset. This changes the summarization to totals as well. If items have the same SKU and the same IntegrationDataProperties, they are totaled together. If items have same SKU, but different IntegrationDataProperties, they are separate.
Example of how this changes the SalesData json, especially totals:

{
    "id": "aac7f8ef-f3f7-45fe-b53a-0946d24de22d",
    "compositions": [
        {
            "name": "Linear Structure with integration data",
            "totals": [
                {
                    "code": "A01",
                    "amount": 1,
                    "properties": {
                        "Material": "Fabric Petrol"
                    }
                },
                {
                    "code": "A02",
                    "amount": 2,
                    "properties": {
                        "Material": "Leather Red"
                    }
                }
            ],
            "properties": {},
            "features": {},
            "tags": [],
            "modules": [],
            "materials": [],
            "position": [],
            "rotation": []
        }
    ],
    "readOnlyPlan": "aac7f8ef-f3f7-45fe-b53a-0946d24de22d",
    "readOnlyLink": "https://app-dev.vividworks.com/?lib=03401849-3e2d-483d-9ec7-493287707e0f&prod=411de54e-846c-4161-9e9a-8472fc2a335d&vw-plan=aac7f8ef-f3f7-45fe-b53a-0946d24de22d",
    "shareLink": "http://localhost:8000/embed-test.html?vw-plan=aac7f8ef-f3f7-45fe-b53a-0946d24de22d"
}

Cart integration

To add products to the cart from our Sales Data the e-commerce shop front needs to be able to transform our data to whatever necessary format and call the right APIs or functions.

To define the cart integration please provide our embed script settings a property called addToBasketCallback, which should return a JavaScript promise. Defining this setting tells our Planner that the site has a shopping cart integration and thus we can show the add-to-cart button.

Here's a simple example:

<script>
    // Somewhere in your scripts..
    function add_to_cart(bom) {
        return new Promise((resolve, reject) => {
            if (bom === undefined 
                || bom.compositions === undefined
                || !Array.isArray(bom.compositions)
                || !bom.compositions.length) {
                reject("Empty configuration");
                return;
            }

            // Get read-only plan and shareable links
            const readOnlyLink = bom.readOnlyLink || "";
		    const shareLink = bom.shareLink || "";

            // Transform the data format
            const items = bom.compositions[0].totals.map(t => {
              return {
                sku: t.code,
                quantity: t.amount,
                ...t.properties && { t.properties }, // Add extra properties
                ...readOnlyLink && { readOnlyLink }, // Add read-only link
                ...shareLink && { shareLink },       // Add share link
              };
            });

            fetch('https://api.example.com/add_to_cart', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(items),
            })
            .then((response) => {
                if (response.ok) {
                    resolve();
                }
                else {
                    reject("Error adding to cart");
                }
            })
            .catch((error) => {
                reject("Error adding to cart: "+error);
            });
        });
    };
</script>

<script type="module">
    // Now we will use the above code in the embed script
    import vw3d from 'https://app.vividworks.com/embed/vividworks-frontend-embed.es.js';
    vw3d({
        "addToBasketCallback": add_to_cart
    }).
    then(resp => window.vw3d = resp);
</script>

Price data integration

For price integration the hosting web site / web shop needs to be able to process a list of SKUs and provide price information for those in a certain format. To trigger price integration, provide the getPricesCallback callback for the embed script settings as explained in before in the document.

The format for the price data to be provided is a list of JavaScript objects, as follows:

[
    {
        "applicationid": "",     // string, can / should be left empty
        "currency": "EUR",       // string, three letter currency code, for example "EUR"
        "country": "FI",         // string, two letter country code, for example "FI"
        "sku": "SKU-CODE",       // string, the SKU for which this price applies
        "value": 125.50,         // number, the price exluding eventual VAT
        "vat": 24,               // number, Value Added Tax added to the price in percentage
    }
]

Here's a somewhat complete example of the embed with price integration, assuming the example API will return data in the format shown above:

<script>
    // Somewhere in your scripts..
    function VW_get_prices(bom) {
        return new Promise((resolve, reject) => {
            if (bom === undefined 
                || bom.compositions === undefined
                || !Array.isArray(bom.compositions)
                || !bom.compositions.length) {
                reject("Empty configuration");
                return;
            }

            fetch('https://api.example.com/get_prices_for_skus', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify(bom),
            })
            .then(response => response.json())
            .then((priceData) => {
                if ( ! priceData ) {
                    resolve([]);
                    return;
                }
                resolve(priceData);
            })
            .catch((error) => {
                reject("Error in price query: "+error);
            });
        });
    };
</script>

<script type="module">
    // Now we will use the above code in the embed script
    import vw3d from 'https://app.vividworks.com/embed/vividworks-frontend-embed.es.js';
    vw3d({
        "getPricesCallback": VW_get_prices
    }).
    then(resp => window.vw3d = resp);
</script>

In the above example we used an HTTP request to the back-end but you might as well use already available data in the front-end if that makes more sense.

Customizing SKU handling

There may be cases where the embedding web shop uses different sales codes (SKUs) than the manufacturer or what have been set in our configurator. In these cases we advice the web shop / site owner to do a mapping of the codes on the fly.

When for example our configurator calls the addToBasketCallback or getPricesCallback our default SalesData object with the default SKUs is provided. Before sending the data to the back-end systems, or handling it in any way, the data could be transformed, mapping to custom sales codes and back.

To map and change the SKUs for the BOM view in the planner, the hosting website should define mapSalesCodesCallback callback function for the embed script settings. This callback should return a promise that resolves to a JavaScript object with the original SKU as key and the new SKU as value. Consider this object as a dictionary, with unique keys.

{
    "abc-123": "cba-321",
    "123-a": "123-b",
}

Here's a simple example of how to define the callback:

<script>

    // Somewhere in your scripts..
    // For the sake of simplicity we here just use a "dictionary" here.
    // You could of course call a back-end if necessary
    const skuMap = {
        "abc-123": "cba-321",
        "123-a": "123-b",
    };
    function VW_map_skus(bom) {
        return new Promise((resolve, reject) => {
            if (bom === undefined 
                || bom.compositions === undefined
                || !Array.isArray(bom.compositions)
                || !bom.compositions.length) {
                reject("Empty configuration");
                return;
            }

            // Get a list of all SKUs in the configuration
            let composition = bom.compositions[0]
            let codes = composition.totals.map(a => a.code);

            if (!!codes.length) {
                // You may want to filter the SKU map to
                // only those keys that are needed for this BOM
                let filteredMap = Object.fromEntries(Object.entries(skuMap)
                    .filter(([key]) => codes.includes(key)));
                resolve(filteredMap);
            }
            
            // Silent fail, just return an empty map
            resolve({});
        });
    };
</script>

<script type="module">
    // Now we will use the above code in the embed script
    import vw3d from 'https://app.vividworks.com/embed/vividworks-frontend-embed.es.js';
    vw3d({
        "mapSalesCodesCallback": VW_map_skus
    }).
    then(resp => window.vw3d = resp);
</script>

Setting the language

To set the language used in our Planner you need to have a culture code in ISO 639-1 / ISO 3166-1 standard format. We use the format with dash (-) as a separator so for example US English would be expressed as en-US and Swedish as sv-SE.

You would then pass this code to us through the Planner settings object discussed above. Here's a simple example setting the language to swedish.

<script type="module">
    // Now we will use the above code in the embed script
    import vw3d from 'https://app.vividworks.com/embed/vividworks-frontend-embed.es.js';
    vw3d({
        "culture": "sv-SE"
    }).
    then(resp => window.vw3d = resp);
</script>

Also remember that you need to have the language defined and localized in our back-end (the Manager site).

Setting the unit system

The unit system settings are used to display the measure units in the measure sticks used to display dimensions in the 3D views. To set the unit system used in our Planner you need to add two settings: the unit system and the unit legth. They both need to be set. See the unitSystem and unitLength described in the chapter: "The script tag".

For example settings for having a metric system displayed in centimeters:

<script type="module">
    // Now we will use the above code in the embed script
    import vw3d from 'https://app.vividworks.com/embed/vividworks-frontend-embed.es.js';
    vw3d({
         "unitSystem": "metric", "unitLength": "cm"
    }).
    then(resp => window.vw3d = resp);
</script>

Placing the planner on the page using the <div> tag

Note

Only one planner instance (one div tag) per page is supported

After the Embed Tag is place, to insert the planner on a web page you will need to include a simple HTML <div> tag. The tag will be filled with the embedded 3D planner on page load. The proper tag for each product can be retrieved from our Management UI, but here is an example tag:

<div class="vw3d" 
    data-vw-library="ba8bb7db-4b31-4afb-a4bd-e647a5a9216f"
    data-vw-product="5b8591c2-ed80-437b-990c-ce102120a6e6">
</div>

The above tag would embed the planner for product with ID 5b8591c2-ed80-437b-990c-ce102120a6e6 from a product library with ID ba8bb7db-4b31-4afb-a4bd-e647a5a9216f. To embed a specific pre-built composition of a product you can add another attribute called data-vw-composition. Otherwise the products default composition is rendered, or an empty planner, or the plan the user was previously working on. Here's a complete example of embedding a specific composition of a product.

<div class="vw3d" 
    data-vw-library="ba8bb7db-4b31-4afb-a4bd-e647a5a9216f"
    data-vw-product="5b8591c2-ed80-437b-990c-ce102120a6e6"
    data-vw-composition="c1eedefa-3ae2-4249-95fb-4d6cb7b1e269">
</div>
DIV Parameter Optionality Description
data-vw-library Mandatory Product Library ID from Management UI used to map what is shown on the website
data-vw-product Mandatory The Product ID from the Management UI used to map what is shown on the website
data-vw-composition Optional Pre-built Component ID that will be used as a default. This overrides the Management UI default configured for the Product Root Properties
data-vw-language Optional Used to guide the planner to using specific locale and language for the texts. Maps directly to all localized data elements on the Management UI eg. "fi_FI", "da_DK" etc

The sizing and styling of the embedded planner is handled completely by our embedding. The planner will use all available horizontal space available to it in its container element. You can however add any number of wrapping elements around the vw3d element and apply CSS as you wish to limit or provide specific space for the planner.