Skip to main content
Shopify Markets lets you sell to multiple regions from a single store with per-market product availability, currencies, and prices. Layers syncs your Markets configuration from Shopify and applies it to every storefront response — search results, collection browses, blocks, and facets — so each shopper sees the catalog and prices that match where they’re shopping from. This page covers what Layers syncs, how it picks the market for a given request, and the three application modes you can choose between.

What Layers Syncs

When Markets sync is enabled, Layers ingests four kinds of data from your Shopify Markets configuration: Sync is driven by markets/create, markets/update, markets/delete, and product update webhooks — there’s no manual refresh required in normal operation. You can trigger a one-off refresh from the Catalog → Sync dashboard if you need to backfill historical data.

Currency rate refresh

Shopify recalculates the exchange rates behind market pricing on its own schedule and doesn’t emit a webhook when it does. To keep localized prices current, Layers polls each store’s Shopify currency settings every 15 minutes. When the rateUpdatedAt timestamp on any enabled currency changes, Layers automatically resyncs market pricing so shoppers see the new converted prices on the next request. No configuration is required, and the poll only runs while markets sync is enabled for the store.
Markets sync is automatically disabled while the Global-E integration is active. Global-E manages its own localized pricing through a country rate table, so the two systems don’t run side-by-side. See Discount Entitlements for related Global-E details.

How Layers Picks the Market for a Request

Every Search, Browse, and Blocks request can carry a context.geo.country field. Layers resolves that country into a market using the synced region table:
  1. The storefront pixel and the JavaScript SDK populate context.geo.country automatically from Cloudflare’s edge geolocation. Custom integrations should pass the shopper’s country explicitly (ISO 3166-1 alpha-2, e.g. "US", "GB", "JP").
  2. Layers looks up which market that country belongs to.
  3. The resolved market ID is attached to the request and used downstream for filtering, pricing, and meta.
You can override this resolution by sending context.market. It accepts a two-letter country code, a numeric Shopify Market ID, or a Shopify Market GID (e.g. "gid://shopify/Market/12345"). Like every other market-related value, it must still be nested inside the request’s context object. If context.geo.country is omitted, or if the country doesn’t map to any active market, Layers falls back to the primary market — the one marked is_primary in Shopify.
context.geo.country is required to serve market-localized pricing. Because prices and currencies are stored per country within a market, Layers cannot pick the right row without a resolved country. If a request supplies context.market but no context.geo.country, Layers falls back to the variant’s default price and skips market pricing entirely — even when the request otherwise resolves to a market. Storefront integrations should always send context.geo.country on price-bearing requests.
Example request context

Application Modes

Layers exposes three modes for how aggressively Markets data is applied to storefront responses. The mode is set on the Integrations → Shopify Markets page in the dashboard and defaults to Off for new stores.

Off

Markets data is synced but not applied. Every shopper sees the full catalog and the variant’s default price, regardless of which market their country maps to. Use this mode when you’ve enabled Markets in Shopify but don’t yet want the catalog to localize — for example, while you’re auditing per-market product publishing before flipping the switch.

Pricing Only

Layers applies the resolved market’s price and currency to every variant in the response and hides products the resolved market isn’t published to. Shoppers see the catalog available to their market, priced in that market’s currency. This mode is the right choice when:
  • You want localized prices and want the catalog to respect Shopify’s per-market product publishing, but you don’t need the additional guarantees of strict.
  • You’re rolling out market-aware pricing and want unavailable products excluded from results without opting into full strict behavior.
Before July 2026, pricing_only applied market pricing but did not filter by available_market_ids. It now filters by availability alongside strict. If you were relying on the old behavior to serve the full catalog everywhere, switch the mode to Off or publish those products to every market in Shopify.

Strict

The full Markets experience. Layers applies the resolved market’s pricing and filters products to the ones published to that market. Products whose available_market_ids array doesn’t include the resolved market are excluded from search, browse, and block results entirely. This is what most multi-region stores end up running. Combine it with the available_market_ids facet attribute if you also want merchandisers to filter or segment by market inside Lab. Both pricing_only and strict filter search, browse, block, and facet responses (including facet-range counts on price) by available_market_ids. The difference between them is reserved for future strictness guarantees around variant-level publishing — today, product-level availability filtering is identical.

