Add an AI ring builder to a React app

There is no npm package to install. The widget is a plain <div> plus embed.js, and embed.js mounts containers that React renders after the script loads, so client-side routing works without extra code.

Using Next.js? Follow the Next.js guide instead.

#1. Add a RingBuilder component

jsx
// src/components/RingBuilder.jsx
import { useEffect } from "react";

const EMBED_SRC = "https://www.showroompro.ai/embed.js";

function loadEmbedScript() {
  if (document.querySelector(`script[src="${EMBED_SRC}"]`)) {
    window.ShowroomPro?.mount();
    return;
  }
  const script = document.createElement("script");
  script.src = EMBED_SRC;
  script.async = true;
  document.body.appendChild(script);
}

export function RingBuilder({ token, mode = "inline", quiz }) {
  useEffect(loadEmbedScript, []);
  return (
    <div
      data-showroompro-ring-builder={token}
      data-mode={mode === "popup" ? "popup" : undefined}
      data-quiz={quiz === "wedding-band" ? "wedding-band" : undefined}
    />
  );
}

mode is "inline" (default) or "popup". Render a fresh component when you change props; the widget reads its attributes once when it mounts.

#2. Render it

jsx
import { RingBuilder } from "./components/RingBuilder";

export default function DesignYourRingPage() {
  return (
    <main>
      <h1>Design your engagement ring</h1>
      <RingBuilder token="YOUR_TOKEN" />
    </main>
  );
}

The token is public, so it can live in code or in an env var such as VITE_SHOWROOMPRO_TOKEN.

#3. Optional: floating button on every page

Paste the floating snippet into index.html, just before </body>:

html
<script src="https://www.showroompro.ai/embed.js" data-token="YOUR_TOKEN" data-mode="floating" async></script>

#4. Optional: open it from your own button

jsx
<button onClick={() => window.ShowroomPro?.open()}>Design your ring</button>

window.ShowroomPro exists once embed.js has loaded on the page (any snippet, or the component above). To react to designs, use window.ShowroomPro.on("design_generated", fn) inside a useEffect and call the returned function on cleanup. See events.

#Notes

  • TypeScript: data-* props need no typings. For window.ShowroomPro, add declare global { interface Window { ShowroomPro?: any } }.
  • React StrictMode runs effects twice in development; the component above only adds the script once.
  • If the app sets a Content Security Policy, allow https://www.showroompro.ai in script-src, frame-src and connect-src.