Company-specific Product catalogs

Restrict the catalog each buyer sees using Product Selections, and avoid the inactive-selection trap that empties an assortment.

Ask about this Page
Copy for LLM
View as Markdown

After completing this page, you should be able to:

  • Restrict a buyer's catalog by attaching Product Selections to the buyer's Store.

  • Choose between Individual and IndividualExclusion modes for a given assortment.

  • Predict assortment behavior when Product Selections are inactive or absent.

In the Model your business structure path you used Product Selections to give different brand sites different assortments. The B2B problem is the same shape with a different driver: instead of a brand or region, the assortment is scoped to a buyer organization. This page assumes you know what a Product Selection is and focuses on the B2B-specific configuration and the one behavior that most often trips architects up.

Restricting a catalog to a buyer

A buyer organization sees a restricted catalog because of a chain you already assembled in Module 1: the Business Unit resolves to a Store, and the Store carries the Product Selections. That Store can be assigned directly or inherited from the Business Unit hierarchy. You do not assign Products to a Business Unit directly. You scope the Store, and the Business Unit inherits that scope by resolving to it.

This indirection is deliberate. Because the restriction lives on the Store, you can point several Business Units at the same Store to share an assortment, or give a Division its own Store (using the Store Override Rule from Module 1) when it needs a different one. The catalog follows the Store, not the buyer.

The default is permissive: a Store with no Product Selections includes every Product in the Project. Restriction is something you add deliberately by attaching at least one Product Selection.
Product Selections are the standard way to restrict a buyer's catalog, but they are not the only one. Some sellers drive restriction through search instead: middleware passes the buyer's price Channel, inventory Channel, or Customer Group as filter criteria on a Product Search query, so results return only the Products that match the buyer's negotiated scope. This approach is a more advanced customization that suits sellers who already resolve a buyer's catalog from pricing context rather than Store-attached selections. For scoping search to a buyer's context, see Product Search for B2B catalogs.

Choosing a mode: Individual vs IndividualExclusion

A Product Selection specifies a subset of the catalog in one of two modes. You pick the mode based on which list is shorter to maintain.

  • Individual: use this as an allowlist when the buyer should see a small, curated slice of the catalog.
  • IndividualExclusion: use this as a denylist when the buyer should see most of the catalog, with only a few restricted lines removed.
The two modes describe the same assortment from opposite ends. A buyer who may see 200 of 5,000 Products is far easier to model with Individual; a buyer who may see 4,950 of 5,000 is far easier to model with IndividualExclusion. The mode is fixed when you create the Product Selection, so choose based on how the assortment will be maintained over time, not just its initial size.
The following request creates an Individual Product Selection for Pacific Property Group's Commercial division. With Individual mode, the selection starts empty and you add Products to it explicitly.
POST /{projectKey}/product-selections HTTP/1.1
Content-Type: application/json

{
  "key": "pacific-commercial-assortment",
  "name": { "en-AU": "Pacific Commercial assortment" },
  "mode": "Individual"
}
In the response, mode confirms the selection's behavior and productCount starts at zero until you add Products.
{
  "id": "b2c3d4e5-1111-2222-3333-444455556666",
  "version": 1,
  "key": "pacific-commercial-assortment",
  "name": { "en-AU": "Pacific Commercial assortment" },
  "mode": "Individual",
  "productCount": 0
}
Before the selection changes a Store assortment, assign Products to it with the Add Product update action. The Store attachment only activates the Products already assigned to the Product Selection.

Attaching selections to a Store

A Product Selection has no effect until a Store uses it. Attaching it both links the selection and sets whether it is active for that Store.
POST /{projectKey}/stores/key=pacific-commercial-store HTTP/1.1
Content-Type: application/json

{
  "version": 2,
  "actions": [
    {
      "action": "addProductSelection",
      "productSelection": {
        "typeId": "product-selection",
        "key": "pacific-commercial-assortment"
      },
      "active": true
    }
  ]
}
The active flag defaults to false. Omitting it attaches the selection in an inactive state, so its Products do not become part of the assortment until you activate it. Set active: true explicitly when you intend the selection to take effect immediately.
A Store can hold more than one Product Selection, and its assortment is the union of all active selections. This is the standard pattern for "shared base plus buyer-specific extras": attach one shared Product Selection that every buyer's Store includes, and supplement it with a buyer-specific selection on each Store. For the field-level definition of the active flag, see ProductSelectionSetting.

