# WEARFITS Shopify Integration

Last updated: 2026-09-22.

Add WEARFITS virtual try-on to Shopify product pages.

## Choose the storefront path

For a Shopify storefront and the complete try-on UI plus size fitting, the
recommended path is the hosted iframe at
https://tryon.wearfits.com/?sizeFitting=true. Follow the public integration
guide at https://tryon.wearfits.com/docs/integration.html for READY/INIT and base
product handoff. Put the optional sizeChart sibling field on each
WEARFITS_INIT.payload.products[] item; SET_PRODUCTS uses the same product shape.
The chart requires version 1, basis "body", unit "cm" or "in", and body ranges
for height, chest, waist, hip, or inseam.
Start with the demo at
https://tryon.wearfits.com/demo_tryon.html; public Liquid exposes no service API key.
Hosted product categories use fullBody and shoes; translate the widget's
full-body and shoe values. Validate message origin/source and use the exact
https://tryon.wearfits.com postMessage target origin.

The widget is the lightweight API-backed alternative and does not include the
hosted iframe's size-fitting overlay. If the merchant explicitly chooses the
widget, use the architecture and snippet below.

## Widget architecture (when selected)

1. A theme app embed or snippet loads `https://api.wearfits.com/widget/tryon.js`.
2. The product page injects product JSON from Liquid.
3. A "Try on" button calls `Wearfits.openTryOn()`.
4. Production stores route API calls through a Shopify app proxy or backend
   service so the service API key is never exposed in the theme.

## Theme snippet

Prerequisite: implement the authenticated Shopify app-proxy routes described
below at /apps/wearfits. This snippet does not install that backend. Configure
a single-line product metafield custom.wearfits_category; default auto is safe
for a single product. Adapt the Size option name for translated storefronts.

```liquid
<script src="https://api.wearfits.com/widget/tryon.js"></script>

<button type="button" id="wearfits-tryon">Try it on</button>

<script>
  document.getElementById('wearfits-tryon').addEventListener('click', function () {
    Wearfits.openTryOn({
      apiBase: '/apps/wearfits',
      products: [{
        id: {{ product.id | append: '' | json }},
        name: {{ product.title | json }},
        category: {{ product.metafields.custom.wearfits_category.value | default: 'auto' | json }},
        images: [
          {% for image in product.images %}
            {{ image | image_url: width: 1600 | prepend: 'https:' | json }}{% unless forloop.last %},{% endunless %}
          {% endfor %}
        ],
        sizes: [
          {% for value in product.options_by_name['Size'].values %}
            {{ value.name | json }}{% unless forloop.last %},{% endunless %}
          {% endfor %}
        ]
      }]
    });
  });
</script>
```

The example uses catalog images. For variant-aware pages, read the selected
variant when the button is clicked and put its image first. The widget does not
select variants for you. If passing variants, map them to { id: string, size:
string, sku: string }; find Size's position instead of assuming option1.
Mount one button per product section and rebind after Shopify section reloads.

## Category mapping

Infer the WEARFITS category conservatively from product type, tags, or
collection:

- shirts, tops, tees, blouses -> `top`
- pants, trousers, skirts, shorts -> `bottom`
- dresses, jumpsuits -> `full-body`
- shoes, sneakers, loafers -> `shoe`

When unsure, require a merchant-set product metafield rather than guessing.

## Security

- Do not expose long-lived service API keys in public Liquid.
- Prefer a Shopify app proxy that forwards the virtual-fitting and job-status
  requests with the service key added server-side.
- If a browser token is used, document its scope and rate-limit assumptions.

Implement POST /apps/wearfits/api/v1/virtual-fitting and GET
/apps/wearfits/api/v1/jobs/{id}. Validate Shopify's app-proxy signature and map
the verified shop to its merchant account. Add the merchant key server-side, or
the service key plus that account's X-Wearfits-Account token. Never accept an
arbitrary upstream URL or account identifier from the shopper. Restrict the
proxy to these routes, validate payloads, and apply shopper/session rate limits.
An app-proxy signature identifies the shop; it does not by itself limit shopper
spending. Preserve upstream status and JSON. See the
[Shopify app-proxy guide](https://shopify.dev/docs/apps/build/online-store/app-proxies)
and [Liquid product options](https://shopify.dev/docs/api/liquid/objects/product_option).

## Deliverables checklist

- Theme snippet or app embed.
- Product JSON handoff from Liquid.
- "Try on" button placement.
- App proxy route (production).
- A smoke test with a real product page payload.

The widget contract is in the `wearfits-virtual-tryon-widget` skill; the REST
API and proxy targets are in `wearfits-api-integration` and the OpenAPI spec at
https://api.wearfits.com/doc.
