Skip to content

Shopify Shoes Try-On App — Storefront Integration

This article explains how the WearFits Try-On app is structured across the three Shopify surfaces it uses, how data flows between them, and what governs whether the "Try On" button is visible to shoppers.


Three Shopify Surfaces

A Shopify app can be composed of up to three types of components. WearFits uses all three.

┌─────────────────────────────────────────────────────────────────┐
│  Shopify Admin                                                   │
│  ┌─────────────────────────────────┐  ┌─────────────────────┐  │
│  │  App Home (embedded iframe)     │  │  Admin Extensions   │  │
│  │  wearfits-tryon/                │  │  (product pages)    │  │
│  │  React Router + Prisma + PG     │  │  Preact + UI Ext.   │  │
│  │  Hosted on Vercel               │  │                     │  │
│  └─────────────────────────────────┘  └─────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│  Storefront (customer-facing)                                    │
│  ┌─────────────────────────────────┐                           │
│  │  Theme Extension                │                           │
│  │  extensions/wearfits-tryon-     │                           │
│  │  button/                        │                           │
│  │  Liquid + vanilla JS            │                           │
│  └─────────────────────────────────┘                           │
└─────────────────────────────────────────────────────────────────┘

1. App Home (wearfits-tryon/)

The primary web application, embedded inside Shopify Admin as an iframe. It hosts the Dashboard, Try-Ons management, Settings, and the onboarding wizard. Built with React Router v7, backed by PostgreSQL via Prisma ORM, and deployed to Vercel.

2. Admin Extensions

Small panels injected into existing Shopify Admin pages — specifically product detail pages. Built with Preact and the Shopify UI Extensions SDK. They display per-product try-on status and allow merchants to enable or disable 3D model processing without leaving the product page.

Two extensions are active: - extensions/admin-block/ — a side panel shown on every product page. - extensions/enable-shoes-tryon/ — a "More actions" menu item for triggering processing.

3. Theme Extension (extensions/wearfits-tryon-button/)

Code injected directly into the merchant's live storefront. Written in Liquid with vanilla JavaScript. This is the component shoppers interact with — it renders the "Try On" button on product pages and handles the AR launch or QR code modal depending on the device type.

The theme extension must be explicitly enabled by the merchant in the Shopify theme editor. See Enabling the Theme Extension below.


Data Flow via Metafields

App Home and the Theme Extension do not communicate directly. The bridge between them is Shopify Metafields: App Home writes values via the Shopify Admin GraphQL API; the Theme Extension reads them via Liquid at page render time.

App Home (backend)
    │  writes via Shopify Admin GraphQL API
Shopify Metafields  ◄──────────────────────────────────────────────┐
    │                                                               │
    │  read by Liquid templates                                     │
    ▼                                                          Admin Extensions
Theme Extension (storefront)                                   read status field
Shopper sees "Try On" button

Metafield Reference

Metafield Namespace Type Written by Read by
product.wearfits.enabled wearfits boolean App Home Theme Extension
product.wearfits.tryon_url wearfits url App Home Theme Extension
product.wearfits.status wearfits text App Home Admin Extensions
shop.wearfits.global_enabled wearfits boolean App Home (Settings, Wizard) Theme Extension
shop.wearfits.button_config wearfits json App Home (Settings) Theme Extension

The button_config JSON field carries appearance settings (button text, style, position, and display options) so the Theme Extension can render the button exactly as configured in Settings without an additional API call.


Button Visibility Rules

The "Try On" button is rendered on a product page only when all three conditions are met simultaneously:

global_enabled == true
    AND
product.wearfits.enabled == true
    AND
product.wearfits.tryon_url is set (non-empty)

If any condition is false — for example, the global toggle is off, the merchant has disabled try-on for that product, or the 3D model has not yet been generated — the button is not rendered and shoppers see no trace of it.


Enabling the Theme Extension

The Theme Extension must be activated once per store in the Shopify theme editor. It does not activate automatically upon app installation.

  1. In Shopify Admin, go to Online Store → Themes.
  2. Click Customize on your active theme.
  3. In the left sidebar, click the App embeds icon (puzzle piece).
  4. Locate WearFits AR Try-On and toggle it on.
  5. Click Save.

The onboarding wizard also guides merchants through this step during initial setup.


Try-On URL Format

When a 3D model is ready, App Home writes the viewer URL to the product metafield in the following format:

https://dev.wearfits.com/tryon?object={objectId}

The objectId is the identifier assigned by the WearFits API when the model is successfully generated. The Theme Extension appends this URL to the AR launch action or embeds it as the QR code target.


External Service Dependencies

Service Base URL Purpose
WearFits API api.wearfits.com (shoe3d) Accepts batches of product images and generates 3D models
WearFits AR Viewer dev.wearfits.com/tryon Hosts the browser-based AR viewer that shoppers use

The app does not self-host 3D models or the AR renderer — both are provided by WearFits infrastructure.


3D Model Generation Flow

Model generation is asynchronous and driven by a background cron job. The merchant does not need to take any action after initial setup.

┌─────────────────────────────────────────────────────────────┐
│ Cron Job                                                     │
│   POST /api/sync-batches  (periodic trigger)                 │
└────────────────┬────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ App Home                                                     │
│   1. Query DB for products with status: pending             │
│   2. Group products into a batch                            │
│   3. Upload product images to WearFits API                  │
│   4. Receive batch_id from WearFits API                     │
│   5. Set product status: processing in DB                   │
└────────────────┬────────────────────────────────────────────┘
                 │  (on next cron tick)
┌─────────────────────────────────────────────────────────────┐
│ App Home                                                     │
│   6. Poll WearFits API: GET batch status by batch_id        │
│   7. For completed jobs: write tryon_url to product         │
│      metafield via Shopify Admin GraphQL API                │
│   8. Update product status: ready in DB                     │
└─────────────────────────────────────────────────────────────┘

Sequence diagram:

Cron Job       App Home          WearFits API      Shopify API       DB
    │               │                  │                 │            │
    │─POST /api/────►│                  │                 │            │
    │  sync-batches  │                  │                 │            │
    │               │──query pending────────────────────────────────►│
    │               │◄──product list────────────────────────────────│
    │               │──upload images──►│                 │            │
    │               │◄──batch_id───────│                 │            │
    │               │──set processing───────────────────────────────►│
    │               │                  │                 │            │
    │  (next tick)  │                  │                 │            │
    │─POST /api/────►│                  │                 │            │
    │  sync-batches  │                  │                 │            │
    │               │──get batch ─────►│                 │            │
    │               │  status          │                 │            │
    │               │◄──completed/─────│                 │            │
    │               │  failed + urls   │                 │            │
    │               │──write metafields────────────────►│            │
    │               │──set ready────────────────────────────────────►│

Database Models Involved

Model Role in the flow
Product Tracks per-product status (pending, processing, ready, failed) and stores the final tryOnViewerUrl
WearFitsBatch Represents one batch submission to the WearFits API; holds the external wearfitsBatchId
WearFitsJob Represents one product within a batch; links Product to WearFitsBatch and stores the job-level status and URL

Application Tech Stack Summary

Layer Technology
App Home (server) React Router v7, TypeScript, Prisma ORM
Database PostgreSQL
Hosting Vercel
Admin Extensions Preact, Shopify UI Extensions SDK
Theme Extension Liquid, vanilla JavaScript
Shopify integration @shopify/shopify-app-react-router, App Bridge, Admin GraphQL API
AI image analysis OpenRouter (classifies product images as shoe / non-shoe)
CRM integration HubSpot API (quality tickets from merchant reports)