# Web SDK quickstart

> Add the TryYourSize element to any product page with a script tag or npm. Publishable keys, events, appearance.

Source: https://docs.tryyoursize.com/quickstarts/web/

> **For your developer**
>
> **What it does:** Adds a TryYourSize element to our product pages. Shoppers who have measured see their size in our own size labels; we can preselect it in the size picker. We receive sizes only, never measurements.
>
> **Time needed:** An afternoon for a first product page; less with the script tag.
>
> **What to send them:** The test publishable key (pk_test_…) from Studio → Developers → API keys, and the list of our site origins to register (Studio → Settings → Stores → Allowed sites).

On Shopify there is nothing to code: see the [Shopify quickstart](https://docs.tryyoursize.com/quickstarts/shopify.md).

1. **Get your key.** In Studio → Developers → API keys, copy the **publishable** key (`pk_test_…` for now). Register the origin of your site (for example `https://staging.brand.com`) for test mode. `http://localhost` works in test mode without registering.

2. **Load TryYourSize.js.**

   **Script tag**

   ```html
   <script src="https://js.tryyoursize.com/v1/tys.js"></script>
   ```

   The `/v1/` path always serves the latest compatible version 1.

   **npm**

   ```bash
   npm install @tryyoursize/sdk
   ```

   ```ts
   import { TryYourSize } from "@tryyoursize/sdk";              // bundled into your app
   // or load the CDN build lazily, once (like loadStripe):
   import { loadTryYourSize } from "@tryyoursize/sdk/loader";
   const tys = await loadTryYourSize("pk_test_…");              // null during SSR
   ```

3. **Add the element** where shoppers choose a size. `product` is your product ID or SKU, as synced to TryYourSize.

   **HTML (no code)**

   ```html
   <script src="https://js.tryyoursize.com/v1/tys.js"></script>

   <tys-fit publishable-key="pk_test_…" product="STRAIGHT-JEANS"></tys-fit>

   <script>
     document.querySelector("tys-fit")
       .addEventListener("tys:size", (e) => selectVariant(e.detail.size));
   </script>
   ```

   **JavaScript**

   ```html
   <div id="tys-fit"></div>
   <script>
     const tys = TryYourSize("pk_test_…");
     const elements = tys.elements();             // inherits your page's font and colours

     const fit = elements.create("fit", { product: "STRAIGHT-JEANS" });
     fit.mount("#tys-fit");
     fit.on("size", ({ size, verified }) => selectVariant(size));
   </script>
   ```

   **React**

   ```tsx
   import { loadTryYourSize } from "@tryyoursize/sdk/loader";
   import { TryYourSizeProvider, FitElement } from "@tryyoursize/react";

   const tysPromise = loadTryYourSize("pk_test_…");

   export function ProductPage() {
     return (
       <TryYourSizeProvider client={tysPromise}>
         <FitElement product="STRAIGHT-JEANS" onSize={({ size }) => selectVariant(size)} />
       </TryYourSizeProvider>
     );
   }
   ```

   See the [React quickstart](https://docs.tryyoursize.com/quickstarts/react.md).

4. **Allow our domains in your Content Security Policy** (if you have one): `script-src https://js.tryyoursize.com` (CDN build) and `frame-src https://embed.tryyoursize.com`.

5. **Try it.** Open your product page, sign in with an email code (or measure without an account), and pick a size. When everything works, follow [Going live](https://docs.tryyoursize.com/get-started/going-live.md).

## Elements

| Element | What it is |
|---|---|
| `"fit"` | The inline element: sign-in and "your body is ready" right in your page. The measuring window opens only to measure. **Recommended.** |
| `"button"` | A compact "Find my size" button that opens the measuring window. |
| `"sizeGuide"` | A link-sized "Size guide" with the TryYourSize mark, for the spot next to your size picker. Shows "Your size: M" when the shopper is connected. See [Size guide button](https://docs.tryyoursize.com/quickstarts/size-guide.md). |

No-code web components: `<tys-fit>` and `<tys-size-guide>`, which emit DOM events (`tys:size`).

## Element API

| Method | |
|---|---|
| `mount(selectorOrElement)` | Shows the element. Throws `mount_not_found` or `already_mounted`. |
| `on(event, handler)` / `once` / `off` | Events below. A handler that throws never breaks the SDK. |
| `update({ product })` | Switch product (for example on a variant page) without recreating the element. |
| `open()` / `close()` | Open or close the measuring window from your own UI. |
| `getRecommendation()` | Promise of the shopper's recommended size for this product. |
| `unmount()` / `destroy()` | Remove from the page; `destroy` also drops handlers. |
| `elements.update({ appearance })` | Live restyle (for example your dark mode), without reloading anything. |

| Event | Payload |
|---|---|
| `ready` | `{ elementType }`: shown and connected. |
| `size` | `{ product, size, verified }`: the shopper chose a size in our window; preselect the variant. `verified` is true when the full simulation confirmed it. |
| `open` / `close` | The measuring window opened or closed. Closing with unsaved changes asks the shopper first. |
| `loaderror` | `{ error }`: our window could not be reached (network, blocked by CSP). |
| `recommendation` | `{ product, status, size, studioSize, wearableSizes? }`: the shopper's recommended size in your labels. See [Recommended size and preselection](https://docs.tryyoursize.com/guides/recommendation-event.md). |

## Client methods

| Method | |
|---|---|
| `tys.elements(options?)` | An elements group (`appearance`, `locale`). |
| `tys.recommendation(product)` | Promise of the shopper's recommended size for a product, without mounting anything. See [Recommended size and preselection](https://docs.tryyoursize.com/guides/recommendation-event.md). |
| `tys.recommendationHandle()` | Promise of `{ handle, expiresAt }` or `null`: a sealed handle your server sends to `POST /v1/recommendations`. See [Server-side recommendations](https://docs.tryyoursize.com/guides/server-side-recommendations.md). |
| `tys.experiment()` | Promise of `{ experimentId, arm, visitorId }` or `null` when the store runs no [A/B holdout](https://docs.tryyoursize.com/guides/ab-holdout.md). |

## Errors

All SDK errors are `TryYourSizeError` with `type` (`integration_error` or `load_error`), a stable `code`, `message` and `docUrl`.

| Code | When |
|---|---|
| `secret_key_in_browser`, `invalid_key` | Wrong key passed to `TryYourSize()`. |
| `mount_not_found`, `already_mounted`, `element_destroyed` | Element lifecycle misuse. |
| `unknown_element_type`, `invalid_option` | Bad `create()` arguments. |
| `window_unreachable` | Emitted with `loaderror` when our window does not connect. |
| `script_load_failed` | `loadTryYourSize()` could not load the CDN script. |

## Security

- Use **publishable keys only** in the browser. Each works only on the origins you register.
- Our windows are iframes on `embed.tryyoursize.com`. Messages between your page and our window go through an exact origin allow-list on both sides, and every argument is validated.
- The shopper's measurements never reach your page or your servers: only the size does.

## Demo mode (test keys only)

For landing pages and sales demos, the `fit` element can show the try-on inline on a named **sample body**, with no sign-in. Sample body tape values are synthetic size-chart values, never a real person's.

```ts
const tys = TryYourSize("pk_test_…");                      // a live key throws
const demo = tys.elements().create("fit", {
  product: "CREW-TSHIRT",
  demo: { body: "sample-female-165", height: 640 },
});
demo.mount("#demo");
demo.update({ product: "SLIM-STRETCH-JEANS" });            // another garment
demo.update({ demo: { body: "sample-male-178" } });        // another body
```

Sample bodies: `sample-female-158`, `sample-female-165`, `sample-female-172`, `sample-male-172`, `sample-male-178`, `sample-male-186`. Demo mode shows precomputed results only and never starts a simulation on a page view; a body and product without a result says "Not simulated on this body yet".

> **Note: Versioning**
>
> The CDN path pins the major version (`/v1/`): improvements reach you automatically, and breaking changes ship as `/v2/`. The npm package follows semantic versioning.
