Skip to main content

CMS Integration

Dopple Visual is designed to be CMS-agnostic and unopinionated, to give developers the freedom to integrate into any website regardless of the CMS or tech stack used.

Official integrations

To help simplify and speed up development, Dopple provides CMS-specific integrations for the following platforms:

Note

Don’t see your CMS listed above? Don’t worry! The Visual Component and Visual API both still provide all the features necessary to easily create custom integrations.

Custom integrations

For websites that require an integration that isn’t covered by the ones listed above, a custom integration can still be built by following a few key concepts:

  1. Edit your page or theme’s template to include either:
  2. Include the <script> tags for Dopple Visual on your page.
  3. Connecting the configuration options on your page (buttons, dropdown menus, etc.) to Dopple Visual.

Keep in mind that the specifics of how you implement each of these concepts may vary depending on your CMS and theme.

Adding <atlatl-visual> or <canvas> to your page template

Since Dopple Visual will look for a <canvas> element on your page to render the 3D product onto, edit your page or theme’s HTML template to include either a <canvas> element (if using the Visual API) or the <atlatl-visual> element (if using the Visual Component, which contains a <canvas> inside of it).

Typically, the 3D product will be placed similar to where other product media goes (such as static images, videos, or thumbnails).

Example: Shopify

Shopify sites will commonly use Liquid templates to define the markup for each page and component across the site.

If, for example, your Shopify theme uses a product-template.liquid file, the <canvas> or <atlatl-visual> tags may be added here.

product-template.liquid
<h1>{{ product.title }} - ${{ product.price }}</h1>
<div class="dopple-visual-container">
<canvas id="dopple-visual" touch-action="none"></canvas>
</div>

Example: WooCommerce

WooCommerce sites will commonly use PHP templates to define the markup for each page and component across the site.

The example below uses a fictional my-custom-template.php file that outputs the product title and Dopple Visual, which can be used as a starting point for your own custom template. In practice, your page template may be named differently, and may be much more complex.

my-custom-template.php
<?php
/**
* Template Name: Page with Dopple (Visual API)
*/

get_header();
?>

<h1><?php the_title() ?></h1>
<div class="dopple-visual-container">
<canvas id="dopple-visual" touch-action="none"></canvas>
</div>

Example: Webflow

Webflow allows you to embed custom code onto your pages, which may be used to add the <canvas> or <atlatl-visual> tags to be placed anywhere in your template.

For a detailed walkthrough, see the official Webflow Custom Code Embed guide.

Adding the <script> tags to your page

Next, in order for Dopple to load on your page, you must include a link to Dopple Visual’s scripts, and either use the defer attribute or place the script after the <atlatl-visual> or <canvas> tag, such as before the closing </body> tag on your page.

  • If using the Visual API directly, this script will be:
    <script src="https://builds.dopple.io/atlatl-visual-api/releases/current/index.js" defer></script>

  • If using the Visual Component, this script will be:
    <script src="https://builds.dopple.io/atlatl-visual-component/releases/current/index.js" defer></script>

For instance, in the Shopify example above, your <script> may be added directly after the Dopple Visual tag:

product-template.liquid
<h1>{{ product.title }} - ${{ product.price }}</h1>
<div class="dopple-visual-container">
<canvas id="dopple-visual" touch-action="none"></canvas>
<script src="https://builds.dopple.io/atlatl-visual-api/releases/current/index.js" defer></script>
</div>

Connecting the configuration options

Different ecommerce platforms will have different ways of defining variable products (i.e. products that have different variants or configurable options, such as color or size, that may be configured).

For most ecommerce sites, it is easier to set up your product page’s configuration options without binding them to the 3D product at first. At this stage, the goal is to build a basic working page (without 3D) and ensure the selection options for each variant are working correctly with your site’s backend, such as successfully adding the configured product to the cart when the user clicks Add To Cart.

Once the selection options are working correctly, you can then bind them to control the page’s 3D product. Two common approaches are:

Mapping properties to product variants

One common method to setup your conifguration bindings is to used a JSON mapping connecting each variant to the corresponding properties and values on the 3D product. This JSON mapping can be stored in a <script> tag on your page, and then referenced by the <atlatl-visual> or <canvas> tag.

For example, let’s say you have a product with two configurable options: color and size. The color option has three possible values: red, green, and blue, and the size option has two possible values: small and large. This would result in a total of six possible variants for this product:

  1. Red / small
  2. Red / large
  3. Green / small
  4. Green / large
  5. Blue / small
  6. Blue / large
tip

Be sure to reference your product’s configurability matrix to determine the possible options and variants for your product.

Example:

Dopple PropertyDopple ValueDescription
colorredSets the product's color to red
colorgreenSets the product's color to green
colorblueSets the product's color to blue
sizesmallChanges the product's size to small
sizelargeChanges the product's size to large

