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.
- In Shopify Admin, go to Online Store → Themes.
- Click Customize on your active theme.
- In the left sidebar, click the App embeds icon (puzzle piece).
- Locate WearFits AR Try-On and toggle it on.
- 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:
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) |