This tutorial series covers how you can use Medusa and its different components and features to implement a B2B commerce store. The series is split in two parts:
- Part one: Covers how to prepare your backend to handle B2B shopping experiences
- Part two: Covers how to customize our Next.js storefront to create a B2B storefront.
You can check out the full code for this tutorial series in this GitHub repository.
Why use open source for B2B commerce?
B2B commerce has seen rapid growth in recent years and is now among the top revenue-generating channels for B2B businesses according to a recent McKinsey study.
Yet, many businesses struggle to get their B2B setup right. Mostly, challenges come from a need to build more custom logic and integration to handle the higher complexity of B2B sales.
Some examples of B2B complexities:
- Unique customers: Special purchasing agreements require the possibility to create custom logic for individual B2B customer groups
- Special pricing: The commerce engine needs to be able to differentiate pricing and discounts based on customer groups
- Omnichannel need: Selling to B2B is often not a one-channel-effort and the commerce engine needs to be able to handle multiple channels
Why use Medusa
Medusa is an open source composable commerce engine. Unlike existing proprietary platforms, its value proposition comes from the flexible and open architecture that equips tech teams with a unique possibility to build bespoke commerce setups. This is even more important in the context of complex B2B businesses
Medusa provides the foundational commerce infrastructure for businesses to take full ownership of their tech stack and avoid compromising on business needs. Custom logic can be injected natively instead of through hacky workarounds.
Our developer-first approach is a central element in this promise of customization and composability. That is why we want to give developers the essential features we find necessary for building a B2B commerce setup.
In this guide, we’ll take you through how you combine these to achieve a scaleable B2B setup.
Medusa’s Recipe for a B2B Commerce Store
Medusa provides many essential commerce features. For the B2B case, in particular, you’ll be using the following features in Medusa to create a B2B commerce store:
- Sales Channels: Sales Channels allow you to segment your product catalog across the channels you sell through. For B2B commerce stores, Sales Channels can be used to specify which products are available for B2B customers.
- Customer Groups: Customer Groups allow you to combine customers with similar attributes. For B2B commerce stores, they can be used to combine customers that belong to an organization that purchases products from your store.
- Price Lists: Price Lists can be used to override products’ prices based on different conditions. For B2B commerce stores, they can be used to set the prices negotiated with B2B customers.
Prerequisites
Node.js
Medusa is a Node.js commerce platform. So, you must have at least version 14 of Node.js installed on your machine.
PostgreSQL
Although Medusa works with an SQLite database, it is highly recommended to use PostgreSQL instead. You can follow our documentation to learn how to install it.
Make sure to also create an empty PostgreSQL database.
Medusa CLI Tool
You’ll need Medusa’s CLI tool to install a Medusa server. You can install the CLI tool with the following command:
npm install @medusajs/medusa-cli -g
If you face any error with this installation, please check out the troubleshooting guide.
Install the Medusa Server
In your terminal, run the following command to install the Medusa server:
medusa new b2b-server
This will install a Medusa server under a newly created b2b-server
directory. Once the command is done executing, change to that directory:
cd b2b-server
Configure Medusa Server
Enable Sales Channels
Sales Channels is a feature in Medusa that allows you to separate between the different sales channels you sell your products in, and ensure different products are available for each sales channel. For example, you can have a Sales Channel for mobile stores, another for website storefronts, and so on.
In the case of B2B stores, you can create a B2B Sales Channel that groups all wholesale products that should only be available to B2B customers.
Sales Channels is currently in beta mode, so you have to enable it manually to use it.
In the .env
file of your Medusa server, add the following environment variable:
MEDUSA_FF_SALES_CHANNELS=true
This will enable sales channels on your Medusa server.
Add Database Configuration
By default, Medusa runs with an SQLite database. This is great for development purposes, but for an optimal experience, it’s recommended to use a PostgreSQL database instead.
In .env
, add the following environment variable:
DATABASE_URL=<DATABASE_URL>
Where <DATABASE_URL>
is the URL of your database. If you’re unsure of what your URL is, check out PostgreSQL’s documentation to see its format.
Then, in medusa-config.js
, you’ll find an exported object similar to this:
module.exports = {
projectConfig: {
// redis_url: REDIS_URL,
// For more production-like environment install PostgresQL
// database_url: DATABASE_URL,
// database_type: "postgres",
database_database: "./medusa-db.sql",
database_type: "sqlite",
store_cors: STORE_CORS,
admin_cors: ADMIN_CORS,
},
plugins,
};
Remove the SQLite database configuration and un-comment the PostgreSQL configurations as such:
module.exports = {
projectConfig: {
// redis_url: REDIS_URL,
database_url: DATABASE_URL,
database_type: "postgres",
store_cors: STORE_CORS,
admin_cors: ADMIN_CORS,
},
plugins,
};
Run Migrations
The Medusa server has migrations defined for all its entities so that you can smoothly prepare your database schema for your commerce store.
Run the following command in the root directory of your Medusa server to migrate entities into your database schema:
medusa migrations run
Seed Database
This step is optional but recommended for the sake of the tutorial. You can seed your database with demo data such as an admin user and products.
Run the following command in the root directory of the Medusa server to seed your database:
npm run seed
Install a File Service Plugin
File service plugins in Medusa are used to store files such as product images. Although this step is optional for this tutorial, if you want to add products with images in your store, you must install a file service plugin.
Medusa provides three official file service plugins: MinIO, Spaces, and S3. You can follow along with the documentation of the file service plugin of your choice to learn how to install it.
Test Medusa Server
In the root directory of your Medusa server, run the following command to run your Medusa server:
npm start
This runs your Medusa server on port 9000
. You can test it out by opening localhost:9000/store/products
in your browser. If you seeded the database earlier, you should see many products in the response. Otherwise, you can see an empty array of products in the response.
It’s recommended to keep the Medusa server running throughout the tutorial as you’ll need it for all the steps.
Install Medusa Admin
Medusa provides an admin panel that allows you to manage the different settings and data of your Medusa server, including products, sales channels, customers, and much more.
In a different directory than the Medusa server, run the following command to clone the Admin panel from GitHub:
git clone https://github.com/medusajs/admin b2b-admin
This creates a new directory b2b-admin
and clones the codebase of the Medusa admin into it.
Change into the new directory and install the dependencies with NPM:
cd b2b-admin && npm install
Test Medusa Admin
Once the NPM installation is done, make sure that the Medusa server is running, then run the following command in the b2b-admin
directory:
npm start
This runs the Medusa admin on localhost:7000
by default. If you open it in your browser, you should see a login screen.
If you seeded the database earlier, you can log in with the email admin@medusa-test.com
and password supersecret
. If not, you can create a user using the Medusa CLI tool.
Add Wholesale Products
After you log in to the admin, go to the Products page from the sidebar. If you’ve seeded the database you should find some products already added.
To add new products:
- Go to the Products page.
- Click on the New Product button at the top right.
- Enter details related to general information, variants, prices, and more.
- Once you’re done, click on the Publish Products button.
You can add as many products as you want.
Create B2B Sales Channel
As mentioned earlier, you’ll create a B2B Sales Channel to add Wholesale Products. These products will then only be available in that sales channel.
To create a B2B Sales Channel:
- Go to Settings → Sales Channels
- In the Sales Channels section on the left, click on the plus icon next to the title of the section.
- The form to create a new sales channel will open. Enter a name and description for the sales channel. You can set the name to “B2B”
- Once you’re done, click on the Publish Channel button.
Add Products to the Sales Channel
Now, you can add products to your B2B sales channel. To do that:
- Go to Settings → Sales Channels
- In the sales channels list on the left, choose the B2B sales channel.
- At the top right of the right section, click on the three dots icon.
- Choose from the dropdown list “Add products”.
- Select the products you want to add to the sales channel.
- Once you’re done, click on the Save button.
Create B2B Customer Groups
Customer groups allow you to group together customers that have common criteria. You can then use this group to apply special pricing for these customers.
In the B2B case in this tutorial, you’ll create a customer group for every organization that will be a B2B customer.
To differentiate every B2B customer group from other customer groups, you’ll also add in the metadata
field of the customer group an is_b2b
flag.
To create a B2B customer group in the admin:
- Go to the Customers page.
- Choose the Groups headline.
- Click on the New Group button.
- In the new window that opens:
- Enter the name of the organization in the Title field.
- Click on the Add Metadata button. This shows additional Key and Value fields.
- Enter in the Key field
is_b2b
and in the Value fieldtrue
.
- Once you’re done, click on the Publish Group button.
Do these steps for every organization you want to add.
Create Customers
Before you can add customers to the customer group, you need to create the customers. You’ll need to use the API Endpoints to do that. You can use a tool like Postman to send requests, or you can use cURL.
Start by logging in using the User Login endpoint. Send a POST
request to localhost:9000/admin/auth
with the following request body:
{
"email": "admin@medusa-test.com",
"password": "supersecret"
}
You can replace the email and password with your own if you’re using different ones.
When you log, the Session ID is set in the cookies. In tools like Postman, you can go ahead and send the rest of the requests and it appends that Session ID to the cookies of those requests. If you’re using cURL, you can learn how to set the Cookie Session ID in our documentation.
Next, you’ll create a customer using the Create a Customer endpoint. Send a POST
request to localhost:9000/admin/customers
with the following request body:
{
"email": "customer@acme.com",
"first_name": "Acme",
"last_name": "Customer",
"password": "supersecret"
}
You can change the values of any of the fields as necessary.
You can add as many customers as you want. Once you’re done, if you go back to the Medusa admin, you can see the new customer on the Customers page.
Add Customers to Customer Group
In this section, you’ll add the customers you created to the customer group of their organization.
To add customers to a customer group:
- Go to each of the B2B customer group’s details page.
- Click on the “Edit customers” button at the top right of the Customers section.
- Check the box next to every customer you want to add to the group.
- Click on the Save button.
Create B2B Price List
Price lists in Medusa are a list of prices that are applied on specific products under defined conditions. For example, you can set different prices for different customer groups. You can also specify prices based on the quantity of the product in the cart.
In this section, you’ll create a B2B Price List that applies to all the B2B customer groups you created in the previous sections. You’ll then set different prices for each of the wholesale products.
To create a price list:
- Go to the Pricing page.
- Click on the “Add price list” button at the top right.
- In the new form that opens:
- Choose Override under the Price list type.
- Expand the General collapsible section. Enter a name for the price list (for example, B2B) and a description.
- Expand the Configuration collapsible section. Then, toggle the Customer availability field and choose all the B2B customer groups you created.
- You can add prices manually at this point, you can add them manually after creating the price list, or you can import prices from a CSV file after creation. To add prices manually now:
- Expand the Prices collapsible section.
- Click on the Add Products Manually button.
- Check all the products you want to add then click the Save button.
- For all of the products you added, click on the + icon. This will expand the list of variants for that product. You can specify the same prices for all variants, remove some of the variants from the price list, and specify different prices for all variants. To specify prices:
- Click on the three dots icon next to each of the variants and choose Edit prices.
- In the new window, either select Apply overrides on selected variants or Apply on all variants and add the price for every currency in your store.
- Once you’re done, click Save and Close.
- Once you’re done, click on the Publish price list button at the top right.
Importing Prices
As mentioned earlier, you can import prices from a CSV file. This will replace any prices you’ve added before.
To import prices from a CSV file:
- Go to the B2B price list’s details page.
- In the Prices section, click on the three dots icon and click on “Import price list” from the dropdown.
- In the new window:
- If you’re unsure of what the CSV file’s format must be like, you can download a template CSV file by clicking the download icon.
- To upload the CSV file you want to import prices from, either:
- Drag and drop the file into the dashed box;
- Or click on the dashed box and choose the file you want to import the prices from.
- After you upload the CSV file, you can check the number of prices to be added above the uploaded file’s name.
- Once you’re done choosing a file to import prices from, click on the Import List button.
Adding Prices Using the APIs
You can also add prices using the API endpoints. These provide you with even more options than what is currently available in the admin, such as prices based on quantity in the cart.
To add prices to a price list, send a POST
request to {{BACKEND_URL}}/admin/price-lists/{price_list_id}/prices/batch
(replacing {price_list_id}
with the ID of the price list) with the following request body:
{
"prices": [
{
"amount": 100,
"variant_id": "{variant_id_1}",
"currency_code": "eur",
"min_quantity": 10
},
{
"amount": 200,
"variant_id": "{variant_id_2}",
"currency_code": "eur",
"max_quantity": 9
}
]
}
Each object in the prices
array is an object that contains the amount, the ID of the variant to apply the price to, the currency code, and other conditions such as min_quantity
and max_quantity
. You can check all the conditions you can pass by referring to the API Reference.
Add Endpoint to Check Customer Group
The last step is to create an endpoint on the Medusa server to allow you to check whether a customer belongs to a B2B customer group or not. This is helpful when you start customizing the storefront, as you need to figure out what type of customer is logged in.
To create an endpoint, create the file b2b-server/src/api/index.ts
with the following content:
import { CustomerService } from "@medusajs/medusa"
import { Router } from "express"
import authenticate from "@medusajs/medusa/dist/api/middlewares/authenticate-customer"
import cors from "cors"
import { projectConfig } from "../../medusa-config"
export default () => {
const router = Router()
const corsOptions = {
origin: projectConfig.store_cors.split(","),
credentials: true,
}
router.options("/store/customers/is-b2b", cors(corsOptions))
router.get("/store/customers/is-b2b", cors(corsOptions), authenticate(), async (req, res) => {
if (!req.user) {
return res.json({
is_b2b: false
})
}
const customerService: CustomerService = req.scope.resolve('customerService');
const customer = await customerService
.retrieve(req.user.customer_id, {
relations: ['groups']
})
const is_b2b = customer.groups.some((group) => group.metadata.is_b2b === "true");
return res.json({
is_b2b
})
})
return router;
}
In this file, you add a new storefront endpoint /store/customers/is-b2b
. This endpoint checks if the currently logged-in customer belongs to a B2B customer group.
Looking back at when you created each customer group, you set in its metadata
field is_b2b
to true
. In this endpoint, you retrieve the customer along with their customer groups, then check if any of its customer groups has the is_b2b
field set to true
.
Test Endpoint
To test the endpoint, first, run the following command to transpile the TypeScript file into the dist
directory:
npm run build
Then, start the Medusa server:
npm start
Using a tool like Postman, try to first login with a B2B customer then send a request to localhost:9000/store/customers/is-b2b
. You should see that it returns is_b2b
with the value true
.
If you try sending that same request when the customer is logged-out, or when the customer does not belong to a B2B customer group, is_b2b
in the response should be set to false
.
Next Steps
This concludes preparing your Medusa backend to be used for a B2B shopping experience. In the next part of the tutorial, you’ll learn how you can customize the Next.js storefront to implement the entire B2B flow for the customers.
You can read more about how Medusa supports B2B and compares to other OS B2B platforms on our webpage.
You can also check out the following resources in our documentation to learn more about the different components used in this tutorial:
- Sales Channels and how to use them.
- Customer Groups and how to use them.
- Price Lists and how to use them.
Should you have any issues or questions related to Medusa, then feel free to reach out to the Medusa team via Discord.
Top comments (1)
Brilliant!
Hopefully, this will open up the opportunity for many more businesses to build bespoke and composable commerce setups with our open commerce infrastructure.