Any (webshop)

How to Display Customer-Specific Prices

Show the right price to the right customer in Clerk Designs.

Clerk uses a single product catalogue for all visitors. This means that by default, every visitor sees the same price and list_price values synced from your store.

Many B2B and membership-based stores need to show different prices depending on who is logged in. Clerk supports this through two approaches, and the right choice depends on how your pricing works.

When to use which #

ScenarioApproach
Every customer has a unique negotiated priceIndividual prices
A handful of customer groups each share a priceGroup prices

Both approaches work across Search, Recommendations, and Email, on any platform.

Individual prices #

Use this approach when each customer has completely unique prices that cannot be pre-stored in the product data, for example negotiated B2B contracts.

The idea is simple: let Clerk render the products first, then replace the placeholder price with the real price fetched from your server.

This requires a server-side endpoint on your webshop that can return a price when given a product ID and a customer ID. The implementation of that endpoint is specific to your platform and must be built by a developer.

Design placeholder #

Start by adding a placeholder element in your Design where the price will appear:

<div class="clerk-price-container">
  <span class="clerk-price">
    Loading price...
  </span>
</div>

The text “Loading price…” is shown briefly while the real price is being fetched.

Replace with real price #

After Clerk renders the products, use a Clerk.js Event to loop through the products, call your server, and replace the placeholder with the actual price.

<script>
  var customer_id = INSERT_CUSTOMER_ID;
  Clerk("on", "rendered", function(content, data) {
    for (var i = 0; i < data.product_data.length; i++) {
      var product = data.product_data[i];
      var custom_price = FETCH_PRICE_FROM_SERVER(product.id, customer_id);
      var price_container = document.querySelector(
        "[data-clerk-product-id='" + product.id + "'] .clerk-price"
      );
      price_container.innerText = custom_price;
    }
  });
</script>

Replace INSERT_CUSTOMER_ID with your platform’s logic to get the logged-in customer’s ID.

Replace FETCH_PRICE_FROM_SERVER with an actual function that calls your backend and returns the price. This is typically an AJAX/fetch call to an endpoint you build.

data-clerk-product-id is an attribute that Clerk.js automatically adds to every rendered product, so you can target the right element.

How it works #

  1. Clerk returns products from the API and renders them with the placeholder text.

  2. The rendered event fires after the HTML is in the DOM.

  3. Your script loops through each product, calls your pricing endpoint, and replaces the placeholder with the real price.

Because prices are fetched client-side after rendering, there may be a brief moment where the placeholder is visible. Keep the placeholder text short and neutral.

Group prices #

Use this approach when you have a limited number of customer groups that each share the same pricing, for example “Retail”, “Wholesale”, and “VIP”.

Instead of fetching prices at render time, you include all group prices directly in the product data. A Formatter then picks the right price based on the logged-in customer’s group.

This is the recommended approach when possible, because prices display instantly with no loading state and no extra server calls.

1. Include prices in the data #

Add an attribute to your products in the Data Feed that contains a price for each customer group, as a JSON object:

{
  "id": 1,
  "name": "Lightsaber (Green)",
  "price": 199.99,
  "customer_group_prices": {
    "retail": 199.99,
    "wholesale": 149.99,
    "vip": 129.99
  }
}

The keys in customer_group_prices must match the group identifiers you will use in the next step.

2. Set the customer group #

Add a global variable to your Clerk.js config that holds the current customer’s group. This value should be set dynamically using your platform’s logic:

Clerk('config', {
  globals: {
    customer_group: "wholesale"
  }
});

Replace "wholesale" with your platform’s logic to output the current customer’s group ID. For visitors who are not logged in, you can fall back to a default group like "retail".

3. Create a formatter #

Add a Formatter that looks up the price for the current group. This can be added in the same Clerk.js config:

Clerk('config', {
  globals: {
    customer_group: "wholesale"
  },
  formatters: {
    getPrice: function(prices, customer_group) {
      return prices[customer_group];
    }
  }
});

The getPrice formatter receives the customer_group_prices object and the customer_group global, then returns the matching price.

4. Use in the Design #

Reference the formatter in your Design to display the correct price:

<a href="{{ product.url }}">
  <img src="{{ product.image }}" />
  <div class="clerk-product-name">{{ product.name }}</div>
  <div class="clerk-product-price">
    {{ product.customer_group_prices | getPrice customer_group }}
  </div>
</a>

The Design calls getPrice with the product’s price object and the global customer_group variable, and renders the result.

Platform examples #

The approaches above work the same way regardless of platform. The only part that changes is how you identify the logged-in customer and their group.

Below are examples for common platforms.

Shopify #

Clerk('config', {
  globals: {
    customer_group: {{ customer.tags | json }}[0] || "default"
  }
});

Shopify does not have built-in customer groups, but customer tags are commonly used as a substitute. Adjust the logic to match how your store identifies groups.

PrestaShop #

Clerk('config', {
  globals: {
    customer_group: "{$customer->id_default_group}"
  }
});

PrestaShop provides the customer’s default group ID through Smarty variables in the theme.

WooCommerce #

Clerk('config', {
  globals: {
    customer_group: "<?php echo wp_get_current_user()->roles[0] ?? 'guest'; ?>"
  }
});

WooCommerce uses WordPress roles. If you use a membership plugin, adapt this to output the relevant group identifier.

Magento 2 #

Clerk('config', {
  globals: {
    customer_group: "<?php echo $block->getCustomerGroupId(); ?>"
  }
});

Magento provides the customer group ID natively. Make sure the group IDs match the keys in your customer_group_prices data.