For stores & brands
Put a hair-match check on every product page
One script tag adds a “Find my hair match” button to any store. Shoppers measure their hair once (YouCam Hair AI photo scan, or 5 quick questions), and every product shows how well it suits them — with the reasons. Your code gets the result as a JavaScript event.
Live · try it on this page
Shea Whip Curl Cream · $22 · example product
This button is the real widget, loaded from /widget.js, exactly as a store embeds it.
1. Tap the button
On your product page. The StrandLab dialog opens on top — the shopper never leaves your store.
2. Get matched
Quick 5-question check, or their AI-measured StrandLab scan (shared only with their consent). Saved for the next product.
3. Every product scored
The button turns into “82% match · suits your hair”, and every other product on the page gets its own badge.
Why stores add it
- Confidence at the moment of purchase. “Will this work on my hair?” is the question that stops a curly-hair shopper from buying.
- Fewer wrong-product returns. A clear “not ideal for your hair — here’s why” beats a disappointed review.
- Zero catalogue work. It reads the ingredient list you already publish. No tagging, no product feed.
- First-party insight. Use
lookFor/avoidto sort collections or recommend bundles — your data, in your code.
Install
Works on any platform that lets you add HTML: Shopify (theme section / custom liquid), WooCommerce, Webflow, BigCommerce, or a custom site.
<!-- 1. Once per page -->
<script src="https://strandlab-youcam.vercel.app/widget.js" async></script>
<!-- 2. Where the button should appear (product page, quick view, grid card…) -->
<div data-strandlab
data-product="Cloud Curl Defining Gel"
data-product-id="sku-123"
data-ingredients="Aqua, Glycerin, Polyquaternium-11, Aloe Barbadensis Leaf Juice, …"></div>// 3. Optional: use the result in your store
document.addEventListener("strandlab:result", (e) => {
const r = e.detail; // see "Result" below
if (r.product?.verdict === "great") showBadge(r.product.id);
sortCatalogue({ lookFor: r.lookFor, avoid: r.avoid });
});
document.addEventListener("strandlab:score", (e) => {
// { id, match, verdict, label } — fired for every product button on the page
});
// Or open it from your own button / quiz entry point:
StrandLab.open({ name: "Curl Cream", ingredients: "Aqua, Shea Butter, …" });
StrandLab.open(); // no product: profile + what to look forAttributes
| Attribute | What it does |
|---|---|
| data-strandlab | Marks where the button goes (required). |
| data-product | Product name shown in the dialog. |
| data-product-id | Your SKU / ID — returned in every event so you can match results to products. |
| data-ingredients | The INCI ingredient list. StrandLab classifies it (Gemini) and scores it with its deterministic rules. |
| data-ingredients-selector | Instead of data-ingredients: a CSS selector for the element on your page that already shows the ingredients. |
| data-label | Button text (default “Find my hair match”). On the <script> tag it sets the default for all buttons. |
| data-color (script tag) | Brand colour for the button, e.g. data-color="#7A2E5C". |
| data-auto-score="false" (script tag) | Turn off automatic match badges on every product button. |
Result
event.detail of strandlab:result:
{
"product": {
"id": "sku-123", "name": "Cloud Curl Defining Gel",
"match": 82, "verdict": "great", "verdictLabel": "Great match",
"pros": ["Film-formers / hold: gel cast locks the curl clump", "…"],
"cons": ["Humectants: 22°C dew point (humid) — glycerin pulls in moisture"],
"detected": ["Humectants", "Film-formers / hold", "Panthenol"]
},
"profile": {
"curlPattern": "3B TO 3C", "curlFamily": "curly", "frizz": 2,
"density": "High Density", "length": "above chest", "porosity": "high",
"dewPointC": 22, "source": "measured" // measured | self-reported | sample
},
"routineWeight": "rich",
"lookFor": ["Film-formers / hold", "Fatty alcohols", "Rich butters"],
"avoid": ["Humectants", "Sulfate cleansers", "Drying alcohols"]
}Privacy & security
- Photos never reach the store. The photo scan runs on StrandLab in its own window; only the derived hair summary and match scores are shared, after the shopper taps “Share”.
- The widget runs in an isolated iframe; every message is checked against the StrandLab origin, and replies go only to the page that embedded it.
- Button styles live in Shadow DOM, so they can’t clash with your theme. No cookies, no tracking pixels, no dependencies (~10 KB).
- Cosmetic guidance only — the dialog points people with scalp or hair-loss concerns to a dermatologist.