Shopify integration guide
Add virtual glasses try-on to your Shopify store with two Liquid snippets and one theme settings block. After setup, merchants only paste their Tryonixs API key once — the "Try On Virtually" button appears automatically on every product page.
One-time setup
Paste your pk_live_ key in Theme settings. No per-product code edits.
Smart frame images
Uses metafield, theme default, or product featured image automatically.
Self-contained SDK
Embedded loader talks to https://tryonixs.com — no external script tag.
What you get
- tryonixs-sdk.liquid — SDK loader, initializer, modal, analytics, and automatic button injection on product pages.
- tryonixs-button.liquid — Optional manual button for custom placement in your product template.
- Theme settings — API key, button label, validation toggle, default frame URL, and category.
Reference files live in integrations/shopify/ in the Tryonixs repository.
Setup steps
Copy your Tryonixs public key
Dashboard → Integration → copy your pk_live_... key. Whitelist your Shopify store domain in Tryonixs settings if required.
Add theme settings
Online Store → Themes → Edit code → config/settings_schema.json. Paste the Tryonixs settings block from the docs.
Install Liquid snippets
Create snippets/tryonixs-sdk.liquid and snippets/tryonixs-button.liquid with the files from this repo (integrations/shopify/snippets/).
Include the SDK in theme.liquid
Add {% render 'tryonixs-sdk' %} once before </body>. The try-on button is injected automatically on every product page.
Paste your API key in theme settings
Theme editor → Theme settings → Tryonixs AR Try-On → paste API key and save. No per-product editing required.
1. Theme settings schema
In Shopify Admin go to Online Store → Themes → Edit code. Open config/settings_schema.json and append this block to the root array (add a comma after the previous entry if needed):
{
"name": "Tryonixs AR Try-On",
"settings": [
{
"type": "header",
"content": "Tryonixs virtual try-on"
},
{
"type": "paragraph",
"content": "Get your public API key from the Tryonixs dashboard (Dashboard → Integration). App URL is always https://tryonixs.com."
},
{
"type": "checkbox",
"id": "tryonix_enabled",
"label": "Enable Tryonixs try-on",
"default": true
},
{
"type": "text",
"id": "tryonix_api_key",
"label": "Tryonixs public API key",
"info": "Your pk_live_... key from the Tryonixs dashboard."
},
{
"type": "text",
"id": "tryonix_button_label",
"label": "Button label",
"default": "Try On Virtually"
},
{
"type": "checkbox",
"id": "tryonix_skip_validation",
"label": "Skip SDK validation (development only)",
"default": false,
"info": "When enabled, try-on opens without calling the validate API. Keep disabled for production so product limits and domain allowlists are enforced."
},
{
"type": "text",
"id": "tryonix_default_frame_url",
"label": "Default frame image URL (optional)",
"info": "Fallback transparent PNG used when a product has no custom metafield. Leave blank to use each product's featured image."
},
{
"type": "text",
"id": "tryonix_default_category",
"label": "Default product category",
"default": "eyeglasses"
}
]
}
2. Install Liquid snippets
Create two files under snippets/ and paste the contents below.
{% comment %}
Tryonixs SDK Loader, Initializer & Auto Button Injector
Setup (merchant only needs to do this ONCE):
1. Theme editor → Theme settings → "Tryonixs AR Try-On" → paste your API Key.
2. Make sure this snippet is included once in theme.liquid, right before </body>:
{% render 'tryonixs-sdk' %}
That's it. The "Try On Virtually" button is then injected automatically on
EVERY product page. No per-product editing required.
Frame image passed to the SDK (same as the HTML demo's data-image-url):
1. Product metafield tryonixs.frame_image_url (optional — custom transparent PNG)
2. Theme setting default frame URL (optional fallback)
3. Product featured image from Shopify (automatic — works on every product)
{% endcomment %}
{% if settings.tryonix_enabled and settings.tryonix_api_key != blank %}
{% if product %}
{% assign tryonix_product_image = product.metafields.tryonixs.frame_image_url.value %}
{% if tryonix_product_image == blank %}
{% assign tryonix_product_image = settings.tryonix_default_frame_url %}
{% endif %}
{% if tryonix_product_image == blank and product.featured_media %}
{% assign tryonix_product_image = product.featured_media | image_url: width: 1200 %}
{% elsif tryonix_product_image == blank and product.featured_image %}
{% assign tryonix_product_image = product.featured_image | image_url: width: 1200 %}
{% endif %}
{% endif %}
<script src="https://tryonixs.com/tryonixs-sdk.js?v=1.2.0" defer crossorigin="anonymous"></script>
<script>
/* Tryonixs auto-init + auto button injection (runs on every product page) */
;(function (window, document) {
'use strict'
var API_KEY = {{ settings.tryonix_api_key | json }};
var BTN_LABEL = {{ settings.tryonix_button_label | default: 'Try On Virtually' | json }};
var SKIP_VALIDATION = {{ settings.tryonix_skip_validation | default: false | json }};
{% if product %}
var PRODUCT = {
productId: {{ product.id | json }},
productName: {{ product.title | json }},
imageUrl: {{ tryonix_product_image | default: '' | json }},
category: {{ product.metafields.tryonixs.category.value | default: settings.tryonix_default_category | default: 'eyeglasses' | json }}
};
{% else %}
var PRODUCT = null;
{% endif %}
function initSdk() {
if (!window.Tryonixs) return false;
try {
window.Tryonixs.init({ apiKey: API_KEY });
if (SKIP_VALIDATION) {
window.Tryonixs.setConfig({ skipValidation: true });
}
} catch (e) {
console.error('Tryonixs:', e.message);
return false;
}
return true;
}
function getCurrentProductImageUrl() {
var selectors = [
'.product__media-item.is-active img',
'.product-media-container__item.is-active img',
'.product__modal-opener--image img',
'.product__main-photos img',
'.product-single__photo img',
'[data-product-featured-media] img',
'.product__media img',
'.product-media img',
'media-gallery img'
];
for (var i = 0; i < selectors.length; i++) {
var img = document.querySelector(selectors[i]);
if (img && (img.currentSrc || img.src)) {
return img.currentSrc || img.src;
}
}
return PRODUCT ? PRODUCT.imageUrl : '';
}
function openTryonFromElement(el) {
if (!window.Tryonixs || !PRODUCT) return;
var imageUrl = el.getAttribute('data-image-url') ||
el.getAttribute('data-tryonixs-image') ||
getCurrentProductImageUrl() ||
PRODUCT.imageUrl;
if (!imageUrl) {
console.warn('Tryonixs: no product image found for this product.');
return;
}
window.Tryonixs.open({
apiKey: API_KEY,
skipValidation: SKIP_VALIDATION,
productId: el.getAttribute('data-product-id') || String(PRODUCT.productId),
productName: el.getAttribute('data-product-name') || PRODUCT.productName,
imageUrl: imageUrl,
category: el.getAttribute('data-tryonixs-category') || PRODUCT.category,
onSuccess: function (data) {
document.dispatchEvent(new CustomEvent('tryonixs:success', { detail: data }));
},
onError: function (err) {
console.error('Tryonixs error:', err.message);
}
});
}
function openTryon() {
var btn = document.querySelector('.tryonixs-button[data-tryonixs="true"]');
if (btn) {
var liveImage = getCurrentProductImageUrl();
if (liveImage) btn.setAttribute('data-image-url', liveImage);
openTryonFromElement(btn);
return;
}
openTryonFromElement({ getAttribute: function(name) {
if (name === 'data-product-id') return String(PRODUCT.productId);
if (name === 'data-product-name') return PRODUCT.productName;
if (name === 'data-image-url') return getCurrentProductImageUrl() || PRODUCT.imageUrl;
if (name === 'data-tryonixs-category') return PRODUCT.category;
return null;
}});
}
function buildButton() {
var btn = document.createElement('button');
btn.type = 'button';
btn.className = 'tryonixs-tryon-btn tryonixs-button';
btn.setAttribute('data-tryonixs', 'true');
btn.setAttribute('data-product-id', String(PRODUCT.productId));
btn.setAttribute('data-product-name', PRODUCT.productName);
btn.setAttribute('data-image-url', PRODUCT.imageUrl);
btn.textContent = BTN_LABEL;
btn.style.cssText = [
'display:inline-flex',
'align-items:center',
'justify-content:center',
'gap:8px',
'width:100%',
'margin:12px 0',
'padding:14px 24px',
'background:#000',
'color:#fff',
'border:none',
'border-radius:8px',
'font-size:15px',
'font-weight:600',
'cursor:pointer',
'letter-spacing:0.3px',
"font-family:inherit",
'transition:background 0.2s, transform 0.1s'
].join(';');
btn.addEventListener('mouseenter', function () { btn.style.background = '#222'; });
btn.addEventListener('mouseleave', function () { btn.style.background = '#000'; });
btn.addEventListener('mousedown', function () { btn.style.transform = 'scale(0.98)'; });
btn.addEventListener('mouseup', function () { btn.style.transform = 'scale(1)'; });
btn.addEventListener('click', function (e) { e.preventDefault(); openTryon(); });
return btn;
}
function findAnchor() {
var selectors = [
'.product-form__buttons',
'form[action*="/cart/add"] .product-form__buttons',
'form[action*="/cart/add"] [name="add"]',
'form[action*="/cart/add"] button[type="submit"]',
'product-form',
'form[action*="/cart/add"]',
'.product-form',
'.product__info-container',
'.product-single__meta',
'.product__info'
];
for (var i = 0; i < selectors.length; i++) {
var el = document.querySelector(selectors[i]);
if (el) return el;
}
return null;
}
function injectButton() {
if (!PRODUCT) return;
if (!PRODUCT.imageUrl) {
console.warn('Tryonixs: no product image for this product. Add a featured image in Shopify admin.');
return;
}
if (document.querySelector('.tryonixs-button, .tryonixs-tryon-btn')) return;
var btn = buildButton();
var anchor = findAnchor();
if (anchor) {
if (anchor.parentNode) {
anchor.parentNode.insertBefore(btn, anchor.nextSibling);
} else {
anchor.appendChild(btn);
}
} else {
var wrap = document.createElement('div');
wrap.style.cssText = 'position:fixed;right:16px;bottom:16px;z-index:99998;max-width:220px;';
btn.style.width = 'auto';
btn.style.boxShadow = '0 6px 20px rgba(0,0,0,0.25)';
wrap.appendChild(btn);
document.body.appendChild(wrap);
}
}
function start() {
var ready = initSdk();
if (!ready) {
var tries = 0;
var t = setInterval(function () {
tries++;
ready = initSdk();
if (ready || tries > 20) {
clearInterval(t);
if (ready) injectButton();
else console.error('Tryonixs: SDK failed to initialize. Check your API key in Theme settings.');
}
}, 100);
return;
}
injectButton();
}
window.__tryonixOpenFromButton = function (btn) {
if (!window.Tryonixs) { console.error('Tryonixs SDK not loaded.'); return; }
var liveImage = getCurrentProductImageUrl();
if (liveImage) btn.setAttribute('data-image-url', liveImage);
openTryonFromElement(btn);
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
})(window, document);
</script>
{% endif %}
{% comment %}
Tryonixs AR Try-On Button (OPTIONAL / MANUAL placement)
Usage: {% render 'tryonixs-button', product: product %}
Image URL (same order as HTML demo data-image-url):
1. tryonixs.frame_image_url metafield (optional custom PNG)
2. Theme default frame URL
3. Product featured image (automatic)
{% endcomment %}
{% assign tryonix_image_url = product.metafields.tryonixs.frame_image_url.value %}
{% if tryonix_image_url == blank %}
{% assign tryonix_image_url = settings.tryonix_default_frame_url %}
{% endif %}
{% if tryonix_image_url == blank and product.featured_media %}
{% assign tryonix_image_url = product.featured_media | image_url: width: 1200 %}
{% elsif tryonix_image_url == blank and product.featured_image %}
{% assign tryonix_image_url = product.featured_image | image_url: width: 1200 %}
{% endif %}
{% assign tryonix_category = product.metafields.tryonixs.category.value | default: settings.tryonix_default_category | default: 'eyeglasses' %}
{% assign tryonix_product_id = product.metafields.tryonixs.product_id.value | default: product.id %}
{% if settings.tryonix_enabled and settings.tryonix_api_key != blank and tryonix_image_url != blank %}
<div class="tryonixs-wrapper" style="margin: 12px 0;">
<button
type="button"
class="tryonixs-tryon-btn tryonixs-button"
data-product-id="{{ tryonix_product_id }}"
data-product-name="{{ product.title | escape }}"
data-image-url="{{ tryonix_image_url | escape }}"
data-tryonixs-image="{{ tryonix_image_url | escape }}"
data-tryonixs-product-id="{{ tryonix_product_id }}"
data-tryonixs-product-name="{{ product.title | escape }}"
data-tryonixs-category="{{ tryonix_category | escape }}"
onclick="window.__tryonixOpenFromButton(this)"
style="
display: inline-flex;
align-items: center;
gap: 8px;
padding: 12px 24px;
background: #000;
color: #fff;
border: none;
border-radius: 8px;
font-size: 15px;
font-weight: 600;
cursor: pointer;
letter-spacing: 0.3px;
transition: background 0.2s, transform 0.1s;
"
onmouseenter="this.style.background='#222'"
onmouseleave="this.style.background='#000'"
onmousedown="this.style.transform='scale(0.97)'"
onmouseup="this.style.transform='scale(1)'"
>
{{ settings.tryonix_button_label | default: 'Try On Virtually' }}
</button>
</div>
{% endif %}
3. Include in theme.liquid
Open layout/theme.liquid and add this line once, right before </body>:
{% comment %} Add once in layout/theme.liquid, before </body> {% endcomment %}
{% render 'tryonixs-sdk' %}4. Paste your API key
Open the theme editor → Theme settings → Tryonixs AR Try-On. Enable Tryonixs, paste your pk_live_... public key from the Tryonixs dashboard, and save. Visit any product page — the try-on button should appear below Add to cart (or as a floating button if your theme layout differs).
Frame image resolution
The SDK passes an imageUrl to Tryonixs using this priority (same as the HTML data-image-url attribute):
- Product metafield
tryonixs.frame_image_url— custom transparent PNG (best for AR) - Theme setting Default frame image URL — store-wide fallback
- Product featured image — automatic; works on every product with a photo
Tip for best AR fit
frame_image_url metafield per product.Optional product metafields
# Product metafields (optional — Shopify Admin → Settings → Custom data → Products)
Namespace: tryonixs
| Key | Type | Purpose |
|------------------|-------------|----------------------------------------------|
| frame_image_url | URL | Custom transparent PNG for AR overlay |
| category | Single line | e.g. eyeglasses, sunglasses (default: theme) |
| product_id | Single line | Override Shopify product ID for analytics |
Frame image resolution order (same as HTML data-image-url):
1. tryonixs.frame_image_url metafield
2. Theme setting "Default frame image URL"
3. Product featured image (automatic — works on every product)
Create these in Shopify Admin → Settings → Custom data → Products. Namespace: tryonixs.
Manual button placement (optional)
By default, tryonixs-sdk.liquid injects the button automatically. To place it yourself — for example in sections/main-product.liquid — use:
{% comment %} Optional: place anywhere on the product template {% endcomment %}
{% render 'tryonixs-button', product: product %}The manual button calls window.__tryonixOpenFromButton, which is registered by the SDK snippet. It also reads the currently selected variant image from common Dawn-compatible selectors.
Theme settings reference
tryonix_enabledCheckboxMaster on/off switchtryonix_api_keyTextYour pk_live_... public keytryonix_button_labelTextButton label (default: Try On Virtually)tryonix_skip_validationCheckboxSkip SDK validation (default: false — dev only)tryonix_default_frame_urlTextOptional store-wide frame PNG URLtryonix_default_categoryTextDefault category (default: eyeglasses)Troubleshooting
The try-on button does not appear on product pages.
Confirm tryonix_enabled is on, tryonix_api_key is set, the product has a featured image (or metafield/default frame URL), and {% render 'tryonixs-sdk' %} is in theme.liquid before </body>.
Glasses image looks wrong or stretched.
Upload a transparent PNG with only the frame (no model face). Set tryonixs.frame_image_url on the product for a dedicated AR asset instead of the storefront photo.
Tryonixs: validation failed and try-on did not open.
Confirm your API key is active, your Shopify domain is listed in Dashboard → Settings → Allowed SDK domains, and tryonix_skip_validation is disabled in theme settings.
Camera works on desktop but not iPhone Safari.
Shopify themes must serve the store over HTTPS. Open try-on only after tapping the button — Safari blocks camera access without a direct user gesture.
I want the button in a custom position.
Disable auto-injection by removing product-page logic from tryonixs-sdk.liquid, or add {% render 'tryonixs-button', product: product %} where you want the button in your product template.
Need your API key?
Sign up for Tryonixs, open Dashboard → Integration, and copy your public key. Whitelist your *.myshopify.com or custom domain if domain restrictions are enabled.