Documentation Index
Fetch the complete documentation index at: https://docs.hemsy.ai/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Deep links are URLs that configure how Hemsy opens: pre-loaded products or a shared look, bundle metadata on line items, and optional attribution IDs — before or as soon as the shopper lands in the session. Use them from product pages, emails, ads, blog posts, collection tiles, or bundle landing pages so customers don’t have to rebuild a look from scratch or lose tracking context. Hemsy supports these query parameters for pre-populating or attributing a session:| Param | Purpose |
|---|---|
?closet= | Base64-encoded payload for one or more products, with optional line-item attributes. |
?product= | Shortcut for a single product by Shopify ID or handle. |
?share= | A shared look short ID, used by the in-app Share feature. |
?anonymous_id= | Anonymous visitor ID passed into Hemsy for analytics, attribution, and integrations. |
?store=<slug> on preview deployments to
target a specific tenant.
?closet= is the canonical, structured format. Use it for anything beyond a
single-product deep link, and always use it when you need to attach bundle
attributes.Include
anonymous_id whenever the storefront has an anonymous visitor ID
available. Today, Hemsy uses it for Twilio Segment tracking and checkout/order
attribution. Longer term, it should be treated as the shared anonymous
identity for all integrations that need to connect Hemsy activity back to
storefront activity.anonymous_id — Visitor attribution
anonymous_id is an optional query parameter that lets the merchant storefront
tell Hemsy which anonymous visitor is opening the experience.
Use it when launching Hemsy from:
- Embedded storefront buttons
- Product page links
- Bundle landing pages
- Email or ad links where the visitor ID is available
- Any integration that wants to reconcile Hemsy events with storefront behavior
What anonymous_id does
When present, Hemsy uses anonymous_id to:
- Attach the visitor identity to Hemsy analytics events.
- Pass the same identity through checkout creation, so it can surface on the Shopify order as an additional detail/custom attribute when the order is placed through Hemsy checkout.
- Provide a stable identity key for supported integrations.
Current integration support is focused on Twilio Segment. Merchants should
still pass
anonymous_id consistently now so Hemsy can use the same identity
for additional integrations as they are added.?closet= — Structured payload
Format
The value ofcloset is a URL-safe Base64 encoding of a JSON object:
+replaced with-/replaced with_- Trailing
=padding stripped
?closet=<encoded>.
Product entry schema
Each entry in theproducts array supports the following fields:
| Field | Type | Required | Notes |
|---|---|---|---|
variantId | number | string | one of required | Preferred identifier. Accepts a numeric ID or a Shopify GID: gid://shopify/ProductVariant/.... |
productId | number | string | one of required | Fallback when you don’t know the variant. Accepts a numeric ID or a GID. |
attributes | Array<{ key: string; value: string }> | optional | Line-item attributes forwarded into the Shopify cart at checkout. |
Minimal example — single product
Example — multiple products
Line-item attributes
Every entry inproducts may include an attributes array. These are key/value
pairs that get forwarded verbatim to Shopify’s Storefront API cartCreate
mutation when the shopper checks out, and they surface on the resulting Shopify
order.
Use attributes to:
- Track the source of a selection, such as
"utm_campaign"or"source". - Tag items as part of a bundle.
- Pass through arbitrary merchant metadata you want on the order.
Attribute keys that start with an underscore (
_) are treated as private
in Shopify’s admin. They appear on the order but are hidden from the
storefront cart UI. Hemsy follows the same convention for its reserved keys.Use the top-level URL query parameter
anonymous_id for visitor identity. Do
not put visitor identity into each product’s line-item attributes unless the
merchant has a separate order-reporting need for that data at the line-item
level.Bundles and the _bundleId reserved key
Closet URLs are the canonical way to launch a bundle into Hemsy. A bundle is
a group of products a merchant wants a shopper to try on and check out with
together — for example, a “Starter Bedroom Bundle” composed of a sheet set, a
blanket, and a pillow insert.
To mark items as belonging to the same bundle, attach a set of reserved
attributes to every product entry in the bundle.
Reserved bundle attribute keys
| Key | Required | Purpose |
|---|---|---|
_bundleId | yes | Shopify GID or numeric ID of the parent bundle product. Presence of this key marks the line as a bundle member and is the signal Hemsy uses to enforce bundle behavior. |
_uniqueId | recommended | Opaque per-instance identifier, such as <bundle-handle>_<uuid>. Use the same value for every product in a single bundle instance so orders can be reconciled. |
_bundleTitle | recommended | Human-readable bundle name. Surfaces on the order in Shopify admin. |
_bundleHandle | recommended | The Shopify handle of the parent bundle product. |
_bundlesource | optional | Origin of the bundle payload, such as "hemsy". |
Bundle behavior in Hemsy
When any line item in the shopper’s closet has a_bundleId attribute, Hemsy
automatically:
- Hides the “Remove” button for that item in the final Review Your Order step. Bundles ship as a unit, and merchants almost always require every component for checkout to succeed, so customers can’t partially dismantle the bundle from the review screen.
- Forwards the full attribute set to Shopify’s cart so downstream discount rules, bundle-aware fulfillment logic, and order reporting all see the grouping.
Full bundle example
A three-line-item Campers-Starter-Kit bundle, Shopify handlecampers-starter-kit, with the full set of bundle attributes on each line item
and the same _uniqueId on every entry:
?product= — Single-product shortcut
For the common case of “launch Hemsy with one product pre-loaded”, ?product=
accepts either:
- A numeric Shopify product ID:
?product=8888888888888 - A Shopify GID:
?product=gid://shopify/Product/8888888888888 - A product handle:
?product=organic-cotton-duvet
?closet= instead.
?share= — Shared-look links
?share=<shortId> is reserved for links generated by Hemsy’s in-app Share
feature. The short ID resolves server-side to a previously saved look: user
photo, generated image, and full selection. You don’t need to construct these
yourself. They’re produced by the app when a shopper taps Share.
If the storefront knows the visitor identity, append anonymous_id to shared
look links too:
Building a Closet URL
The URL-safe Base64 step is the only gotcha. In JavaScript:base64.urlsafe_b64encode(...).rstrip("=") in Python.
Validation checklist
Before shipping a Closet URL in production, confirm:- Every product entry has
variantIdorproductId. - IDs are numeric or full GIDs — not handles. Handles only work with
?product=. - Base64 is URL-safe:
-and_, with no trailing=. -
anonymous_idis included whenever the storefront has an anonymous visitor ID available. - For bundles: every item has
_bundleId, and all items share the same_uniqueId. - You aren’t using
_bundleIdfor non-bundle use cases. - The link round-trips through
atobandJSON.parsesuccessfully.