The inactive-selection trap

The behavior that most often surprises architects is the difference between no selections and inactive selections, and it depends on the mode of the inactive selections:
  • A Store with no Product Selections includes all Products in the Project.
  • A Store with at least one active Product Selection includes only the Products in its active selections.
  • A Store whose selections are all inactive and include at least one Individual selection includes no Products at all, an empty assortment.
  • A Store whose only selections are inactive IndividualExclusion selections still includes all Products in the Project.
The trap is specific to assortments built with Individual selections: deactivating the last active selection does not fall back to "show everything." It falls forward to "show nothing." A buyer whose Store has one or more Individual selections attached but all of them inactive sees an empty catalog and cannot place an order, even though the Project is full of Products.
There are two ways to fall into this trap. The first is deactivating the Store's last active selection. The second is quieter: because active defaults to false, attaching a selection without setting active: true adds it in an inactive state. A Store whose only Individual selection was added with the default flag is already empty, before anyone deactivates anything.
Deactivating every Product Selection on a Store does not automatically revert it to showing all Products. If any of those inactive selections uses Individual mode, the assortment becomes empty; only a Store with no Product Selections, or one left with solely inactive IndividualExclusion selections, shows the full catalog. When troubleshooting an unexpectedly empty B2B catalog, check the active flag and mode on each of the Store's Product Selections before anything else.

You toggle the active state with the Change Product Selection Active action. The following request deactivates a selection, the operation behind an empty-assortment incident if it is the Store's only selection.

POST /{projectKey}/stores/key=pacific-commercial-store HTTP/1.1
Content-Type: application/json

{
  "version": 3,
  "actions": [
    {
      "action": "changeProductSelectionActive",
      "productSelection": {
        "typeId": "product-selection",
        "key": "pacific-commercial-assortment"
      },
      "active": false
    }
  ]
}

Worked example: Pacific Property Group

Pacific Property Group is a Company with two Divisions, Residential and Commercial. Both buy from Zen Electron Trade's catalog, but Commercial is entitled to a broader range that includes commercial-grade appliances Residential should not see.

A clean way to model this with the shared-base pattern:

  1. Create a shared Product Selection in Individual mode, zen-trade-core, holding the Products both Divisions may buy. Attach it, active, to both Divisions' Stores.
  2. Create a Commercial-only Product Selection in Individual mode, pacific-commercial-assortment, holding only the commercial-grade Products. Attach it, active, to the Commercial Store only.
  3. Residential's Store carries just zen-trade-core; its assortment is the shared range.
  4. Commercial's Store carries zen-trade-core plus pacific-commercial-assortment; its assortment is the union: the shared range plus commercial-grade lines.
Residential and Commercial now see different catalogs from the same underlying Products, with no duplication. If a future audit requires temporarily pulling the commercial-grade range, you deactivate pacific-commercial-assortment on the Commercial Store, and because zen-trade-core is still active there, the Store falls back to the shared range rather than to an empty assortment, avoiding the inactive-selection trap.
Had you instead modeled Commercial with a single selection covering its full range, deactivating it would have emptied the Store entirely. Keeping the shared base as its own always-active selection is what makes the configuration safe to change.

Key takeaways

  • A buyer's catalog is restricted by attaching Product Selections to the buyer's Store; Products are never assigned to a Business Unit directly.
  • A Store with no Product Selections shows every Product; restriction is something you add deliberately.
  • Individual mode lists the Products to include; IndividualExclusion lists the Products to exclude. Choose the mode whose list is shorter to maintain.
  • A Store's assortment is the union of its active Product Selections, which enables a shared-base-plus-buyer-specific pattern.
  • Deactivating every selection on a Store empties it when any inactive selection uses Individual mode, rather than reverting to the full catalog: the inactive-selection trap.

Test your knowledge