Skip to content

Quickstart A - bare HTML

Put the try-on widget on a product page with two script tags. No server code and no build step.

Before you start

You need:

  • A publishable key (pk_…). It is listed on the Integration page of the client portal at https://app.ziex-tryon.com. This is the only key a public page may carry. Never put the secret key (tryon_…) into page source - it also signs in to the portal. See Overview & concepts.
  • The key must be bound to your shop's domain, for example shop.example. If it is not, every request from your page answers 403 KEY_NOT_BOUND; contact us to bind it.

For this quickstart the examples use pk_YOUR_PUBLISHABLE_KEY and the shop shop.example. To try the page without spending anything, use a pk_test_… key instead - see Local development.

1. Add the widget

<script src="https://api.ziex-tryon.com/embed/tryon-embed.js"></script>
<script>
  TryOn.init({
    apiKey: 'pk_YOUR_PUBLISHABLE_KEY',
    productImage: 'https://shop.example/images/linen-shirt.jpg',
    productTitle: 'Linen shirt',
    productUrl: 'https://shop.example/p/linen-shirt',
    category: 'tops',
    lang: 'en'
  });
</script>

A floating "Try on" button appears. The shopper presses it, picks a photo, and the widget sends the photo and the garment to the API, follows the job and shows the result.

Load tryon-embed.js from https://api.ziex-tryon.com/embed/. The widget takes the address of the API from where its script was loaded, so a copy of the file on your own server would send its requests to your server.

Option Meaning
apiKey Required. The publishable key pk_….
productImage URL of the garment photo. A URL on another host is fine.
productTitle The product name; kept with the job so you can tell what a try-on was for.
productUrl The product page. Kept only if it is a plain http(s) URL; with a publishable key it must be on your bound domain.
category tops, outerwear, bottoms, one-pieces or auto. The current list is GET /api/v1/tryon/capabilities (no key needed).
lang ru or en. By default the widget reads <html lang>.
launcher false hides the floating button; your page opens the widget itself (below).

If you omit productImage or productTitle, the widget tries to find them on the page (structured data, Open Graph tags, the first h1). Passing them yourself is more reliable. All options, events and update() are in the Widget reference.

2. Use your own button

With launcher: false the widget draws no button and makes no domain check on load; your page calls TryOn.open():

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

<script src="https://api.ziex-tryon.com/embed/tryon-embed.js"></script>
<script>
  TryOn.init({
    apiKey: 'pk_YOUR_PUBLISHABLE_KEY',
    productImage: 'https://shop.example/images/linen-shirt.jpg',
    productTitle: 'Linen shirt',
    productUrl: 'https://shop.example/p/linen-shirt',
    category: 'tops',
    launcher: false
  });
  document.getElementById('tryon-button').addEventListener('click', function () {
    TryOn.open();
  });
</script>

When the product changes without a page load (a colour or size switch), call TryOn.update({ productImage: '…' }) instead of destroy() and init() again - see the Widget reference.

3. Bind the key to your domain

A publishable key works only on the domain it is bound to: the domain itself, www. and any subdomain. A request from another site is 403 DOMAIN_NOT_ALLOWED, and a request with no Origin or Referer is 403 ORIGIN_REQUIRED - a publishable key works from a browser page, not from a server.

You can check a key from the command line by sending the Origin a browser would send:

curl -i https://api.ziex-tryon.com/api/v1/tryon/domain-check \
  -H 'X-API-Key: pk_YOUR_PUBLISHABLE_KEY' \
  -H 'Origin: https://shop.example'
{
  "allowed": true,
  "domain": "shop.example",
  "client_name": null,
  "plan_id": null,
  "limit_exceeded": false,
  "limit_remaining": null,
  "mode": "live"
}

200 means the key may be used from that host. A publishable key gets only limit_exceeded (and mode) as account information; client_name, plan_id and limit_remaining stay null - they are for the secret key. A refusal is 403 with error.code DOMAIN_NOT_ALLOWED, KEY_NOT_BOUND or ORIGIN_REQUIRED; decide by the code, not by the message. The widget runs the same check when it starts (unless launcher: false) and hides its button only when limit_exceeded is true.

4. Load the widget lazily

The widget is a sizeable script. To load it only when a shopper first presses your button, use the small loader, https://api.ziex-tryon.com/embed/tryon-loader.js. It defines a global ZiexTryOn with two functions:

  • ZiexTryOn.hasPending(pk) returns true when this browser tab holds a try-on that was sent from an earlier page of your shop and has not been shown yet.
  • ZiexTryOn.load([scriptUrl]) loads the widget script once and returns a Promise that resolves with TryOn. scriptUrl is optional.

A try-on that has been sent is paid for and keeps running when the shopper moves to another page. So the loader must be on every page, and a page where hasPending is true must load the widget at once, without waiting for a click - otherwise the shopper never sees the result:

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

<script src="https://api.ziex-tryon.com/embed/tryon-loader.js"></script>
<script>
  var PK = 'pk_YOUR_PUBLISHABLE_KEY';
  var config = {
    apiKey: PK,
    productImage: 'https://shop.example/images/linen-shirt.jpg',
    productTitle: 'Linen shirt',
    productUrl: 'https://shop.example/p/linen-shirt',
    category: 'tops',
    launcher: false
  };

  var ready = null;
  function widget() {
    if (!ready) {
      ready = ZiexTryOn.load().then(function (t) { t.init(config); return t; });
    }
    return ready;
  }

  if (ZiexTryOn.hasPending(PK)) {
    widget();                                   // picks the earlier try-on up
  }
  document.getElementById('tryon-button').addEventListener('click', function () {
    widget().then(function (t) { t.open(); });  // first click loads, later clicks only open
  });
</script>

While an outcome waits for the shopper, the widget sets data-tryon-ready="result" (or "error") on the <html> element, so your own button can show a dot with a CSS rule on html[data-tryon-ready]. The details of the pickup are on Lazy loading and pickup.

5. Allow the widget under a Content Security Policy

If your site sends a Content-Security-Policy, allow https://api.ziex-tryon.com for scripts and connections and https://media.ziex-tryon.com for images. The exact directives are on the CSP page.

Next steps