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 resyncs market pricing for the affected variants so shoppers see the new converted prices on the next request. To keep large catalogs from re-pricing on every small FX tick, Layers refreshes market pricing at most once every six hours per store. Layers coalesces rate changes detected within that window and applies them on the next refresh. The poll itself only runs while the application mode is Adjust pricing only or Restrict to market catalog.

How Layers picks the market for a request

Send context.market to choose a market explicitly. It accepts a two-letter country code, a numeric Shopify Market ID, a Shopify Market GID (e.g. "gid://shopify/Market/12345"), or a market handle. For Search and Browse requests, Layers selects the market in this order:
  1. Explicit market: context.market, or the top-level market parameter when context.market is absent.
  2. Direct market ID: context.marketId, if it identifies an active market and no explicit market selector was sent.
  3. Shopper’s country: context.geo.country, or request geolocation when the country isn’t supplied.
  4. Primary market: The active market marked as primary in Shopify.
An explicit selector takes precedence over a stale context.marketId. If the explicit selector doesn’t resolve, Layers tries the shopper’s country and primary market, not the stale ID. An unknown or inactive direct market ID also falls back to country and primary market resolution. For Blocks requests, use context.market to select a market explicitly; don’t rely on context.marketId alone to override country or primary-market resolution. Server-side and headless integrations should pass the shopper’s country explicitly (ISO 3166-1 alpha-2, e.g. "US", "GB", "JP"), because request geolocation would identify your server. Layers attaches the resolved market to the request for filtering, pricing, and response metadata. Layers resolves the pricing country and shop base currency on the server. Client-supplied pricingCountryCode and baseCurrencyCode context fields don’t override those values. These selection rules apply when the application mode uses Markets, not in Ignore markets mode.
Prices and currencies are stored per country within a market, so Layers picks a pricing country inside the resolved market. It uses a two-letter country code sent in context.market if that country belongs to the market, otherwise the shopper’s context.geo.country (or IP-detected country) if it belongs to the market. If neither applies, for example when the shopper is outside the market or a server-side request omits context.geo.country (so the detected country is your server’s), Layers uses the market’s only country for single-country markets, or the first country alphabetically by country code for multi-country markets. In a multi-country market like International, that fallback can price a shopper in the wrong currency, so always send context.geo.country (or a country code in context.market) 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 in the Markets card under Settings > Search & Discovery > Search Behavior and defaults to Ignore markets for new stores.

Ignore markets

Markets sync is paused and Markets data is not applied. Every shopper sees the full catalog and the variant’s default price, regardless of which market their country maps to. Layers stops polling Shopify for currency rate updates and stops running per-market pricing refreshes for the store while the mode is Ignore markets. Use this mode when you’ve enabled Markets in Shopify but don’t yet want the catalog to localize. When you switch back to Adjust pricing only or Restrict to market catalog, Layers automatically starts a catalog-wide market pricing refresh. Newly opted-in stores don’t have to wait for the next webhook to backfill.

Adjust pricing only

Layers applies the resolved market’s price and currency to every variant in the response. The catalog itself is not filtered by market membership. Every shopper sees every product, priced in their market’s currency. Use Adjust pricing only when:
  • You want localized prices without hiding any products, even if some products aren’t published to every market in Shopify.
  • You’re rolling out market-aware pricing and don’t want visibility changes to ship at the same time.

Restrict to market catalog

In Restrict to market catalog mode, Layers applies the resolved market’s pricing and filters products to the ones published to that market. Products whose available_market_ids array includes the resolved market are returned. Products published to other markets, but not the resolved one, are excluded from search, browse, and block results. 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.
A product with no market availability data is treated as visible in every market only until Layers has synced its market availability. Once Markets sync has run for the product, an empty availability list means Shopify published it to no market, and Restrict to market catalog mode hides it everywhere. If a product you’ve just added to a market is still hidden, resync the product so Layers picks up the new availability.

Markets and sales channels

Layers checks market availability and sales channels separately. On your web storefront, a product must be published to the Online Store sales channel to appear, whatever the market mode. Removing a product from the Online Store channel hides it from web shoppers in every market, even markets it’s published to. Mobile app requests check your configured app sales channel instead. Without one, they fall back to web-channel filtering. See Sales channel visibility. Only Restrict to market catalog filters search, browse, block, and facet responses (including facet-range counts on price) by available_market_ids. Adjust pricing only localizes pricing without touching the catalog.

Fixed-amount discounts

Discount entitlements use the shop’s base currency for fixed amounts. Layers skips a fixed discount on a variant’s native market price when that price uses a different currency. It doesn’t convert the discount. Percentage discounts still apply to localized prices, and a variant that falls back to its base price can still receive a fixed discount. If a foreign-currency market price has no compare-at price, Layers doesn’t fill it with a base-currency compare-at price. This avoids displaying prices in two different currencies together.

What shows up in API responses

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

Variant pricing

In Restrict to market catalog and Adjust 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), 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, which is 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.
_meta.pricing doesn’t include decimal places because Shopify doesn’t expose them. Derive decimals from the ISO currency_code if you need them. If Layers can’t resolve a native currency for the market and country, the response omits currency_code.

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 without hiding any products

Set the mode to Adjust pricing only. Shoppers see the full catalog, priced in their market’s currency, whether or not every product is published to every market in Shopify.

Region-specific soft launches

Run in Restrict to market catalog 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 reflects what a real shopper in that country would see: the same market, pricing, and filtered catalog.

Limitations

  • Translations follow the market’s languages. Layers serves translated text only for languages published on the resolved market. See Translations.
  • 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.
  • Send a shopper country for accurate market pricing. Requests without a country in the resolved market are priced for a fallback country in that market, which may not be the shopper’s. See the warning under How Layers picks the market for a request.
  • Restrict to market catalog 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 Ignore markets 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.