# Product rules per customer group

URL: https://docs.sparklayer.io/help/storefront/product-settings
Applies to: Shopify, BigCommerce, WooCommerce, Magento

Give customer groups their own pack sizes, quantity limits, reserved stock and product visibility with the sparklayer.settings metafield on each variant.

> **Quick summary**
>
> - Product settings give one [customer group](https://docs.sparklayer.io/help/glossary.md#customer-group) its own rules for a product. Customers in that group can get a different pack size, minimum or maximum quantity, or reserved stock. You can also hide a product from the group, or stop them ordering it.
> - You set them in a field on each product variant in your platform's admin, called the `sparklayer.settings` [metafield](https://docs.sparklayer.io/help/glossary.md#metafields). The [form on this page](#set-product-settings-for-a-customer-group) writes its value for you to copy.
> - For a rule that applies to all B2B customers, use the simpler single-value fields in [Quantity rules](https://docs.sparklayer.io/help/storefront/quantity-rules.md) and [Stock display](https://docs.sparklayer.io/help/storefront/stock-display.md#reserving-stock) instead.
> - Available on every plan, on Shopify, BigCommerce, WooCommerce and Magento. Wix doesn't support metafields, so these settings aren't available on Wix.

## How it works

Customers in each group see the product with their group's rules, for example a pack size of 50 instead of 1 in the quantity selector.

Behind this is a metafield: an extra field on a product or variant in your eCommerce platform's admin. SparkLayer reads the `sparklayer.settings` metafield on each product variant. Its value is a list with one entry per customer group. Each entry names the group and the settings that apply to it:

```javascript
[
    {
        "customer_group": "gold-tier",
        "min_order_quantity": 5,
        "max_order_quantity": 50
    }
]
```

The `base` entry is the default for every customer group. An entry for a specific group, such as `influencer`, overrides it for that group. You only need to include the settings you want to set. See [Which rule wins](#which-rule-wins).

To set a rule for all customers without customer groups, you can use the individual metafields instead, such as `sparklayer.pack_size` in [Quantity rules](https://docs.sparklayer.io/help/storefront/quantity-rules.md) or `sparklayer.reserve_stock_quantity` in [Stock display](https://docs.sparklayer.io/help/storefront/stock-display.md#reserving-stock). Don't combine the two on one variant: when a variant has a `sparklayer.settings` value, it takes priority over the individual metafields.

> **Before you start: turn the metafield on in SparkLayer**
>
> SparkLayer doesn't read a metafield until it's enabled in SparkLayer. Go to **Integrations > Platform** in the SparkLayer Dashboard ([open](https://app.sparklayer.io/configuration/integrations/platform)), or **SparkLayer Wholesale > Integrations > Platform** in the Shopify app and, in the **Metafields** card, click **Configure** next to **SparkLayer metafields**, then enable the product settings metafield. If you create the definition yourself in Shopify, it must read exactly `sparklayer.settings`, with the type **JSON**, on **Variants**. See [Common mistake: wrong namespace](https://docs.sparklayer.io/help/platforms/shopify/metafields.md#add-metafields-by-hand).

## Which rule wins

When SparkLayer works out a customer's rules for a variant, it checks in this order:

1. **The customer's group entry** in `sparklayer.settings`, if there is one. Its settings override the `base` entry.
2. **The `base` entry** in `sparklayer.settings`. It's the default for every customer group, including groups that have no entry of their own.
3. **The individual metafields**, such as `sparklayer.pack_size` or `sparklayer.max_order_quantity`, but only when the variant has no `sparklayer.settings` value at all.

So if you use `sparklayer.settings` to hide a product from one group, and you also want a pack size or a maximum quantity, put those keys in the JSON too, inside each group's entry. Don't rely on the individual metafields for them.

For example, this value on a variant:

```json
[
  { "customer_group": "base", "pack_size": 50 },
  { "customer_group": "retail-partners", "pack_size": 10, "display": true },
  { "customer_group": "distributors", "display": false }
]
```

| Customer group | What its customers get |
| --- | --- |
| **Base**, and every group with no entry of its own | The product, in packs of 50 |
| `retail-partners` | The product, in packs of 10 |
| `distributors` | The product is hidden |

If the same variant also had `sparklayer.pack_size` set to `6`, nobody would see packs of 6: the `sparklayer.settings` value wins.

Quantity pricing can set a minimum too. The lowest quantity tier in the customer's price list is the smallest quantity they can order. If the first tier is 50+, customers can't order fewer than 50 and may see "Unavailable in selected quantity". Add a tier from 1 to fix it. See [Quantity pricing](https://docs.sparklayer.io/help/pricing/quantity-pricing.md).

## What hides what

`display: false` in `sparklayer.settings` hides a product inside SparkLayer's own views. Hiding it from your Shopify theme's pages needs the free [B2B Catalogs](https://docs.sparklayer.io/help/storefront/b2b-catalogs.md) app as well.

**Variant rules don't hide anything from retail shoppers.** `sparklayer.settings` rules only apply to signed-in B2B customers, by customer group. Retail shoppers and signed-out visitors see every variant your theme shows, and Shopify can't hide a single variant of a product from them. To keep one variant for B2B customers only, such as a 12-pack case, make it a separate product. On Shopify, tag that product `b2b-only` with B2B Catalogs.

**Shopify only:**

| What you use | SparkLayer's views (search, quick order, quick buy, cart) | Collection and search pages | Product page | Featured sections |
| --- | --- | --- | --- | --- |
| `display: false` in `sparklayer.settings` | Hidden | Still shown | Still opens. SparkLayer's product interface leaves the variant out | Still shown |
| `b2b-only` or `b2c-only` product tag, with B2B Catalogs | Not hidden | Hidden | Access denied page | Hidden |
| [Catalogs per customer group](https://docs.sparklayer.io/help/storefront/b2b-catalogs/configuring-advanced-catalogs.md): `display: false` for a group, with B2B Catalogs | Hidden | Hidden | Access denied page | Hidden |

**Things to check when a product isn't hidden**

- **B2B Catalogs must be enabled on your live theme.** The `b2b-only` and `b2c-only` tags only work when the app is installed and enabled on your published theme. See [Enable or disable it on other themes](https://docs.sparklayer.io/help/storefront/b2b-catalogs.md#enable-or-disable-it-on-other-themes).
- **After an app update or a theme change**, if `b2b-only` products appear in a section such as a featured collection, disable B2B Catalogs on the live theme and enable it again. Disabling removes your changes to the access denied page, so keep a copy first.
- **The JSON uses straight quotes** (`"`). Curly quotes (“ ”), which word processors add, stop the value working. Build it with the [form](#set-product-settings-for-a-customer-group) to be safe.
- **A whole collection can't be hidden.** B2B Catalogs hides products, not collections. A third-party Shopify app can restrict who can open a collection's URL.
- **Collection pages, search and filter counts.** Hiding happens in your theme as the page loads, so a hidden product can still take a place in a collection grid and count towards product and filter totals. See [Collection grids, search and filter counts](https://docs.sparklayer.io/help/storefront/b2b-catalogs/limitations.md#grids-search-and-filter-counts).

To show a product to everyone but its price only to some customers ("price on application"), see [Price on application](https://docs.sparklayer.io/help/pricing/managing-pricing.md#price-on-application).

### Example: a product range for each customer group

A supplier sells to retail shoppers, salons and stockists from one Shopify store. Salons should see the professional range, stockists the retail-pack range, and retail shoppers neither.

1. Tag every product in both ranges `b2b-only`, so retail shoppers and signed-out visitors don't see them.

2. On each variant in the professional range, set `sparklayer.settings` to show it only to the `salons` group:

   ```json
   [
     { "customer_group": "base", "display": false },
     { "customer_group": "salons", "display": true }
   ]
   ```

3. On each variant in the retail-pack range, do the same for the `stockists` group:

   ```json
   [
     { "customer_group": "base", "display": false },
     { "customer_group": "stockists", "display": true }
   ]
   ```

| Who | Professional range | Retail-pack range | Everything else |
| --- | --- | --- | --- |
| Retail shoppers and signed-out visitors | Hidden (`b2b-only`) | Hidden (`b2b-only`) | Shown |
| Customers tagged `b2b-salons` | Shown | Hidden | Shown |
| Customers tagged `b2b-stockists` | Hidden | Shown | Shown |
| Any other B2B customer | Hidden | Hidden | Shown |

Rules are per customer group, not per customer. To give one customer their own range, put them in a group of their own. Build each value with the [form](#set-product-settings-for-a-customer-group), which also shows how to fill in many variants at once.

## Set product settings for a customer group

**Step 1.** **Create the metafield definition**

You only do this once. It adds the `sparklayer.settings` field to every variant.

- **Shopify:** in SparkLayer, go to **Integrations > Platform** in the SparkLayer Dashboard ([open](https://app.sparklayer.io/configuration/integrations/platform)), or **SparkLayer Wholesale > Integrations > Platform** in the Shopify app and, in the **Metafields** card, click **Configure** next to **SparkLayer metafields**. SparkLayer adds its metafields for you.
- **Other platforms:** follow your platform's guide: [BigCommerce](https://docs.sparklayer.io/help/platforms/bigcommerce/metafields.md), [WooCommerce](https://docs.sparklayer.io/help/platforms/woocommerce/metafields.md) or [Magento](https://docs.sparklayer.io/help/platforms/magento/metafields.md).

**More detail**

**Shopify only:**

On Shopify, you can also create the definition yourself at **Settings > Custom data > Variants** ([open in the Shopify admin](https://admin.shopify.com/settings/custom_data/productvariant/metafields)), using the values in the [metafield reference](#metafield-reference).

**Step 2.** **Find the customer group's handle**

Go to **Customers > Groups** in the SparkLayer Dashboard ([open](https://app.sparklayer.io/customers/groups)), or **SparkLayer Wholesale > Customers > Customer groups** in the Shopify app, click the group's name and find its **Handle (or ID)**, for example `base` for the base customer group or `vip` for a group with the handle `vip`. The group's Shopify tag is `b2b-` followed by the handle. In the metafield, always write it in lowercase. See [Customer groups](https://docs.sparklayer.io/help/customers/customer-groups.md#create-a-customer-group) for how handles work.

**Step 3.** **Build the value and add it to the variant**

Fill in the form below: one entry per customer group, with only the settings you want. It writes the value for you. Click **Copy**, then open the product variant in your platform's admin, paste the value into the `sparklayer.settings` field and save the variant.

**Lots of products? Fill them in one table (Shopify):** in your Shopify admin, go to **Products**, tick the products and click **Edit products**. Click **Columns**, tick the SparkLayer field under **Metafields**, type the values and click **Save**. See [Shopify's guide](https://help.shopify.com/en/manual/custom-data/metafields/bulk-edit-metafields).

## Examples

### Exclusive products for one group

Company X has 2 customer groups:

1. **Base**: standard B2B customers
2. **Gold tier**: preferred customers with discounted pricing and access to exclusive products

To make a range exclusive to Gold tier, they add this to the exclusive variants:

```javascript
[
    {
        "customer_group": "base",
        "display": false,
        "sell": false
    },
    {
        "customer_group": "gold-tier",
        "display": true,
        "sell": true
    }
]
```

The `base` entry hides the variants from every group, and the `gold-tier` entry overrides it, so these variants are now only visible to Gold tier customers. Variants with no `sparklayer.settings` value stay visible to everyone, so the rest of the catalogue needs nothing.

### Different pack sizes for each group

Company X has 2 customer groups:

1. **Wholesale**: other businesses that stock their products, who order large quantities
2. **Influencer**: people who promote their products on social media, who only need single units

To sell in packs of 50 to wholesale customers and singly to influencers, they use:

```text
[
    {
        "customer_group":"base",
        "pack_size":50
    },
    {
        "customer_group":"influencer",
        "pack_size":1
    }
]
```

The `base` entry applies to all customer groups. The second entry gives the `influencer` group a pack size of 1.

## Available product settings

You can set any of these for a customer group:

| Setting | Type | What it does | Default |
| --- | --- | --- | --- |
| `customer_group` | `string` | The customer group the settings apply to. Required in every entry. | |
| `pack_size` | `integer or null` | Only allow the product to be bought in multiples of this number. | `1` |
| `reserve_stock_quantity` | `integer or null` | Always keep this much stock back, usually so retail (DTC) customers can still buy it. | `null` |
| `min_order_quantity` | `integer or null` | Only allow the product to be bought in at least this quantity. | `null` |
| `max_order_quantity` | `integer or null` | Only allow the product to be bought in at most this quantity. | `null` |
| `min_order_parent_quantity` | `integer or null` | Minimum quantity across all of the product's variants. | `null` |
| `max_order_parent_quantity` | `integer or null` | Maximum quantity across all of the product's variants. | `null` |
| `display` | `boolean or null` | Whether the product shows in the frontend interfaces. | `null` |
| `sell` | `boolean or null` | Whether the product can be added to the cart. | `null` |

## Metafield reference

Use these values if you create the metafield definition yourself:

| Field | Value |
| --- | --- |
| **Custom data type** | Variants ([Shopify](https://admin.shopify.com/settings/custom_data/productvariant/metafields)) |
| **Metafield type** | `JSON` |
| **Namespace** | `sparklayer` |
| **Key** | `settings` |
| **Value** | A list of entries, for example:<br />`[{"customer_group": "base","pack_size": 1,"reserve_stock_quantity": 10,"min_order_quantity": 5,"max_order_quantity": 50,"min_order_parent_quantity": 5,"max_order_parent_quantity": 50,"display": true,"sell": true}]` |

## Troubleshooting

**Diagnose: Product showing to the wrong customers?** Check which tool should hide it.

1. **What’s happening?** Pick the closest match.
   - A product shows to customers who shouldn’t see it: go to question 2
   - A product is hidden from customers who should see it: go to fix A (Check the product itself)
2. **Where do they see it?** SparkLayer’s own views and your theme’s pages are hidden by different tools.
   - In SparkLayer’s quick order, search or cart: go to question 3
   - On collection, product or search pages: go to question 4
   - In a section such as a featured collection: go to question 5
3. **Does the variant’s `sparklayer.settings` metafield set `"display": false` for the customer’s group?** Use the group’s handle, for example `base`. Entries for a group override the `base` entry. Where to look: Products > select a variant > Metafields (Shopify admin).
   - Yes: go to question 6
   - No: go to fix B (Add a rule for that group)
4. **Is the free B2B Catalogs app installed and enabled on your live theme?** The visibility metafield only hides products inside SparkLayer. Hiding them from your theme’s pages needs B2B Catalogs. Where to look: Online Store > Themes (Shopify admin).
   - Yes: go to question 7
   - No / not sure: go to fix C (Install B2B Catalogs and enable it on your live theme)
5. **Is the free B2B Catalogs app installed and enabled on your live theme?** Sections such as featured collections are your theme’s, so only B2B Catalogs can hide products in them. Where to look: Online Store > Themes (Shopify admin).
   - Yes: go to fix D (Turn B2B Catalogs off and on again on your live theme)
   - No / not sure: go to fix C (Install B2B Catalogs and enable it on your live theme)
6. **Is the JSON written with straight quotes and valid formatting?** Curly quotes from a word processor, or a missing comma or bracket, break every rule in the value. Paste it into a JSON checker if unsure.
   - Yes: go to fix E (Everything checks out)
   - No / not sure: go to fix F (Fix the JSON)
7. **Is the product tagged, for example `b2b-only`, or in a catalog for the right groups?** `b2b-only` hides a product from retail shoppers. `b2c-only` hides it from B2B customers. Where to look: Products > select the product (Shopify admin).
   - Yes: go to fix D (Turn B2B Catalogs off and on again on your live theme)
   - No: go to fix G (Tag the product)

**Fixes**

- **A. Check the product itself** A product that should show but doesn’t usually has a SKU, status, sales channel or price list issue. Next: Product missing, no B2B price or “Unavailable”?
- **B. Add a rule for that group** Add an entry for the customer’s group with `"display": false` to the variant’s `sparklayer.settings` metafield. To hide it from every B2B customer, use the `base` group. Where: Products > select a variant > Metafields (Shopify admin). See [Product settings](https://docs.sparklayer.io/help/storefront/product-settings.md).
- **C. Install B2B Catalogs and enable it on your live theme** Without it, tags such as `b2b-only` and the visibility metafield can’t hide products on your theme’s pages. Install the free app, then enable it on your live (published) theme. See [B2B Catalogs](https://docs.sparklayer.io/help/storefront/b2b-catalogs.md).
- **D. Turn B2B Catalogs off and on again on your live theme** After app updates or theme changes, the live theme may not have the latest B2B Catalogs code. Turn it off and on again on the live theme. If the product still shows in a section, send us the page link. See [B2B Catalogs](https://docs.sparklayer.io/help/storefront/b2b-catalogs.md).
- **E. Everything checks out** Your setup looks right, so we'll take it from here. Send us your answers with the product link and the customer’s email.
- **F. Fix the JSON** Retype the quotes as straight quotes, correct the formatting and save. Copy an example from Product settings as a starting point. See [Product settings examples](https://docs.sparklayer.io/help/storefront/product-settings.md).
- **G. Tag the product** Add `b2b-only` to keep it from retail shoppers, or set up a catalog for the groups that should see it. Where: Products > select the product (Shopify admin). See [Catalogs per customer group](https://docs.sparklayer.io/help/storefront/b2b-catalogs/configuring-advanced-catalogs.md).

## FAQs

**Do I need to include every setting in the value?**

No. Include `customer_group` and the settings you want to set. Remove the others, or set them to `null`.

**Why aren't my settings being applied?**

Check that:

- The metafield is **enabled in SparkLayer**, at **Integrations > Platform** in the SparkLayer Dashboard ([open](https://app.sparklayer.io/configuration/integrations/platform)), or **SparkLayer Wholesale > Integrations > Platform** in the Shopify app (**Metafields** card).
- The field is **on the variant**, not the product, and its definition reads exactly `sparklayer.settings`.
- The customer group handle **matches the group's Handle (or ID)**.
- The JSON uses **straight quotes**. If you typed the value by hand, rebuild it with the [form](#set-product-settings-for-a-customer-group) and paste it in again: a missing comma or a curly quote mark stops it working.
- You've put pack sizes and quantity limits **inside the JSON**. The individual metafields, such as `sparklayer.pack_size`, are ignored on a variant that has a `sparklayer.settings` value. See [Which rule wins](#which-rule-wins).
