Skip to content

Clothing AI Try-On — SDK & Integration Guide

This guide covers all methods for embedding the WEARFITS Clothing AI Try-On experience into an e-commerce website or application: the JavaScript Modal SDK, direct iframe embedding, the PostMessage communication API, product data schemas, URL parameter integration, Shopify-specific setup, selection rules, and integration best practices.

See also: The latest hosted version of this guide is available at tryon.wearfits.com/docs/integration.


The JavaScript Modal SDK is the recommended integration path. It handles modal lifecycle, DOM mounting, and product synchronization automatically, with minimal code required on the host page.

Installation

<!-- Option A: Script tag -->
<script src="https://tryon.wearfits.com/sdk/wearfits.js"></script>

<!-- Option B: ES module import -->
<script type="module">
  import { openWEARFITSTryOn } from 'https://tryon.wearfits.com/sdk/wearfits.esm.js';
</script>

Usage Example

const tryOn = new WearfitsTryOn({
  apiKey: 'wf_prod_abc123...',
  products: [
    {
      id: 'suit_01',
      name: 'Executive Suit',
      category: 'fullBody',
      images: ['https://cdn.example.com/suit_front.jpg']
    }
  ],
  onComplete: (result) => {
    console.log('Result image URL:', result.resultImageUrl);
  },
  onError: (error) => {
    console.error('Try-on error:', error);
  },
  onClose: () => {
    console.log('Modal closed');
  }
});

tryOn.open();

Constructor Options

Option Type Default Description
apiKey string null Your public WEARFITS API key.
products array [] Initial list of products to display in the try-on panel.
baseUrl string /api/v1 Proxy endpoint URL. Defaults to the application's built-in worker path.
useMock boolean false When true, uses mock data instead of live AI rendering. Useful for UI development and testing.
onComplete function null Callback invoked on successful try-on. Receives a fitting result object.
onError function null Callback invoked on system or AI errors. Receives an error object with code, message, and optional details.
onClose function null Callback invoked when the user closes the modal.

2. Direct Iframe Integration

For integrations that require full control over the surrounding UI, the application can be embedded directly as an <iframe>.

Basic HTML Setup

<iframe
  id="wearfits-frame"
  src="https://tryon.wearfits.com"
  allow="camera"
  style="width: 100%; height: 100vh; border: none;"
></iframe>

The allow="camera" attribute is required for digital twin creation. Omitting it will prevent the camera from activating inside the iframe.

URL Parameters

Parameters are appended to the iframe src as standard query string values.

Parameter Description Example
products URL-encoded JSON array of product objects, or a URL pointing to a hosted JSON feed. ?products=[{"id":"1",...}]
productsUrl Legacy alias. URL to a public JSON file containing the product list. Use products with a URL value for new integrations. ?productsUrl=https://cdn.example.com/catalog.json
avatarId ID of an existing digital twin to load immediately, skipping twin creation. ?avatarId=dt_abc123
step Start at a specific step: twin_creation or virtual_fitting. Intended for internal routing and debugging. ?step=virtual_fitting

3. PostMessage Communication API

When the application runs inside an iframe, the host page and the application exchange messages via window.postMessage. This enables dynamic product updates and handling of try-on outcomes without reloading the iframe.

Host → Application (Inbound Messages)

const iframe = document.getElementById('wearfits-frame');

// Send initialization after WEARFITS_READY is received
iframe.contentWindow.postMessage({
  type: 'WEARFITS_INIT',
  payload: {
    products: [...],
    apiKey: 'your-api-key',
    baseUrl: 'https://api.wearfits.com'
  }
}, 'https://tryon.wearfits.com'); // Use specific origin in production
Message Type Payload Description
WEARFITS_INIT { products, apiKey, baseUrl } Full initialization of the application state. Send this in response to WEARFITS_READY.
WEARFITS_SET_PRODUCTS [...products] Dynamically updates the garment list in the side panel without reinitializing the session.

Application → Host (Outbound Events)

window.addEventListener('message', (event) => {
  // Always validate the origin in production
  if (event.origin !== 'https://tryon.wearfits.com') return;

  const { type, payload } = event.data;

  switch (type) {
    case 'WEARFITS_READY':
      // App has loaded — send WEARFITS_INIT now
      initializeApp();
      break;

    case 'WEARFITS_COMPLETE':
      console.log('Result image:', payload.resultImageUrl);
      console.log('Selected products:', payload.selectedProducts);
      break;

    case 'WEARFITS_ERROR':
      console.error('Error code:', payload.code, payload.message);
      break;

    case 'WEARFITS_CLOSE':
      // Hide the iframe or overlay
      document.getElementById('wearfits-modal').hidden = true;
      break;
  }
});
Event Type Payload Description
WEARFITS_READY { version: "1.0.0" } Emitted when the application has fully loaded and is ready to receive WEARFITS_INIT.
WEARFITS_COMPLETE { resultImageUrl, selectedProducts, timestamp } Emitted on successful try-on. See Fitting Result Object.
WEARFITS_ERROR { message, code } Emitted on any system or AI failure.
WEARFITS_CLOSE {} Emitted when the user requests to close the application.