What Shows Up in API Responses

When a market is resolved for a request, Layers enriches the response in two places:

Variant Pricing

In strict and pricing_only modes, the price and compare_at_price on each variant (and the rolled-up price_range on the product) reflect the pricing Shopify returned for the shopper’s specific country within the resolved market — not a single collapsed currency for the whole market. A shopper in France browsing a USD-base International market sees the variant’s EUR price; a shopper in Japan on the same market sees the JPY price. If Layers doesn’t have a price stored for the exact (market, country) pair — for example, the product was created before the market was published to, or context.geo.country was not supplied on the request — it falls back to the variant’s default price.

_meta.pricing

When market-aware pricing applies, the response includes a _meta.pricing object:
currency_code reflects the shopper country’s native currency inside the resolved market — the same currency the returned price and compare_at_price are expressed in. Use it on the storefront to format prices consistently — Intl.NumberFormat(locale, { style: "currency", currency: currency_code }) is the usual pattern.
The same _meta.pricing shape is used by the Global-E integration when active. The shape of the object is stable across both integrations so your frontend doesn’t need to branch on which pricing provider is in play. When Shopify Markets is the active source, currency_decimal_places may be omitted (Shopify does not expose it) — derive decimals from the ISO currency_code if you need them.

available_market_ids on Products

Every product carries an available_market_ids array regardless of which mode you’re in (provided Markets sync is enabled). You can read it directly from any search, browse, or block result. You can also expose available_market_ids as a filterable catalog attribute of type number to use it in merchandising rules, facets, and sort orders. See Filtering by Shopify Market for the setup steps.

Common Patterns

Localize Prices When Every Product Is Published Everywhere

Set the mode to Pricing Only. If every product is published to every market in Shopify, the availability filter is a no-op and shoppers effectively see the full catalog — priced in their market’s currency. If your catalog isn’t fully published to every market and you want shoppers to see products regardless of availability, use Off instead so the catalog isn’t filtered.

Region-Specific Soft Launches

Run in Strict mode. Publish a new product to a single market in Shopify, and that product will only appear in search and browse responses where context.geo.country resolves to that market.

Per-Market Merchandising Rules

Once available_market_ids is exposed as a catalog attribute, you can write merchandising rules whose conditions or actions reference it — for example, pin a hero product in the EU market but not in the US. Combine with contextual conditions on geo.country for finer geo targeting than market-level rules.

Auditing What a Shopper in Country X Sees

Pass context.geo.country explicitly in a request from your own machine. The response will reflect whatever a real shopper in that country would see — same market, same pricing, same filtered catalog.

Limitations

  • One market per request. Layers resolves exactly one market per request from context.geo.country. There’s no notion of “multi-market” results in a single response.
  • Currency conversion is read from Shopify. Layers does not do its own FX — the price served is exactly what Shopify’s contextual pricing returned for the shopper’s country. If Shopify hasn’t computed a price for a given variant in a given (market, country) pair, Layers falls back to the default variant price — even though that price is in the store’s primary currency.
  • A shopper country is required for market pricing. Requests that omit context.geo.country fall back to the variant’s default price and skip market pricing, even when a market is otherwise resolvable. See the warning under How Layers Picks the Market for a Request.
  • Strict mode can hide products from anonymous shoppers. Anonymous traffic from a country with no resolvable market lands on the primary market. Make sure your primary market’s product publishing covers the products you want anonymous visitors to see.

FAQ

Q: Can I use Shopify Markets alongside B2B catalogs?
A: Yes. B2B catalog rules win for buyers signed in to a company location. Markets apply to everyone else. See B2B Catalogs for the precedence rules.
Q: Do I need to call a different endpoint for each market?
A: No. Every storefront endpoint accepts context.geo.country and resolves the market automatically.
Q: What happens if Shopify Markets is disabled mid-traffic?
A: Layers continues serving cached data until the next webhook arrives, then disables sync. The application mode reverts to Off so shoppers immediately see the unfiltered catalog and default pricing.
Q: How do I test a specific market locally?
A: Pass the country code explicitly in context.geo.country — for example, "DE" to simulate Germany. Cloudflare won’t override the value if it’s already set.