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 working glasses, footwear, and gloves catalog examples. The custom shoe generator uses the same footwear widget to build a 3D-printable pair from the scan.

What you need from AI Sizer

The widget always loads from the AI Sizer platform (https://aisizer.com) — not from your store domain. Before integrating:

  1. Send your store origin(s) to your AI Sizer contact for CORS allowlisting — full origin only (scheme + host, no path), e.g. https://example.com. See Store origin.
  2. Receive a publishable API key (sz_pk_…) from them. Keys are created in the platform admin panel by the operator — you do not generate one on your store. Optionally they assign a widget theme (banner colors) to your key.
  3. Paste that key into data-api-key in the embed snippet below. Keep src and data-api-base pointed at https://aisizer.com.

Widget embed

Place an empty mount element before the script. Use a static <script> tag (not injected later) so data-* attributes are read reliably. Replace sz_pk_… with the key from your AI Sizer contact. Leave the aisizer.com URLs as-is.

Glasses

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

<script
  src="https://aisizer.com/widget/v1/sizer-widget.js"
  data-api-base="https://aisizer.com"
  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://aisizer.com/widget/v1/sizer-widget.js"
  data-api-base="https://aisizer.com"
  data-api-key="sz_pk_…"
  data-category="footwear"
  data-return-path="/shop/footwear"
  async
></script>

Gloves — data-category="gloves" and your gloves return path:

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

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

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

Script attributes

AttributeRequiredPurpose
data-api-baseYesAI Sizer platform origin — use https://aisizer.com (must match the script host). Not your store URL.
data-api-keyYesPublishable key (sz_pk_…) issued by AI Sizer admin after they allowlist your store origin.
data-categoryNoglasses (default), footwear, or gloves.
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: 44 EU · 10 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 (Nike men's chart)
{
  "category": "footwear",
  "sizes": [
    { "label": "44", "displayLabel": "44 EU" },
    { "label": "10", "displayLabel": "10 US" }
  ],
  "footLengthMm": 273,
  "footWidthMm": 97,
  "leftFoot": { "lengthMm": 270, "widthMm": 95 },
  "rightFoot": { "lengthMm": 273, "widthMm": 97 }
}
FieldWhenNotes
categoryAlwaysglasses, footwear, or gloves
sizes[].labelAlwaysMatch products on this (e.g. L, 44). Also what the banner uses.
sizes[].displayLabelAlwaysShopper-facing string (e.g. 44 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; gloves S–XXL.

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://aisizer.com/widget/v1/sizer-widget.js"
  data-api-base="https://aisizer.com"
  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 (the same person who issues your API key), for example:

https://example.com
https://www.example.com

Use the full origin (scheme + host, no path). They add it in the platform admin CORS allowlist, then send you the sz_pk_… key to put in data-api-key. Until the origin is allowlisted and the key is set, the widget may show Sizing service unavailable.

Verify integration

  1. Confirm you sent your store origin to AI Sizer admin, received a sz_pk_… key, and set it on data-api-key (with https://aisizer.com in src / data-api-base)
  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