4. Product Data Schema

Product Object

All integration methods accept products in the same format.

{
  "id": "top-001",
  "name": "Classic White Blouse",
  "category": "top",
  "default": true,
  "images": [
    "https://cdn.example.com/products/blouse-model.jpg",
    "https://cdn.example.com/products/blouse-flat.jpg"
  ]
}
Field Type Required Description
id string Yes Unique product identifier.
name string Yes Product display name shown in the selection panel.
category string Yes Product category. See table below.
images array Yes Array of 1–2 publicly accessible image URLs.
default boolean No When true, the product is pre-selected when the application loads.

Product Categories

Category Value Typical Items
Tops "top" T-shirts, blouses, shirts, sweaters, jackets
Bottoms "bottom" Pants, skirts, shorts
Full Body "fullBody" Dresses, jumpsuits, full outfits
Shoes "shoes" All footwear

Image Array Convention

The images array should contain 1–2 URLs:

  • images[0] — Primary (lifestyle or model) image. Used in the rendered try-on result preview.
  • images[1] — Secondary (packshot or flat-lay) image. Used in the product selection carousel.

If only one image is supplied, it is used for both purposes.

Fitting Result Object

The WEARFITS_COMPLETE event and the onComplete SDK callback both receive the same result object:

{
  "resultImageUrl": "https://api.wearfits.com/files/result_xyz.jpg",
  "selectedProducts": [
    { "id": "top-001", "name": "Classic White Blouse", "category": "top" },
    { "id": "bottom-001", "name": "Navy Dress Pants", "category": "bottom" }
  ],
  "timestamp": "2026-04-08T10:30:00Z"
}

5. Standalone Page (URL Parameters)

For the simplest possible integration — such as a "Try On" link that opens in a new tab — product data can be passed directly in the URL.

Encoded JSON

const products = [
  {
    id: 'top-001',
    name: 'Classic White Blouse',
    category: 'top',
    default: true,
    images: [
      'https://cdn.example.com/products/blouse-model.jpg',
      'https://cdn.example.com/products/blouse-flat.jpg'
    ]
  }
];

const url = new URL('https://tryon.wearfits.com/');
url.searchParams.set('products', JSON.stringify(products));

window.open(url.toString(), '_blank');

Hosted JSON File

For larger catalogs where URL length is a concern, pass a URL to a hosted JSON file instead of inline data:

https://tryon.wearfits.com/?products=https://your-store.com/api/tryon-products.json

The application detects whether the products value is JSON or a URL automatically. The legacy productsUrl parameter is also accepted for backward compatibility.

Your server-hosted JSON should follow this structure:

{
  "products": [
    {
      "id": "top-001",
      "name": "Classic White Blouse",
      "category": "top",
      "default": true,
      "images": ["https://cdn.example.com/products/blouse-model.jpg"]
    }
  ]
}

6. Shopify Integration

The recommended approach for Shopify is to render the WEARFITS experience as an iframe modal on the product detail page (PDP), initialized via a Shopify app proxy feed.

  • WEARFITS iframe source: https://tryon.wearfits.com
  • Product feed endpoint: /apps/wearfits/products/{{ product.handle }}.json (served via Shopify app proxy)
  • Category mapping: Use a product metafield with namespace wearfits and key category; accepted values are top, bottom, fullBody, and shoes

This approach keeps the customer on the PDP throughout the try-on experience, maintains a clear path back to add-to-cart, and avoids exposing API credentials in the browser.

App Proxy Setup (shopify.app.toml)

[access_scopes]
scopes = "write_app_proxy"

[app_proxy]
url = "/proxy/wearfits"
prefix = "apps"
subpath = "wearfits"

With this configuration:

  • https://{shop}.myshopify.com/apps/wearfits/products/{handle}.json proxies to https://{your-app}/proxy/wearfits/products/{handle}.json

Run shopify app dev after updating shopify.app.toml to apply the proxy config to your development store. Production stores require shopify app deploy. Choose proxy prefix and subpath values carefully: changes to these after stores are installed only apply to new installs.

Liquid Snippet — Try On Button (New-Tab Fallback)

Use this snippet on product pages to render a "Try On" button. The button is shown only for products that have a valid wearfits.category metafield, and opens the try-on experience in a new tab.

{%- assign wearfits_category = product.metafields.wearfits.category.value | default: product.metafields.wearfits.category -%}

