In wholesale there is no single price on the tag - there is a base price, group prices, negotiated price lists and quantity breaks, and WooCommerce can carry all of it. Nobody tells you that when the store is installed, though. A fresh WooCommerce knows one price per product and possibly a sale price. Everything else - the wholesaler pays less than the retail buyer, a regular customer has negotiated rates, the per-unit price drops on a full box - is a layer you have to design deliberately and add.
This piece is a map: which mechanisms come into play, when a plugin is enough, when you need logic built to measure, and where the trap sits that lets customer A see customer B’s prices.
A wholesale price list is layers, not one price
Before you touch any plugin, write down how pricing really works in your wholesale business. It is almost always made of layers:
- Base price - what an anonymous visitor sees, in other words retail
- Customer groups - retail, wholesale, VIP; each group buys at its own price level
- Negotiated per-customer price lists - a regular buyer has individual rates on selected products
- Quantity breaks - the more units in an order, the lower the price per unit
WooCommerce will handle all four layers at once. But the order in which they stack, and which one wins in a conflict (a VIP customer buys a wholesale quantity of a product they also have a separately negotiated rate on - which applies?), are design decisions. A store where nobody made them deliberately will sooner or later quote someone the wrong price. I write about the whole wholesale sales model at more length in the piece on WooCommerce B2B.
Prices after login - customer groups and roles
The foundation is assigning a customer to a group. Technically that is done with WordPress user roles or with groups from a B2B plugin: you approve a new wholesale account by hand (or after verifying the company’s VAT number), and from then on the store shows that customer their group’s prices - on the product page, in the cart and on the invoice.
The second part of the puzzle is hiding prices from visitors who are not logged in. Many wholesalers do not want to flash their rates at competitors, so an anonymous visitor sees a catalogue with no prices and a button along the lines of “Log in to see prices”, with the numbers appearing only after logging into an approved account. That setup has a bonus: a public catalogue without prices keeps working in Google for industry terms, so hiding the rates does not hide the whole offer. Groups are also useful for controlling product visibility - part of the range, a premium brand for example, can be shown to authorised buyers only. WooCommerce cannot do that on its own, but it is a standard feature of B2B plugins and a small piece of code where there is no plugin.
Different prices for different customers - per-customer price lists
Groups are enough as long as the terms are simple: retail pays full price, wholesale pays less. It gets awkward when a salesperson has negotiated individual rates with a specific buyer - across the whole range or on just a few items. Then you need a price list pinned to a single account that overrides the group price.
The good news: that is doable too. The bad news: this is exactly where off-the-shelf plugins start to creak, because editing hundreds of individual rates through the WordPress admin is a grind, and every exception to the rule breeds more. Hence a healthy rule: as few individual exceptions as you can manage - each one is a future mistake.
Quantity breaks and net versus gross
Quantity breaks are wholesale classics: buy by the unit and you pay the base rate, take a box and the per-unit price drops, take a pallet and it drops further. In WooCommerce you set that per product or per category, and the customer should see a table of the breaks on the product page before they load up the cart. The specific thresholds and discount levels are your commercial decision - the mechanism is there so the store enforces them for you.
The second thing wholesalers remember and implementers do not always: wholesale thinks in net, retail in gross. A company compares your rates against competitors’ price lists net of VAT; a consumer wants to see the final price including it. A store serving both has to display prices differently for each group - one setting in the wrong place can break a wholesaler’s trust on day one.
Off-the-shelf plugin or logic built to measure
The typical cases - price groups, hidden prices, simple breaks - are covered by mature B2B plugins, and that is where I would start, because it is the shortest route to a working store. The line runs where your own specifics begin: thousands of customers with individual terms maintained in an ERP, prices that depend on purchase history, combining breaks with negotiated rates. At that point the work turns into a fight with the plugin - working around its assumptions with hacks until nobody knows any more where the price on screen comes from.
In that situation the opposite direction is healthier: a small, custom pricing-logic layer written for your rules. Less code than in an all-in-one plugin, and every line corresponds to a real commercial rule you can point a finger at.
Trap number one: caching
Now the thing that sends stores my way “to be fixed after someone else”. A store is sped up with a cache - a mechanism that stores a page once generated and serves it to the next visitors without asking the database. Great for speed, lethal for individual prices: if the cache does not distinguish between users, it can store the page with customer A’s prices and show it to customer B. Or serve wholesale prices to visitors who are not logged in - exactly the ones competitors and retail buyers were never meant to see.
This is not a theoretical scare story, it is a bug I genuinely fix: pages with account-dependent prices must be excluded from the cache, or the cache must keep separate versions per group. After every change to the cache plugin it has to be checked again - which is why wholesale price lists and technical care for the store travel in pairs.
What helps: a simple test after every rollout and every settings change - open the store in a private window as a guest, then log into two different test accounts (retail and wholesale) and compare the price of the same product. Three looks, and they catch most of the mishaps with caching and groups.
Price lists from an ERP - the store pulls, it does not retype
If your price lists live in a trading system such as Subiekt or Optima, the store should pull them from there rather than hold a second, manually retyped copy. Manual retyping always ends the same way: someone changes a rate in the ERP, forgets the store, and the customer orders at the old price. How to join those two worlds - and what happens with invoices - I describe in the piece on ERP and e-invoicing integration.
Where to start
Not with a plugin. With a sheet of paper: write down your real pricing rules - groups, exceptions, breaks, who negotiates and what takes precedence. An hour with a sheet of paper saves weeks of rework, because only with the rules on paper can you see whether an off-the-shelf tool is enough or a made-to-measure layer is needed.
If you would rather have it put together by someone who has done it more than once - I quote these rollouts fixed-bid, roughly in the 5,000-10,000 PLN net range depending on how complex the rules are, always with a concrete written quote before the start. It is part of the optimization work on stores that already run and are meant to earn more.
Frequently asked questions
Does WooCommerce handle wholesale prices without plugins? Not out of the box - bare WooCommerce knows one price and a sale price. Customer groups, prices after login and quantity breaks are added with a B2B plugin or with custom code.
How do I hide prices from visitors who are not logged in? The store shows the catalogue without prices and a login button, with the rates appearing only after logging into an approved account. It is done with a B2B plugin or a short piece of code - the important part is that the cache does not serve those hidden prices to guests.
How do I set different prices for different customers in WooCommerce? The basis is groups (retail, wholesale, VIP) with their own price levels, and for customers with negotiated terms, an individual price list pinned to the account that overrides the group price.
Can wholesale prices be net and retail prices gross? Yes, WooCommerce can show net prices to logged-in companies and gross prices to retail buyers. It is a matter of configuring taxes and groups correctly - worth testing on test accounts before launch.
What about the customer who always phoned in for “their price”? After logging in they see exactly their price - and that is usually the strongest argument for moving them to ordering online. The phone stays for negotiations, not for reading out a price list.
Sitting on this yourself and unsure where to start? I speed up and repair existing sites and stores - Core Web Vitals, outages, the features that are missing. Tell me what is happening and you will get a concrete quote with a date.