Overview
The Visual Search widget gives shoppers three ways to discover products:- Image search modal: shoppers upload an image or select an area of an image to find visually similar products.
- Shop-similar modal: shoppers open a product-specific view of similar products.
- Similar-products preview: you can display a product grid directly on a page and let shoppers open the full modal.
storefrontApiToken that the widget can use and loads the storefront pixel, which forwards widget events to Clarity or Blotout when those integrations are enabled. Add the widget script to your theme yourself. See What the app embed handles.
Prerequisites
- Install Layers and enable the app embed if you want it to provide the storefront access token and forward widget events.
- Have a storefront access token available. When the app embed is enabled, the widget can read its
storefrontApiTokenautomatically. You can also provide a token on the widget script or through the widget manager. - Add the widget script to your Shopify theme. Enabling the app embed alone does not add the widget.
Installation
Add the script tolayout/theme.liquid, before the closing </body> tag:
type="module". Module scripts defer automatically; you do not need to add defer.
Once the script loads, you can add the custom elements where you want the entry points and preview to appear. See Image search, Shop similar, and Similar-products preview.
Script attributes
Put these attributes on the script element withid="layers-script".
API key resolution and load order
The widget resolves its access token whenever it makes an API request, in this order:widgetManager.config.apiKey, set withsetApiKey(),configure({ apiKey }), or by a non-emptydata-api-keyvalue read when the widget initializes.- The current non-empty
data-api-keyvalue on#layers-script. - The
storefrontApiTokenvalue in the app embed’s<script id="layers-config" type="application/json">element.
data-api-key after the widget loads and no key was configured at initialization, the widget can use the new value on its next request. A key already stored in config.apiKey remains higher priority than later changes to the attribute. The widget caches the app embed token after it first parses a valid value. Missing or invalid embed JSON does not prevent initialization.
data-debug is read once when the widget initializes. In contrast, data-hide-branding is checked when each modal renders, unless you explicitly configure hideBranding.
JavaScript configuration
The widget manager is available atwindow.Layers.widgetManager. Configure it after the module has loaded:
configure() accepts these options:
The
currencyFormat object accepts:
For example,
configure({ currencyFormat: { currency: 'EUR' } }) keeps the default style: 'currency' and currencyDisplay: 'symbol'. You can also use updateCurrencyFormat() to merge currency-format properties.
Other available methods include:
setApiKey(apiKey)andgetApiKey()to set or resolve the storefront access token.createImageSearchToggle(options),createSimilarProductsToggle(options), andcreateSimilarProductsPreview(options)to add widgets from JavaScript.updateTheme(properties)to set CSS custom properties at runtime.updateTranslations(widgetType, translations)to merge translations forimage-searchorsimilar-products.debugTheme()to log the theme values the widget manager tracks.
Image search toggle
Use<layers-image-search-toggle> to add a button that opens the image-search modal.
Custom upload content
Add a<template> and reference its id with template-id to display custom content in the upload step:
Reference images and area-selection events
Use<layers-image-search-reference-image> to open image search from an image:
layers-image-search-area-selected event after the shopper selects an image area:
Similar-products toggle
Use<layers-similar-products-toggle> to add an entry point for a product’s similar-products modal:
You can add a filter group as a child script. The widget validates this JSON before using it:
conditional to "AND" or "OR". Each expression has a string property, a string operator, and a values array containing strings, numbers, or booleans.
Similar-products preview
Use<layers-similar-products-preview> to render a product grid with a button that opens the similar-products modal:
The preview also accepts a child
<script type="layers/filter-groups"> with a filter group in the same format as the similar-products toggle.
Prices, currency, and Shopify Markets
The image-search and similar-products requests sendcontext.market when window.Shopify.country contains a country code. The widget trims and uppercases the value, for example "ca" becomes "CA". If Shopify country is unavailable or empty, the widget omits context.market. The API then uses the request’s geo country, or the US if no country is available, and returns prices localized for that market.
When the response includes _meta.pricing.currency_code, the widget uses it to format the returned prices. It resolves currency in this order:
currencyFormat.currency, if you explicitly configure it.- The response’s
_meta.pricing.currency_code. window.Shopify.currency.active.USD.
currencyFormat.locale, if you explicitly configure it.window.Shopify.locale, withwindow.Shopify.countryappended when the locale has no region subtag, such asen-CA.- The bare
window.Shopify.locale. en-US.
en-US.
Set explicit formatting when your storefront needs a fixed currency or locale:
configure() merges currencyFormat properties, so setting only currency keeps the existing currency style and symbol display. For more about configuring Shopify market context, see Shopify Markets.
Styling
The widget applies theme values across its shadow roots. Set supported variables on:root in your theme CSS, or call window.Layers.widgetManager.updateTheme() to change them at runtime. The theme manager reads computed values from document.documentElement and observes changes to its style and class attributes.
updateTheme() does not track --layers-widget-transition-properties; set that one in CSS.
Translations and analytics
UseupdateTranslations() to deep-merge custom text for either widget:
window.Layers.analytics.subscribe(handler) for its analytics events. When Clarity or Blotout is enabled, the app embed can also forward widget events to those services when their scripts are present and consent allows it. See app embed integrations.
Troubleshooting
The widget does not appear
- Confirm that
layout/theme.liquidincludes the module script and that itssrcURL loads successfully. - Confirm that your page includes the appropriate custom element. The similar-products toggle and preview also need a
product-id. - Check the browser console for script, configuration, or network errors.
The console says “No API key found”
Confirm that at least one token source is available:data-api-key on #layers-script, storefrontApiToken in the app embed’s #layers-config JSON, or window.Layers.widgetManager.setApiKey() / configure({ apiKey }). A token configured at initialization takes priority over later attribute changes.
Prices use the wrong currency
Checkwindow.Shopify.country, window.Shopify.locale, and window.Shopify.currency.active on the storefront. Review the API response’s _meta.pricing.currency_code and any explicit currencyFormat settings, which take priority over Shopify’s active currency. See Shopify Markets.
Branding is still visible
Setdata-hide-branding="true" on the script element with id="layers-script". If you set hideBranding with configure(), its boolean value overrides the script attribute.
Enable debug logging
Setdata-debug="true" on #layers-script before the module initializes, or enable logging later:
Next steps
- What the app embed handles for token delivery, storefront pixel behavior, and event forwarding.
- Theme implementation checklist for the wider Shopify theme integration.
- Shopify Markets for market and currency setup.
- Liquid integration for reading Layers configuration and metaobjects in your theme.