{%- if wearfits_category != blank -%}
  {%- capture wearfits_feed_url -%}
    {{ shop.url }}/apps/wearfits/products/{{ product.handle }}.json
  {%- endcapture -%}

  <button
    type="button"
    id="wearfits-tryon-button-{{ product.id }}"
    class="button button--secondary"
    data-wearfits-url="https://tryon.wearfits.com/?products={{ wearfits_feed_url | strip | url_encode }}"
  >
    Try On
  </button>

  <script>
    (() => {
      const button = document.getElementById('wearfits-tryon-button-{{ product.id }}');
      if (!button) return;
      button.addEventListener('click', () => {
        const url = button.getAttribute('data-wearfits-url');
        if (!url) return;
        window.open(url, '_blank', 'noopener,noreferrer');
      });
    })();
  </script>
{%- endif -%}

For the full on-page experience, use an iframe modal initialized via PostMessage:

<button type="button" id="wearfits-open-iframe">Try On</button>
<div id="wearfits-modal" hidden>
  <iframe
    id="wearfits-frame"
    src="https://tryon.wearfits.com"
    allow="camera"
    style="width: 100%; height: 100%; border: 0;"
  ></iframe>
</div>
const button = document.getElementById('wearfits-open-iframe');
const modal  = document.getElementById('wearfits-modal');
const iframe = document.getElementById('wearfits-frame');
const feedUrl = `${window.Shopify.routes.root}apps/wearfits/products/{{ product.handle }}.json`;

button.addEventListener('click', () => {
  modal.hidden = false;
});

window.addEventListener('message', async (event) => {
  if (event.origin !== 'https://tryon.wearfits.com') return;

  if (event.data?.type === 'WEARFITS_READY') {
    const response = await fetch(feedUrl);
    const payload  = await response.json();
    iframe.contentWindow.postMessage(
      { type: 'WEARFITS_INIT', payload },
      'https://tryon.wearfits.com'
    );
  }

  if (event.data?.type === 'WEARFITS_COMPLETE') {
    console.log('Try-on result:', event.data.payload);
  }

  if (event.data?.type === 'WEARFITS_CLOSE') {
    modal.hidden = true;
  }
});

Shopify Field Mapping

Shopify Field WEARFITS Field
product.id id
product.title name
product.metafields.wearfits.category category
Featured image + first alternate image images
Current PDP product default: true

Feed Generation Rules

The app proxy endpoint should build its response using the following logic:

  1. Load the current product by handle.
  2. Read the wearfits.category metafield.
  3. Include the current product with default: true.
  4. Add compatible complementary products:
  5. If the current category is top, add bottoms.
  6. If the current category is bottom, add tops.
  7. If the current category is fullBody, optionally add shoes.
  8. If the current category is shoes, add a complete top + bottom or fullBody look.
  9. Limit the response to 2–4 products total.
  10. Return image URLs that are absolute, HTTPS, and publicly accessible.

7. Product Selection Rules

The try-on engine enforces the following garment combination rules:

  • A Top + Bottom combination, or a single FullBody item, is required to generate a clothing try-on.
  • Shoes are always optional and can be added to any outfit combination.
  • Selecting a FullBody item automatically clears any Top or Bottom selections.
  • Selecting a Top or Bottom automatically clears any FullBody selection.

These rules are enforced in the application UI; no additional handling is needed in the integration layer.


8. Best Practices

Image Quality

  • Use product images of at least 500 × 500 px.
  • Ensure consistent lighting and a white or neutral background.
  • Include both a lifestyle (model) image and a packshot (flat-lay) where available — images[0] should be the lifestyle shot.
  • Use HTTPS URLs for all images. Images must be publicly accessible; Data URLs are also supported.

Security

  • Always validate postMessage origins in production — use the specific iframe origin rather than '*'.
  • Implement proper CORS headers on your image CDN to ensure images are accessible from the WEARFITS domain.
// Production-safe postMessage handler
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://tryon.wearfits.com') return;
  // Process message...
});

Performance

  • Trigger a background warmup call to https://api.wearfits.com/health/warmup when the twin creation step first renders to reduce cold-start latency.
  • Trigger a second warmup call to https://api.wearfits.com/health/queue-warmup when the garment selection step is displayed to pre-warm the fitting queue.
  • Consider lazy-loading the try-on iframe so it does not block the initial page render.
  • Digital twin IDs are cached automatically in browser cookies and localStorage; avoid manually clearing them between sessions.

Camera Permissions

  • Always include allow="camera" on the <iframe> element. Without it, browsers block camera access regardless of user permission grants.
  • The application is fully responsive and optimized for mobile. Camera access is required for digital twin creation on all devices.

CORS and Persistence

  • Ensure your baseUrl proxy endpoint allows cross-origin requests from your host domain.
  • In iframe mode, verify that browser settings permit third-party cookies if you want the digital twin resume-session feature to work across visits.