# 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](https://www.showroompro.ai/docs/install/nextjs.md) 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](https://www.showroompro.ai/docs/widget.md#javascript-api-and-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`.

---

Source: https://www.showroompro.ai/docs/install/react · Last updated 2026-10-16 · All docs: https://www.showroompro.ai/llms.txt
