The Macgi widget is one script tag: about 15 KB, no dependencies, and it runs in a Shadow DOM so it never touches your styles. This page covers any website where you can add HTML. On Haravan, Sapo, WooCommerce or Shopify, see the platform guides.
Get a key
Each store has a publishable key like pk_live_.... You get it when you join the beta (1,000 free try-ons, no card needed); we email it within 1–2 business days.
The key only works on your store’s domains. When you sign up, list every domain shoppers can use: with and without www, your platform subdomain (for example your-store.myharavan.com) and any staging site. The publishable key is meant to sit in your page source; never share a secret key if you are given one later.
Option 1: auto mode (recommended)
Paste this just before the </body> tag of your theme, on every page:
<script src="https://cdn.macgi.app/widget.js"
data-key="pk_live_..."
data-auto
defer></script>With data-auto, the widget recognises product pages and inserts a “Try it on” button next to your add-to-cart button. A page counts as a product page when it has at least one of:
Productstructured data (JSON-LD), which most store platforms already output;- an
og:imagetag with the product photo; - an add-to-cart form.
The product photo comes from the page’s own data. By default every product is tried on as a top (top). To have trousers, skirts and dresses tried on correctly, add keyword rules matched against the product name:
<script src="https://cdn.macgi.app/widget.js"
data-key="pk_live_..."
data-auto
data-default-slot="top"
data-slot-rules='{"jeans":"bottom","trousers":"bottom","skirt":"bottom","dress":"one_piece"}'
defer></script>For a product the rules get wrong, add meta tags to that product page. They override the keyword rules and the detected photo:
<meta name="macgi:slot" content="bottom">
<meta name="macgi:garment-image" content="https://your-store.com/images/blue-jeans.jpg">The Haravan and Sapo guides show how to output these tags from product tags automatically.
Option 2: place the button yourself
To control exactly where the button goes and how it looks, remove data-auto from the script tag and add an element with data-macgi-tryon to your product page. Any element works, and it can be added after the page loads (single-page apps are fine). Use your theme’s button classes so it matches the rest of the page.
<script src="https://cdn.macgi.app/widget.js" data-key="pk_live_..." defer></script>
<button type="button" data-macgi-tryon
data-garment-image="https://your-store.com/images/black-tee.jpg"
data-garment-slot="top"
data-garment-description="black cotton crew-neck t-shirt">
Try it on
</button>The description (data-garment-description) is used to generate the image, so it must match the photo, colour especially. The product name is usually enough. For a full outfit (up to 2 items: a top plus trousers or a skirt), use data-garments:
<button type="button" data-macgi-tryon
data-garments='[
{"slot":"top","description":"white shirt","imageUrl":"https://your-store.com/images/white-shirt.jpg"},
{"slot":"bottom","description":"beige trousers","imageUrl":"https://your-store.com/images/beige-trousers.jpg"}
]'>
Try the outfit
</button>Pick one option per page. With data-auto on and your own button too, the page may show two buttons.
Options
Script tag attributes
| Attribute | What it does |
|---|---|
data-key | Your publishable key (required). |
data-auto | Auto mode: detect product pages and insert the button. |
data-default-slot | Garment type when no rule matches: top (default), bottom or one_piece. |
data-slot-rules | JSON of keyword → garment type, e.g. {"jeans":"bottom","dress":"one_piece"}. |
data-placement | CSS selector of the element the button goes next to, when the detected spot is not right, e.g. .product-form. |
data-lang | vi or en. Default: Vietnamese, or English when the shopper’s browser prefers English. |
data-consent | Replaces the consent text shown before the shopper adds a photo. |
Button attributes
| Attribute | What it does |
|---|---|
data-macgi-tryon | Marks the element as a try-on button. |
data-garment-image | Product photo URL (absolute, relative or starting with //). |
data-garment-slot | top (default), bottom or one_piece (dresses, jumpsuits). |
data-garment-description | Short description that matches the photo, e.g. “black crew-neck tee”. |
data-garments | Instead of the three above: an outfit of 1–2 items as JSON. |
Per-page meta tags (auto mode)
| Tag | What it does |
|---|---|
<meta name="macgi:slot"> | Garment type of the product on this page. |
<meta name="macgi:garment-image"> | Photo to use, when the detected one is not a front-facing product shot. |
Events and JavaScript API
The script creates window.Macgi. You do not need to call init when the script tag has data-key.
// Open the widget from your own code (a custom button, a single-page app…)
Macgi.open([
{ slot: 'top', description: 'black tee', imageUrl: 'https://your-store.com/images/black-tee.jpg' },
]);
Macgi.close(); // close the widget
Macgi.setLang('vi'); // switch language: 'vi' or 'en'
Macgi.forgetPhoto(); // drop the shopper's photo held in memoryThe widget dispatches events on window, so you can send them to your analytics or trigger actions such as opening the cart:
| Event | When | event.detail |
|---|---|---|
macgi:open | The shopper opens the widget | garments |
macgi:photo | A photo is taken or chosen | bytes |
macgi:submit | The try-on is sent | garments |
macgi:result | The result image is ready | id, resultUrl, processingMs |
macgi:error | The try-on failed | message |
macgi:close | The shopper closes the widget | (empty) |
window.addEventListener('macgi:result', (e) => {
// e.detail = { id, resultUrl, processingMs }
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({ event: 'macgi_tryon_result' });
});
window.addEventListener('macgi:error', (e) => {
console.warn('Macgi:', e.detail.message);
});Events carry no photo or personal data. Result links expire after 24 hours, so do not store them.
Privacy
- Before adding a photo, the shopper sees a consent notice (change it with
data-consent). - The photo is resized and stripped of all metadata (GPS location, camera, time) on the device before it is sent.
- Nothing about the shopper goes into a database. The temporary photo is deleted when the try-on ends; results are deleted after 24 hours.
- The photo stays only in the page’s memory so the shopper can try more items; it is never put in browser storage.
Macgi.forgetPhoto()drops it at once. - Shoppers’ photos and your product photos are never used to train AI or for advertising.
We suggest one line in your store’s privacy policy saying the try-on feature is provided by Macgi, linking to our privacy policy.
Troubleshooting
The button does not show
- The page is not recognised as a product page. Auto mode needs
Productdata, anog:imagetag or an add-to-cart form. Place the button yourself (option 2) on that page. - No product photo was found. Add
<meta name="macgi:garment-image">, or place the button yourself withdata-garment-image. - The domain is not allowed for your key. The key only works on registered domains; a new domain, the
wwwversion or your platform subdomain each need adding. Send us the domain over Zalo or email and we add it. - The script is not loading. Open a product page, press F12, open the Console and type
window.Macgi. If it saysundefined, the theme was not saved, you edited an unpublished theme, or the page is still cached.
The button is in an odd spot
Add data-placement with the CSS selector of the block it should sit next to, or place the button yourself.
Trousers or dresses are tried on as tops
Add the keyword to data-slot-rules, set <meta name="macgi:slot"> for that product, or set data-garment-slot on the button.
Wrong colour or style in the result
Check that the description matches the photo, and use a front-facing photo that shows the whole item on a plain background. Posed side-on model shots or multi-colour collages give weaker results.
Need a hand?
During the beta we install it with you over Zalo or email, free of charge.