Skip to main content
Member storefront is in a limited pilot. Confirm that member storefront is enabled for your company before relying on this behavior.
Every product and variant price your theme prints is already member-aware. There is no filter to add, no tag to wrap, and no theme change to make. If your template prints {{ product.price }}, a signed-in member sees their own price there. A storefront page is cached once and served to everyone, so it can never contain one member’s price. Member pricing works around that: Fluid renders the public price into the cached HTML inside a small placeholder called a shell, and the SDK replaces the text once it has confirmed who is viewing.

What becomes member-aware

Any visible product or variant price you print:
With the feature enabled, that renders a shell wrapping the public price:
The shell sits in the light DOM, so your existing price styles apply unchanged. With the feature disabled, the same template prints $48.00 and nothing else. price, price_in_currency, and formatted_price are recognised on products and variants. A price needs a country to be resolvable, so a value with no country context prints plain.

Prices you print are hydrated. Prices you calculate with are not

This is the rule that keeps the rest of your theme working. A price becomes a shell only where it is printed as visible text. Everywhere else it stays the ordinary number or string it has always been:
Comparisons, arithmetic, HTML attributes, <script> and <style> bodies, JSON, and captured strings all keep scalar values. Only visible page text gets a shell, so your conditionals and your data attributes behave exactly as before.

Filters still apply

Filters on a printed price are carried with the shell and re-applied to the member’s price on Fluid’s side:
The guest sees the filtered public price. A member sees the same chain applied to their own price. Filters applied through an assign compose with filters on the final output:
Arithmetic, rounding, money, default, escaping, and text operations such as append, replace, and truncate are supported. Filters that load resources or build HTML are not, and an expression using one simply prints its public value with no shell. The browser never calculates money; it only writes the text Fluid returns.

You no longer need the member_price filter

Earlier releases required {{ product | member_price }} on every price you wanted hydrated. That is no longer necessary. Printing the price is enough. The filter still works, so themes that already use it keep working and need no edit:
Reach for it only when you are printing something the automatic rule does not recognise, such as a value that is not a product or variant. Passing your own formatted string as the argument makes that string the guest fallback. Do not apply both to one price. And never hand-write a <fluid-member-price> element: a hand-written shell has no guaranteed fallback and no country, so the SDK cannot resolve it safely.

What the browser does

The SDK is one script that Fluid adds for companies with member storefront enabled. You do not add it to your layout. A guest costs nothing. The SDK looks for a small non-secret cookie that marks a signed-in session, and when it is absent it makes no requests at all — no session check, no price requests. Nothing about the page changes. For a signed-in member it confirms the session against Fluid, then asks for the prices the page needs and writes each one into its shell. Fluid resolves the price from the member’s own pricing tier using the signed-in cookie. The tier is never chosen in the browser and never appears in the page. Two details worth knowing:
  • The public price stays visible while requests run. There is no blanked-out or masked state. A member sees the public price briefly and then their own.
  • Identical prices share one request. The same product printed twice on a page is resolved once. Different variants and different countries are always resolved separately.
When the page regains focus, or comes back from the browser’s back/forward cache, the SDK re-checks the session and resolves again, so a price never outlives the session that produced it.

When nothing changes

The public price staying on screen is the designed outcome of every failure, not an error: Nothing writes an error into the page, and nothing is ever left blank.

What to do, and what not to

Member pricing works by replacing the text inside the element your theme prints the price into. Everything on this list follows from that one fact: if something else owns that text, it wins.

Do

  • Print the price and leave the element alone. <p class="price">{{ product.price }}</p> is the whole requirement.
  • Let the price be the element’s own content. Hydration replaces text in place, so the price needs to be text on the page, not a value you stash and render later.
  • Reserve space for the price so a longer or shorter member price does not shift the layout.
  • Style on the resolution attributes rather than on the price text.
  • Test with JavaScript disabled when a price does not personalise. That shows what the server actually sent, which separates a rendering problem from a theme-script problem.

Do not

  • Do not render the price with your own script. Writing {{ product.price }} into a data- attribute and then setting textContent from it replaces the hydrated value with the public one. This is the single most common cause of a price that never personalises.
  • Do not set textContent or innerHTML on an element that holds a price. Your write lands after hydration and silently undoes it.
  • Do not re-render the price container from client state — an AJAX section replace, or a component that redraws on variant change — unless you re-render from the server’s HTML.
  • Do not do arithmetic on a price in the browser. Read the price, and let Fluid apply discounts, currency and rounding. A member price is not the public price times a factor.
  • Do not cache a rendered price in a JavaScript variable, localStorage, or a template you re-apply later. It belongs to one viewer and one session.
  • Do not hand-write a shell element. It has no guaranteed fallback and no country, so it cannot be resolved safely.
  • Do not strip unknown elements or attributes. A sanitizer or optimiser that removes custom elements removes the price shell with them.
  • Do not assume the price text at page load is the member’s. It is the public price until hydration completes, which is the point of the fallback.

Style around resolution

Each shell gains data-fluid-member-settled once it has either written a value or decided to keep the fallback. Section wrappers become resolved or guest. Reserve space so a card does not shift when a longer or shorter price arrives:

Test member pricing

  1. Feature disabled. Render the page and confirm the output matches the version before any member work. No shells, no markers.
  2. Guest, feature enabled. Confirm the page looks identical. In the HTML, confirm shells carry the public price and the right data-country-iso, and that your data attributes and JSON still hold plain numbers.
  3. Signed-in member. Confirm prices swap to the member’s own. Sign out and confirm they revert.
Also check a member whose type buys at retail. They should see the public price with no error. On a multi-country storefront, switch countries and confirm each shell carries that country’s code.

Troubleshoot