@aabhastech/shopify-vto
v0.1.6
Published
Typed, performance-budgeted virtual try-on SDK for Shopify Hydrogen storefronts.
Maintainers
Readme
Aabhas VTO for Shopify Hydrogen
A typed, performance-budgeted virtual try-on SDK for custom Shopify Hydrogen storefronts.
Get started · Integration guide · API entry points · Security
@aabhastech/shopify-vto brings the Aabhas virtual try-on experience to
headless Shopify storefronts. It provides the server exchange, storefront
client, React launchers, consent handling, image crop flow, synchronous VTO
execution, analytics, saved-photo reuse, and cart-line attribution needed for
a Hydrogen integration.
This package is for Shopify Hydrogen/headless storefronts. Shopify Liquid themes should use the Aabhas theme app extension instead.
Capabilities
- Server-authenticated product eligibility and storefront session exchange.
- SSR-safe React provider, embedded CTA, and singleton floating launcher.
- Lazy-loaded crop, progress, saved-photo, and result UI.
- Viewport-safe generation countdown that remains visible after crop/upload.
- Device-local saved-photo reuse with legacy cache-key migration.
persistand privacy-preservingno_storemedia flows.- Short-lived, exact-origin storefront tokens kept in memory.
- Consent-aware analytics and VTO cart-line attribution.
- Typed contracts shared with the Aabhas storefront API.
- Explicit bundle-size budgets for initial and interactive code.
Quick start
npm install @aabhastech/shopify-vtoYour Aabhas installation credential must stay in the Hydrogen server runtime. Use it to check eligibility and exchange a short-lived storefront session:
import {
checkEligibility,
exchangeSession,
} from '@aabhastech/shopify-vto/core/server';
const serverConfig = {
backendBaseUrl: context.env.AABHAS_BACKEND_BASE_URL,
installationCredential: context.env.AABHAS_INSTALLATION_CREDENTIAL,
};
const eligibility = await checkEligibility(serverConfig, {
shopDomain: context.env.PUBLIC_STORE_DOMAIN,
productId: product.id,
variantId: variant.id,
});
const session = eligibility.eligible
? await exchangeSession(serverConfig, {
requestOrigin: new URL(request.url).origin,
anonymousSessionId,
})
: null;In the storefront, provide the public configuration and lazy-load the interactive runtime only after the shopper opens VTO:
import {lazy, Suspense} from 'react';
import {
VtoEmbeddedCta,
VtoProvider,
} from '@aabhastech/shopify-vto/hydrogen';
const VtoRuntime = lazy(() => import('./AabhasVtoRuntime.client'));
export function ProductVto({config, open, setOpen}) {
return (
<VtoProvider config={config}>
<VtoEmbeddedCta label="Try it on" onClick={() => setOpen(true)} />
{open ? (
<Suspense fallback={<span role="status">Loading virtual try-on...</span>}>
<VtoRuntime onClose={() => setOpen(false)} />
</Suspense>
) : null}
</VtoProvider>
);
}The complete reference implementation includes session persistence, Shopify customer privacy integration, crop and upload handling, token refresh, result rendering, and cart attribution:
View the Hydrogen integration example
Requirements
- Shopify Hydrogen with React 18 or 19.
- An active Aabhas installation configured for the storefront origin.
- ESM-based application tooling. CommonJS applications must use dynamic
import(). - A durable anonymous session ID stored in the Hydrogen server session.
- CSP access to the configured Aabhas backend and result-media host.
Modern npm clients install the compatible @aabhastech/contracts peer
automatically. Other package managers should install the exact peer version
reported during installation.
Integration
Hydrogen loader
-> Aabhas eligibility check
-> short-lived storefront token exchange
Hydrogen browser
-> bootstrap product configuration
-> upload/crop or reuse customer photo
-> synchronous VTO execution
-> render result and attach attribution to cart lineUse Shopify GIDs returned by the Storefront API for product, variant, and media values. The browser must not provide garment URLs, organization IDs, template IDs, license keys, workflow variables, or the installation credential.
The reference integration expects these environment values:
| Variable | Exposure | Purpose |
| --- | --- | --- |
| AABHAS_BACKEND_BASE_URL | Server only | Backend used for eligibility and session exchange |
| AABHAS_INSTALLATION_CREDENTIAL | Server only | Installation authentication; never expose to the browser |
| PUBLIC_AABHAS_BACKEND_BASE_URL | Public | Storefront API base URL |
| PUBLIC_STOREFRONT_API_TOKEN | Public | Shopify customer privacy integration |
| PUBLIC_CHECKOUT_DOMAIN | Public | Shopify checkout domain |
API entry points
| Import | Runtime | Purpose |
| --- | --- | --- |
| @aabhastech/shopify-vto/core/server | Server | Eligibility check and storefront-session exchange |
| @aabhastech/shopify-vto/core | Browser/framework-neutral | API client, types, image helpers, idempotency, errors, analytics |
| @aabhastech/shopify-vto/hydrogen | React, pre-interaction | Provider, launchers, consent, analytics, cart attribution |
| @aabhastech/shopify-vto/hydrogen/analytics | React application root | Shopify Hydrogen analytics bridge and typed custom-event API |
| @aabhastech/shopify-vto/hydrogen/runtime | Lazy browser chunk | Crop, saved photo, execution, progress, and result UI |
Analytics integration
Mount the Aabhas provider once below Shopify's Analytics.Provider. It
subscribes to Shopify Hydrogen's semantic analytics bus, so route, product,
collection, search, cart-view, add-to-cart, and remove-from-cart events flow to
Aabhas without duplicating event calls in each route.
import {Analytics} from '@shopify/hydrogen';
import {AabhasAnalyticsProvider} from '@aabhastech/shopify-vto/hydrogen/analytics';
<Analytics.Provider cart={cart} shop={shop} consent={consent}>
<AabhasAnalyticsProvider
config={{
analyticsEndpoint: `${env.PUBLIC_AABHAS_BACKEND_BASE_URL}/storefront/v1/analytics/events`,
refreshStorefrontSession: async () => {
const response = await fetch('/vto-session', {method: 'POST'});
if (!response.ok) throw new Error('Aabhas storefront session refresh failed');
return response.json();
},
}}
>
<Outlet />
</AabhasAnalyticsProvider>
</Analytics.Provider>The bridge uses Shopify's Customer Privacy decision through canTrack().
Events are suppressed until analytics consent is available. Do not substitute
photo-processing consent for analytics consent.
For actions Shopify cannot publish automatically, use the typed API:
import {useAabhasAnalytics} from '@aabhastech/shopify-vto/hydrogen/analytics';
function CheckoutButton() {
const analytics = useAabhasAnalytics();
return (
<button onClick={() => {
analytics.track('checkout_started');
void analytics.flush();
window.location.assign('/checkout');
}}>
Checkout
</button>
);
}VTO execution events are emitted by the SDK runtime. Use track() for custom
UI boundaries such as CTA exposure/click, photo selection, crop completion,
result display, or VTO add-to-cart. trackOnce(key, event, fields) is available
for React exposure effects that must not double count.
Purchases, revenue, refunds, returns, and RTO are not accepted from browser
telemetry as final truth. They come from verified Shopify webhooks and Admin
commerce reconciliation. Preserve the _aabhas_vton cart-line attribute so
orders can be attributed exactly to a VTO result.
Performance
The SDK separates the pre-interaction surface from the interactive runtime so product pages do not load crop and execution code until VTO is opened.
Current release gates, measured minified and Brotli-compressed:
| Entry | Current size | Budget | | --- | ---: | ---: | | Core | 2.87 KB | 8 KB | | Core server | 443 B | 4 KB | | Hydrogen pre-interaction | 3.04 KB | 6 KB | | Hydrogen lazy runtime | 7.02 KB | 12 KB |
The package is tree-shakeable, ESM-only, and declares no side effects.
Security and privacy
- Keep
AABHAS_INSTALLATION_CREDENTIALserver-only. - Storefront bearer tokens are short-lived and retained in memory only.
- Add only the configured Aabhas backend to CSP
connect-src. - Allow
data:in CSPimg-srcwhen usingno_storeresults. no_storecustomer images and results remain inline and are not uploaded.- In
persistmode, treat a signed-upload failure as an upload failure. Do not fall back to inline execution; inline customer media is reserved forno_storemode. - Analytics failures do not block VTO, and events emit only with consent.
- Expired or lifecycle-invalidated storefront tokens are refreshed once through the configured same-origin session route. Analytics delivery failures never block the VTO UI.
Validation
npm test
npm run typecheck
npm run build
npm run size
npm run lintSupport
- Integration assistance: aabhas.tech
- Source and issues: AabhasTech/aabhas-shopify-app
- Package: npmjs.com/package/@aabhastech/shopify-vto
