Overview
Most of what makes a Layers integration work end-to-end is not code you write in your theme. The Layers app embed (the theme app extension) and the@commerce-blocks/sdk handle the cross-cutting concerns (authentication, identity, cart and customer context, attribution, tracking, third-party forwarding, semantic redirects, and dynamic linking), so your theme code only has to worry about rendering search, browse, blocks, and banner UI.
This page is the reference for what is handled automatically. If something on this list isn’t behaving in your theme, the fix is almost always a configuration toggle in the Layers dashboard or an embed setting. It is not theme code.
The app embed and the SDK are independent. The app embed is the Storefront Pixel + cross-cutting integrations. The SDK is the optional client library you use to call the Layers APIs. You can use the app embed without the SDK (vanilla
fetch from Liquid) and you can use the SDK without the app embed (custom storefront), but the two are designed to work together on a Shopify theme.What the app embed handles
The app embed is delivered as a Shopify theme app extension. Once it is toggled on under Online Store → Themes → Customize → App embeds, the following behavior is automatic.Authentication and identity
- Storefront token loading. The embed writes a
<script id="layers-config" type="application/json">tag into the theme<head>carryingapiToken(the analytics tracking token) andstorefrontApiToken(the storefront token), and attaches the token to every Layers API request it makes on behalf of the storefront. Theme code that needs the token for its ownfetchorcreateSDK()calls parses that tag. See Liquid integration. You do not paste a token into theme code. - Device and session IDs. The embed manages
deviceId(persisted) andsessionId(per visit) for every Layers request and event. Cookie fallbacks are configured viasessionCookieFallbacksin embed settings. - Customer context. If a shopper is logged in, the embed forwards Shopify customer ID, segment, and tag context to every request automatically.
- Cart context.
productsInCartis sent on every Layers request without you reading/cart.js. Cart-anchored blocks and cart-aware merchandising work out of the box. The embed keeps the cart context current as the cart changes, but it doesn’t re-request blocks already on the page. Fetch them again after a cart change if you want them to reflect the new cart. - Cross-block deduplication. On every Blocks request, the embed sets
excludeProductIdsto the products already on the page (other blocks’ results, cart items, the product being viewed, and the search or collection grid), so recommendation blocks don’t repeat each other. To turn this off, check Disable block deduplication in the Layers app embed settings in the theme editor. - Market detection. When Shopify Markets is configured, the embed forwards the active market context (currency, country, language) so search, browse, and blocks return market-correct results and pricing.
Tracking
The embed includes the Storefront Pixel, which captures and ships events to the Tracking API:collection_viewwhen a shopper lands on a collection page.searchwhen a shopper views search results.product_viewwhen a PDP renders.product_impression,product_hover, andproduct_touchwhen a product card surfaced by Layers is seen, hovered, or touched.product_clickwhen a shopper clicks a product card surfaced by Layers.add_to_cartwhen a Shopify add-to-cart form submits.block_viewwhen a recommendation block enters the viewport.autocompleteandautocomplete_clickwhen a shopper uses autocomplete and picks a suggestion.banner_impressionandbanner_clickwhen a Layers banner is seen or clicked. The banner element must carry adata-banner-idattribute with the banner’sidfrom the API response.content_view,content_impression, andcontent_clickfor blog articles and pages, including ones surfaced by content search.
navigator.sendBeacon yourself for these events. Custom storefronts that don’t load the embed should follow the navigator.sendBeacon guide instead.
Attribution
_layers_attributionline item property. The pixel appends a_layers_attributionproperty to add-to-cart forms when the shopper clicked the product from a Search or Browse response. The value is theattributionTokenof the originating request.- Order attributes. The pixel reads
_em_session_id,_em_device_id,_em_nav_id, and_layers_session_idfrom order note attributes to tie purchases back to sessions. Edgemesh’s_em_*attributes take priority when present. - Edgemesh attribute writing. When the Edgemesh integration is enabled, Edgemesh’s session and device IDs are written onto every order automatically. No theme work required.
Semantic redirects (auto-redirect)
The storefront pixel that the embed loads handles redirects. When a search response carries a_meta.redirect object, the pixel navigates the shopper to the configured URL before the search results page renders. When an autocomplete response carries one, the pixel remembers it and redirects the shopper as soon as they submit that query or click a link to its search page. This happens automatically whenever the app embed is enabled. You do not need to handle _meta.redirect in theme code. See Semantic Redirects.
Dynamic linking via ?utm_products=
The embed handles inbound ?utm_products= deep links: when a shopper lands on the storefront with a utm_products query param, the embed expands it into the matching products and surfaces them through the appropriate Layers experience. See Dynamic linking.
Third-party integration forwarding
When the integrations below are enabled in the Layers dashboard, the embed forwards events and reads/writes IDs without theme changes. Browse all integrations on the Layers integrations page.
With Clarity or Blotout enabled, the embed forwards these visual search and shop similar events, using the same payload it sends to Layers. Forwarding only happens when that service is already loaded on the page and your store’s consent settings allow it; the embed never loads extra scripts.
Search Inspector
Append?_layers_debug_menu=true to any storefront URL to open the Search Inspector, a built-in QA panel that shows the request being made, the response, attribution, and storefront-pixel events. Mode persists for the session via sessionStorage; ?_layers_debug_menu=false turns it off.
No theme code is needed to expose the Search Inspector. It is available on every page when the embed is enabled.
What the SDK handles
If you adopt@commerce-blocks/sdk, the SDK adds a second layer of behavior on top of the app embed. None of it requires theme code.
Reactive controllers
sdk.collection(), sdk.search(), sdk.blocks(), sdk.autocomplete(), and similar methods return controllers with reactive state. Subscribe once, call get() whenever inputs change, and the subscriber re-runs on every state transition. See Client methods.
Caching and request deduplication
Identical in-flight requests are deduplicated into a single network call. Controller responses use an in-memory cache and in-flight deduplication for the life of the page. Configurestorage when you want prepared search IDs to be reused across pages; the SDK does not restore response data from localStorage. See Cache and storage.
Framework-agnostic reactivity
Every controller exposessubscribe() and state. You can wire it to vanilla JS, React, Vue, Svelte, Solid, and Lit. See Framework integration. You do not need a framework-specific adapter package.
Product card controller
createProductCard() returns a reactive product card with variant selection, availability logic, and price formatting. The controller updates as variants are chosen, so your tile component just renders the latest snapshot.
Product transforms
createSDK({ transforms }) lets you mutate every product, collection result, and search result before it lands in your render code. See Client methods — transforms.
Prepare / get split
The SDK’s search controller exposesprepare() and get() so you can stage the request shape (filters, sort, pagination) before firing the network call. The split is useful for SSR and for UIs that build the request across multiple user interactions.
SSR-safe XHR fallback
In environments where the globalfetch is unavailable or blocked (or keepalive is not honored), import xhrFetch from @commerce-blocks/sdk or @commerce-blocks/sdk/xhr and pass fetch: xhrFetch to createSDK().
What is not handled
Some things still belong to your theme code, even with the embed and the SDK installed:- Rendering UI — search results pages, collection grids, facet sidebars, sort selectors, block tiles, banner placement. The embed does identity, context, and tracking; the SDK does request management. Markup is yours. See the Liquid guides and the matching SDK guides.
- Banner placement math. The browse response carries a top-level
bannersarray. Your theme owns hero placement above the grid and inlineposition-based slotting. See Rendering banners in Liquid and Rendering banners with the SDK. - Banner markup for tracking. The pixel tracks banner impressions and clicks only on elements that carry a
data-banner-idattribute set to the banner’sidfrom the API response. Add that attribute when you render banners. - Block picker UI. The embed knows which blocks exist (via metaobjects) but doesn’t render the block-picker dropdown in the theme editor. See Rendering blocks in Liquid.
- Visual Search and Similar Products UX. The embed loads the underlying widget, but you choose where it appears on PDPs and collection pages.
See also
- Storefront Pixel — how the pixel ingests events and writes attribution.
- Liquid integration — reading embed settings and metaobjects from Liquid.
- SDK overview — the optional client library.
- Integrations — Clarity, Blotout, Rivo, Abra, FoxSell, Edgemesh.
- Theme implementation checklist — step-by-step plan for shipping a theme integration.