The JSON mapping for this product could then look like this:

const productJsonMap = {
"red-small": {
"color": "red",
"size": "small"
},
"red-large": {
"color": "red",
"size": "large"
},
"green-small": {
"color": "green",
"size": "small"
},
"green-large": {
"color": "green",
"size": "large"
},
"blue-small": {
"color": "blue",
"size": "small"
},
"blue-large": {
"color": "blue",
"size": "large"
}
}

As a simple example, your page’s HTML may display the options as <select> dropdowns:

<h2>Select your color:</h2>
<select id="product-color">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select>
<h2>Select your size:</h2>
<select id="product-size">
<option value="small">Small</option>
<option value="large">Large</option>
</select>

Then, if the user selects the red color and small size, you would use this JSON mapping to find the corresponding variant, and then call setValue() on the 3D product for each of the properties on that variant.

This approach is particularly useful for platforms like Shopify that assign a unique ID to each variant (the key in the JSON mapping above) and trigger a variantChange event with that ID whenever a new configuration option is selected.

// Be sure to globally define your `product` variable when initializing Dopple Visual, before this event listener below

document.addEventListener('variant:change', event => {
const variantId = event.detail.variant.id
const variant = productJsonMap[variantId]
if (variant) {
// For each property/value pair, set the 3D product's properties to match the current variant
Object.keys(variant).forEach(key => {
product.setValue(key, variant[key])
})
}
})

Binding the configuration options to the 3D product

Another approach is to break your product’s configuration options into categories, and then bind them manually to their respective controls in your page’s UI.

For example, using the same example as above with the three color options and two size options, your configuration options object may be set up like this:

const configOptions = [
{
// The Dopple-given name of the property on the 3D product that will be updated
property: 'color',

// The Dopple-given values for the property on the 3D product
values: {
// For each of these key/value pairs:
// - Key = any identifier used in the DOM, e.g. the `value` attribute the <option> element
// - Value = the name of the Dopple-given value for that property
'r': 'red',
'g': 'green',
'b': 'blue'
}
},
{
property: 'size',
values: {
'sm': 'small',
'lg': 'large'
}
}
]

Then, you can call setValue() on the 3D product each time a new option is selected with that option’s property and value name:

index.html
<!-- The canvas for Dopple Visual to render the product onto -->
<canvas id="dopple"></canvas>
<!-- Product color options -->
<select id="product-colors">
<option value="r">Red</option>
<option value="g">Green</option>
<option value="b">Blue</option>
</select>
<!-- Product size options -->
<div id="product-sizes">
<label >
<input type="radio" name="product-size" value="sm" checked />
Small
</label>
<label >
<input type="radio" name="product-size" value="lg" />
Large
</label>
</div>
script.js
const configOptions = [
{
property: 'color',
values: {'r': 'red', 'g': 'green', 'b': 'blue'}
},
{
property: 'size',
values: {'sm': 'small', 'lg': 'large'}
}
]

// Listen for changes to the Product Color dropdown menu
const colorsSelect = document.getElementById('product-colors')
colorsSelect.addEventListener('change', event => {
// Get the item from the configOptions array for the product color options
const options = configOptions.find(option => option.property === 'color')

// Get the `value` attribute of the selected <option> element, e.g. 'r' if Red was selected
const colorKey = event.target.value

// Get the Dopple-given value for that key, e.g. 'red'
const color = options.values[colorKey]

// Set the 3D product's color to the selected value
// Make sure your `product` instance was globally defined when initializing Dopple Visual
product.setValue('color', color)
})

// Listen for changes on each of the Product Size radio buttons
const sizesDiv = document.getElementById('product-sizes')
const sizeInputs = sizesDiv.querySelectorAll('input')
sizeInputs.forEach(input => {
input.addEventListener('change', event => {
// Same logic flow as above: set the product's based on the selected radio's `value` attribute
const options = configOptions.find(option => option.property === 'size')
const sizeKey = event.target.value
const size = options.values[sizeKey]
product.setValue('size', size)
})
})
info

This is especially useful when you might not have control over how your platform outputs the value or id attributes on your configuration options in the final HTML.

For example, some platforms may automatically set an <option>’s value attribute to some arbitrary internal ID, such as <option value="foo-dc8b1ff5">Red</option>. In cases like this, simply update your configOptions array to use the internal ID as the key, and the Dopple-given value as the value:

const configOptions = [
{
property: 'color',
values: {
// Replace these keys with your CMS's generated values
// The values remain the same Dopple-given values on the 3D product
'foo-dc8b1ff5': 'red',
'foo-4c98ad23': 'green',
'foo-39ef16c0': 'blue'
}
},
]

Your event listeners on those inputs would then take that internal ID (e.g. foo-dc8b1ff5), find the corresponding Dopple value for it (e.g. red), and set the product’s property to that value.