> ## Documentation Index
> Fetch the complete documentation index at: https://docs.virtual.fit/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom JavaScript quickstart

> Install the hosted virtual.fit loader on a custom or headless storefront.

The Custom JavaScript integration adds virtual.fit to any storefront that can load a hosted script. Your virtual.fit settings control product availability, shopper access, and daily limits.

## Prerequisites

Before installing the loader, you need:

* A custom storefront site in virtual.fit.
* Its public site key and hosted loader URL.
* An exact production or staging origin.
* One synced, enabled product with usable garment images.
* A CSS selector for the main product media wrapper.

<Warning>
  The site key is public and belongs in browser code. Management API keys are secret and must never be embedded in the storefront.
</Warning>

## 1. Allow the storefront origin

In virtual.fit, open **Custom JS → Installation**. Add each origin that will load the widget or send analytics.

```text theme={null}
https://shop.example.com
https://staging-shop.example.com
```

An origin is the scheme, hostname, and optional port. Do not include paths, query strings, or trailing product URLs.

| Page URL                                        | Allowed origin                     |
| ----------------------------------------------- | ---------------------------------- |
| `https://shop.example.com/products/linen-dress` | `https://shop.example.com`         |
| `https://staging.example.com:8443/p/sku-42`     | `https://staging.example.com:8443` |

## 2. Sync and enable one product

Use a CSV import or the management API to add a product. Its `handle` or `product_id` must match the value your product URL exposes.

For `/products/linen-midi-dress`, a typical record uses:

```json theme={null}
{
  "product_id": "sku-10042",
  "handle": "linen-midi-dress",
  "title": "Linen Midi Dress",
  "product_image_urls": [
    "https://cdn.example.com/linen-midi-dress-front.jpg",
    "https://cdn.example.com/linen-midi-dress-back.jpg"
  ],
  "enabled": true
}
```

See [Sync the catalog](/custom-js/catalog) for CSV and API details.

## 3. Configure product URL detection

For a URL such as `https://shop.example.com/products/linen-midi-dress`:

* Set **Resolution Mode** to **Path template**.
* Set **Match Products By** to **Handle**.
* Set **Path Template** to `/products/:handle`.

Paste a real product URL into the virtual.fit live URL tester. Continue only when it reports an enabled matched product.

## 4. Install the loader

Copy the generated snippet from virtual.fit. The basic pattern is:

```html theme={null}
<script>
  window.bitstudio = window.bitstudio || function () {
    (window.bitstudio.q = window.bitstudio.q || []).push(arguments);
  };

  bitstudio('init', {
    siteKey: 'site_pub_your_key',
    mount: '.product-media',
    terms: {
      fullSelector: '#virtual-fit-terms'
    }
  });
</script>
<script async src="COPY_THE_SCRIPT_URL_FROM_VIRTUAL_FIT"></script>
```

Place the snippet on product pages, usually before `</body>`. Use the exact site key and script URL shown in virtual.fit.

<Info>
  `window.bitstudio` is the stable browser API name retained for integration compatibility. Use virtual.fit in all merchant and shopper-facing copy.
</Info>

### Choose the mount target

Point `mount` at the main product gallery or media wrapper.

Good targets:

```text theme={null}
.product-media
.product-gallery
[data-product-gallery]
```

Avoid the buy box, product form, add-to-cart button, cart drawer, recommendations, and elements that disappear on variant change.

## 5. Provide full terms markup

If you use `fullSelector`, add a hidden element whose `innerHTML` the widget can display:

```html theme={null}
<div id="virtual-fit-terms" hidden>
  <p>
    By continuing, you confirm that you have the right to use this photo and agree
    to this store's virtual try-on terms.
  </p>
</div>
```

You can instead provide `terms.fullHtml` directly. See [Styling, labels, and terms](/custom-js/styling-and-copy).

## 6. Verify the integration

Open the real product URL and confirm:

* The **Try On** control appears once.
* A disabled or unknown product does not show the control.
* The widget is positioned over the main product media.
* A photo can be uploaded and a try-on completes.
* The generated image appears under **Results** in virtual.fit.

<Check>
  Your first integration is complete when one enabled product passes the full [launch checklist](/getting-started/launch-checklist).
</Check>

## Next steps

<CardGroup cols={2}>
  <Card title="Configure the loader" icon="sliders" href="/custom-js/configuration">
    Add authentication, product context, terms, and advanced selectors.
  </Card>

  <Card title="Track commerce" icon="cart-shopping" href="/custom-js/commerce-events">
    Connect add-to-cart, checkout, and purchase outcomes to try-on usage.
  </Card>
</CardGroup>
