Merchant documentation

Embed the AI Sizer widget on your store, use the sizes it returns, and verify the flow end to end.

Overview

Add one script tag to your storefront. Shoppers measure on iPhone; your store receives their size labels to filter the catalog (optional built-in markup, or your own logic). Measurement runs on the AI Sizer platform — your site embeds the widget and decides how to use the sizes.

See the demo store for a working glasses and footwear catalog example. The custom shoe generator uses the same footwear widget to build a 3D-printable pair from the scan.

What you need from AI Sizer

Before integrating, ask your AI Sizer contact (platform operator) for:

  • Platform URL — e.g. https://aisizer.com (used for both the script src and data-api-base)
  • Publishable API key — sz_pk_… for data-api-key

Keys are created in the platform admin panel by the operator — not something you generate on your store. Optionally they can assign a widget theme (banner colors) to your key.

Widget embed

Place an empty mount element before the script. Use a static <script> tag (not injected later) so data-* attributes are read reliably.

Glasses

<div id="sizer-widget-mount"></div>

<script
  src="https://YOUR_PLATFORM/widget/v1/sizer-widget.js"
  data-api-base="https://YOUR_PLATFORM"
  data-api-key="sz_pk_…"
  data-category="glasses"
  data-return-path="/shop/glasses"
  async
></script>

Footwear — same pattern with data-category="footwear" and your footwear return path:

<div id="sizer-widget-mount"></div>

<script
  src="https://YOUR_PLATFORM/widget/v1/sizer-widget.js"
  data-api-base="https://YOUR_PLATFORM"
  data-api-key="sz_pk_…"
  data-category="footwear"
  data-return-path="/shop/footwear"
  async
></script>

After a successful measure, the banner shows the shopper’s sizes. Catalog filtering is optional — see below.

Script attributes

AttributeRequiredPurpose
data-api-baseYesPlatform origin from your AI Sizer contact. Must match the script host.
data-api-keyYesPublishable key (sz_pk_…) from your AI Sizer contact.
data-categoryNoglasses (default) or footwear.
data-mount-selectorNoWhere the banner mounts (default #sizer-widget-mount).
data-return-pathNoPath on your store after measurement (default /), e.g. /shop/glasses.
data-catalog-selectorNoProduct list selector for built-in filtering only (default #glasses-list). Not needed if you filter via events.

What you receive

You do not call sizing APIs yourself. After a shopper measures (or returns with a saved size), the widget updates its banner and fires sizer:size-ready on window. How (or whether) the catalog filters is up to you.

Shown in the widget banner

Size labels only — e.g. Your sizes: L (glasses) or Your sizes: 46 EU · 11 US (footwear). Raw millimetre metrics are not displayed in the banner.

Event payload (sizer:size-ready)

Use this for catalog filtering and for your own fitting logic. Labels match product tags; millimetre fields are available when the category provides them.

// Glasses
{
  "category": "glasses",
  "sizes": [{ "label": "L", "displayLabel": "L" }],
  "headWidthMm": 151,
  "pupillaryDistanceMm": 65
}

// Footwear
{
  "category": "footwear",
  "sizes": [
    { "label": "46", "displayLabel": "46 EU" },
    { "label": "11", "displayLabel": "11 US" }
  ],
  "footLengthMm": 273,
  "footWidthMm": 97,
  "leftFoot": { "lengthMm": 270, "widthMm": 95 },
  "rightFoot": { "lengthMm": 273, "widthMm": 97 }
}
FieldWhenNotes
categoryAlwaysglasses or footwear
sizes[].labelAlwaysMatch products on this (e.g. L, 46). Also what the banner uses.
sizes[].displayLabelAlwaysShopper-facing string (e.g. 46 EU). Do not use for matching.
headWidthMmGlassesHead width (mm). Not shown in banner — for custom fitting.
pupillaryDistanceMmGlassesPupillary distance / PD (mm). Not shown in banner — for custom fitting.
footLengthMmFootwearMax foot length across scanned feet (mm). Size lookup and catalog filtering use this. Not shown in banner.
footWidthMmFootwearMax foot width across scanned feet (mm). Not shown in banner.
leftFoot / rightFootFootwearPer-foot { lengthMm, widthMm }. Not shown in banner — for custom fitting later.

Labels to match on products: glasses XS–XL; footwear EU/US numbers such as 46, 11.

Catalog filtering

Catalog filtering is optional. Choose built-in DOM filtering, your own logic, both, or events only for analytics.

Option A — Built-in (optional)

Point data-catalog-selector at your product list and tag each row with data-product-id + data-sizes. The widget hides non-matching rows. Skip this if you prefer Option B.

<ul id="glasses-list">
  <li data-product-id="g1" data-sizes="XS,S,M">Shield Pro Clear</li>
  <li data-product-id="g2" data-sizes="L,XL">Wide Fit</li>
</ul>

<script
  src="https://YOUR_PLATFORM/widget/v1/sizer-widget.js"
  data-api-base="https://YOUR_PLATFORM"
  data-api-key="sz_pk_…"
  data-category="glasses"
  data-catalog-selector="#glasses-list"
  data-return-path="/shop/glasses"
  async
></script>

Option B — Your own filter (SPAs / custom catalogs)

Keep your existing product markup. When sizes arrive, match any product size against the shopper’s labels:

window.addEventListener("sizer:size-ready", (e) => {
  const {
    category,
    sizes,
    headWidthMm,
    pupillaryDistanceMm,
    footLengthMm,
    footWidthMm,
    leftFoot,
    rightFoot,
  } = e.detail;

  // Built-in labels (also on the banner)
  const labels = new Set(sizes.map((s) => s.label)); // "L" or "46", "11"

  document.querySelectorAll("[data-product-id]").forEach((el) => {
    const productSizes = (el.getAttribute("data-sizes") || "")
      .split(",")
      .map((s) => s.trim())
      .filter(Boolean);
    const match =
      productSizes.length === 0 || productSizes.some((s) => labels.has(s));
    el.hidden = !match;
  });

  // Optional: your own fitting using mm metrics (not shown in the widget)
  if (category === "glasses") {
    // headWidthMm, pupillaryDistanceMm
  }
  if (category === "footwear") {
    // leftFoot / rightFoot raw mm; footLengthMm / footWidthMm are max across feet
  }
});

window.addEventListener("sizer:size-clear", () => {
  document.querySelectorAll("[data-product-id]").forEach((el) => {
    el.hidden = false;
  });
});

You can use both options, either alone, or listen only for analytics with no catalog change.

Store origin (allowlist)

Your store’s origin must be allowlisted on the AI Sizer platform or the browser blocks the widget. You do not configure this yourself — send your live store origin(s) to your AI Sizer contact, for example:

https://your-store.example.com
https://www.your-store.example.com

Use the full origin (scheme + host, no path). They will add it on the platform and redeploy. Until that is done, the widget may show Sizing service unavailable.

Verify integration

  1. Confirm you have platform URL + API key, and your store origin is allowlisted
  2. Open your store over HTTPS (or LAN IP in local dev)
  3. Confirm the widget banner appears (not the red unavailable state)
  4. Complete a measurement on iPhone
  5. Confirm the banner shows sizes and your catalog filter (A and/or B) works