The ring builder's JavaScript SDK
Load ring-builder.js from your 3JD address and call RMJRingBuilder.mount with your builder's slug. The SDK draws the builder in an iframe, sizes it to its content, and calls your functions when the shopper changes the ring, shares it or adds it to the cart. Return false from onAddToCart to write the cart line yourself, or let the SDK do it on Shopify.
3D Jewelry Designer3 min read
Mount a builder
Copy your builder's slug from Dashboard → Embeds, then:
<div id="ring"></div>
<script src="https://3djewelrydesigner.com/ring-builder.js"></script>
<script>
var builder = RMJRingBuilder.mount("#ring", {
slug: "YOUR_EMBED_SLUG",
onSelection: function (s) { showPrice(s.priceCents, s.currency); },
onAddToCart: function (s, instruction, meta) { /* see below */ },
});
</script>
Without any JavaScript of your own, a container works too. The SDK finds it when the page loads:
<div data-rmj-ring-builder data-rmj-slug="YOUR_EMBED_SLUG" data-rmj-height="640px"></div>
<script src="https://3djewelrydesigner.com/ring-builder.js"></script>
The data attributes are data-rmj-slug, data-rmj-base, data-rmj-height,
data-rmj-min-height, data-rmj-max-height, data-rmj-fit and
data-rmj-datalayer.
Options
| Option | What it does |
|---|---|
slug | Your builder's slug. Required. |
baseUrl | The 3JD address to load from. Defaults to the address the script came from. |
height | The starting height: a number of pixels, any CSS length, "auto", or { mobile, tablet, desktop }. |
minHeight, maxHeight | Limits on the height the builder asks for. |
autoResize | true or false to force resizing on or off. Left out, the builder decides from its own layout setting. |
fit | "viewport" keeps a frame you sized to the screen as it is. |
autoCart | false stops the SDK writing the cart line, so only your onAddToCart runs. |
loading | "eager" or "lazy". Left out, a builder near the top of the page loads at once and one far below waits until it is close. |
borderRadius, title | The frame's corner radius and its accessible title. |
resume | A shared-design token. Left out, the SDK reads ?c= from your page's address, so a shared link opens the shared ring. |
dataLayer | true, or the name of your own array: each builder event is also pushed to the page's dataLayer, for Google Tag Manager. |
Callbacks
onReady(): the builder has loaded.onSelection(selection): every change the shopper makes.onAddToCart(selection, instruction, meta): the shopper pressed the cart button.metaholdsquoteToken,properties(the line-item properties),sku,priceCentsandcurrency. Returnfalseto stop the SDK from writing the cart itself.onShare(selection, url): the shopper shared the ring;urlreopens it.onEnquiry(selection): on a builder set to Send an enquiry, the shopper sent the form. The enquiry is already in your Leads.onResize(height, data): the frame changed height.onAdded(instruction)andonError(error): after the SDK wrote a Shopify cart line, or failed to.
The selection
{
"band": "classic-round",
"shape": "Round",
"setting": "cp",
"carat": 1,
"metal": "yellow_gold_14k",
"variant": null,
"engraving": { "text": "Always", "font": "serif", "position": "inside" },
"sku": "RB-RND-100-14Y",
"priceCents": 248000,
"currency": "USD"
}
shape, setting and carat are the values in your own catalogue, and gem
is there when the builder offers a gem choice. sku and priceCents come from
our server, not from the shopper's browser (price is an older display figure:
use priceCents). On add to cart the selection also has quoteId, the lead
saved for that add. engraving is null when there is none.
Writing the cart yourself
On Shopify the SDK writes the cart line for you: it finds or makes the right
variant and adds it, then sends the shopper to the cart or checkout if your
builder is set to. With the builder's own checkout (hosted) or a Shopify draft
order (draft) it opens that page. Otherwise instruction.mode is "event"
and the add is yours to make. Use meta.sku and meta.priceCents, and put
meta.properties on the line so the order can be traced back to the builder.
If your server sets the line price, check it first: send meta.quoteToken to
POST /api/public/ring-builder/verify as { "token": "…" }. The answer is
{ "valid": true, "sku", "priceCents", "currency", "expiresAt" } for a genuine
quote, and { "valid": false } for a changed or expired one. No API key is
needed: the token is the proof.
Google Tag Manager
With dataLayer: true the SDK pushes the builder's events to window.dataLayer
(or to the array you name), so your own analytics can count them. Each push has
event and rmj_embed (the builder's slug):
| Event | When | Also has |
|---|---|---|
rmj_ready | The builder has loaded. | |
rmj_selection | The shopper changed the ring. | rmj_sku, rmj_value, rmj_currency, rmj_shape, rmj_metal |
rmj_add_to_cart | The shopper pressed the cart button. | the same |
rmj_share | The shopper shared the ring. | the same |
rmj_enquiry | The shopper sent an enquiry (a builder set to Send an enquiry). | the same |
rmj_try_on | The shopper opened try-on. |
rmj_value is the price in whole units: 2480 where the selection's priceCents is 248000.
The names start with rmj_ so they never double your store's own events: map
them to your tags in Tag Manager. Nothing is pushed unless you turn this on.
The handle
mount returns an object with:
iframe: the frame element.remeasure(): ask the builder to report its height again, for example after a tab or an accordion around it opens.destroy(): remove the frame and every listener the SDK added.
RMJRingBuilder.version is the script's version.
Media Only embeds
A Media Only embed (a 360° hero and captured stills, no cart) mounts with
RMJRingBuilder.mountMedia("#media", { slug, fallback }), or with
<div data-rmj-media data-rmj-slug="…">. fallback is a selector for your
own product gallery: it is hidden while the 3D view loads and shown again if
the view cannot run. columns sets the number of still tiles in a row, and
onFail(reason) tells you when the fallback was used.
Listening without the SDK
A plain <iframe> of the builder sends the same events with
window.postMessage. Each message has source: "rmj-ring-builder" and a
type: ready, selection, addToCart, share, resize, tryon-open or
tryon-close. Check event.origin is your 3JD address before you use one.
Related
Related
- How an integration fits together
From a shopper building a ring to the order in your systems: what runs where, which price to trust, and how products and 3D models stay in step.
- Webhooks: events, payloads and signatures
Send leads, saved designs, carts and orders to your CRM or backend as signed webhooks, and check each delivery with a few lines of code.
- Band engraving on a ring
Let shoppers engrave a message on the band: live curved 3D text in nine fonts, with symbols, placement, size and an optional surcharge.