A comprehensive guide to understanding and working with all Magento 2 product types.
- Introduction
- Product Types Overview
- Simple Product
- Configurable Product
- Grouped Product
- Bundle Product
- Virtual Product
- Downloadable Product
- Custom Product Types
- Comparison & Best Practices
Product types in Magento 2 define how products behave, what attributes they support, how they're displayed, priced, and purchased. Understanding product types is crucial for:
- Properly modeling your product catalog
- Optimizing performance
- Implementing custom functionality
- Managing inventory effectively
- Providing the best customer experience
Product types are classes that extend Magento\Catalog\Model\Product\Type\AbstractType and define specific behaviors for different kinds of products. Each type handles:
- Cart operations - How products are added to cart
- Pricing logic - How prices are calculated
- Inventory management - How stock is tracked
- Display behavior - How products appear on frontend
- Admin configuration - What options are available in admin
Magento 2 provides six core product types out of the box:
| Type | Code | Description |
|---|---|---|
| Simple | simple |
Basic single product with no variations |
| Configurable | configurable |
Parent product with variations (size, color, etc.) |
| Grouped | grouped |
Collection of simple products sold together |
| Bundle | bundle |
Product with customizable options |
| Virtual | virtual |
Non-physical product (services, warranties) |
| Downloadable | downloadable |
Digital product with downloadable files |
Magento\Catalog\Model\Product\Type\AbstractType
├── Simple
├── Virtual (extends Simple)
├── Downloadable (extends Virtual)
├── Configurable
├── Grouped
└── Bundle
The most basic product type - represents a single item with a fixed price and no variations.
- ✅ Single SKU
- ✅ Fixed price
- ✅ Direct inventory management
- ✅ No variations or options (but can have custom options)
- ✅ Can have weight and dimensions
Use simple products for:
- Basic physical products without variations
- Products sold as a single unit
- When you don't need size/color variations
- Individual items that can be sold separately
- Book (specific edition)
- Coffee mug (single design)
- Laptop charger (specific model)
- Phone case (specific phone model and color)
- Water bottle
- Go to Catalog → Products
- Click Add Product button
- Select Simple Product from dropdown
- Fill in required fields:
- Product Name
- SKU
- Price
- Quantity
- Weight
- Configure additional settings as needed
- Click Save
<?php
namespace Vendor\Module\Model;
use Magento\Catalog\Api\Data\ProductInterfaceFactory;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Model\Product\Type;
use Magento\Catalog\Model\Product\Visibility;
class SimpleProductCreator
{
private $productFactory;
private $productRepository;
public function __construct(
ProductInterfaceFactory $productFactory,
ProductRepositoryInterface $productRepository
) {
$this->productFactory = $productFactory;
$this->productRepository = $productRepository;
}
public function create()
{
$product = $this->productFactory->create();
$product->setTypeId(Type::TYPE_SIMPLE)
->setAttributeSetId(4) // Default attribute set
->setName('Sample T-Shirt')
->setSku('sample-tshirt-001')
->setUrlKey('sample-tshirt')
->setDescription('High quality cotton t-shirt')
->setShortDescription('Cotton t-shirt')
->setStatus(Status::STATUS_ENABLED)
->setVisibility(Visibility::VISIBILITY_BOTH)
->setPrice(29.99)
->setWeight(0.5)
->setStockData([
'use_config_manage_stock' => 1,
'manage_stock' => 1,
'is_in_stock' => 1,
'qty' => 100
]);
return $this->productRepository->save($product);
}
}Type Class: Magento\Catalog\Model\Product\Type\Simple
Key Methods:
isSalable()- Checks if product can be purchasedprepareForCartAdvanced()- Prepares product for carthasWeight()- Returns true (simple products have weight)isVirtual()- Returns false (simple products are physical)
A parent product that groups simple products (variants) based on configurable attributes like size, color, or material.
- ✅ Parent-child relationship
- ✅ Configurable attributes (size, color, material, etc.)
- ✅ Child products must be simple products
- ✅ Dynamic pricing based on selected variant
- ✅ Shared attributes from parent
- ✅ Individual inventory per variant
Use configurable products for:
- Products available in multiple sizes
- Products available in different colors
- Products with different specifications (RAM, storage, etc.)
- When variants share most attributes but differ in a few
- T-shirt available in S, M, L, XL and multiple colors
- Shoes in different sizes and materials
- Laptop with different RAM/storage configurations
- Phone in different colors and storage capacities
Configurable Product (Parent)
├── Simple Product (Red, Size S)
├── Simple Product (Red, Size M)
├── Simple Product (Blue, Size S)
└── Simple Product (Blue, Size M)
Step 1: Create Configurable Attributes
First, create attributes that will be used for variations (e.g., color, size):
# Attributes must be:
# - Scope: Global
# - Catalog Input Type for Store Owner: Dropdown
# - Use To Create Configurable Product: YesStep 2: Create Simple Product Variants
Create simple products for each variation:
- SKU:
tshirt-red-s,tshirt-red-m,tshirt-blue-s, etc. - Set the attribute values (color=Red, size=S)
- Set visibility to "Not Visible Individually"
Step 3: Create Configurable Product
- Create a new product with type "Configurable Product"
- Click "Create Configurations"
- Select attributes (e.g., color and size)
- Select attribute values
- Configure images and pricing per variant
- Generate products
<?php
namespace Vendor\Module\Model;
use Magento\ConfigurableProduct\Helper\Product\Options\Factory;
class ConfigurableProductCreator
{
private $productFactory;
private $productRepository;
private $optionsFactory;
public function create()
{
// 1. Create parent configurable product
$configurableProduct = $this->productFactory->create();
$configurableProduct
->setTypeId('configurable')
->setAttributeSetId(4)
->setName('Configurable T-Shirt')
->setSku('configurable-tshirt')
->setStatus(Status::STATUS_ENABLED)
->setVisibility(Visibility::VISIBILITY_BOTH)
->setPrice(29.99);
$configurableProduct = $this->productRepository->save($configurableProduct);
// 2. Create simple product variants (see Simple Product section)
$variants = $this->createVariants();
// 3. Link variants to configurable product
$configurableProduct->getExtensionAttributes()
->setConfigurableProductLinks(array_map(function($v) {
return $v->getId();
}, $variants));
// 4. Set configurable attributes
$configurableOptions = $this->optionsFactory->create([
['attribute_id' => $this->getAttributeId('size')],
['attribute_id' => $this->getAttributeId('color')]
]);
$configurableProduct->getExtensionAttributes()
->setConfigurableProductOptions($configurableOptions);
return $this->productRepository->save($configurableProduct);
}
}Type Class: Magento\ConfigurableProduct\Model\Product\Type\Configurable
Key Methods:
getUsedProducts()- Returns child simple productsgetConfigurableAttributes()- Returns configurable attributesgetUsedProductCollection()- Returns collection of variants
Important Notes:
- Configurable product itself has no inventory
- Stock is managed at the child (simple) product level
- Price can come from parent or child products
- Only simple products can be children
A collection of simple products displayed together, allowing customers to purchase multiple items in one transaction.
- ✅ Groups multiple simple products
- ✅ Individual quantities for each item
- ✅ Separate pricing for each product
- ✅ Optional purchases - customers can buy any combination
- ✅ Shared product page
- ✅ No inventory on parent
Use grouped products for:
- Related product collections
- Product kits where items can be purchased separately
- Cross-selling scenarios
- Furniture sets (table + chairs)
- Dining room set (table + 4 chairs + buffet)
- Computer bundle (monitor + keyboard + mouse)
- Skincare routine (cleanser + toner + moisturizer)
- Tool set (drill + bits + case)
Grouped Product (Parent - No inventory)
├── Simple Product A (Individual price & inventory)
├── Simple Product B (Individual price & inventory)
└── Simple Product C (Individual price & inventory)
- Create simple products first (associated products)
- Create new product with type "Grouped Product"
- Go to "Grouped Products" tab
- Click "Add Products to Group"
- Select associated products
- Set default quantity for each
- Save product
<?php
namespace Vendor\Module\Model;
class GroupedProductCreator
{
private $productFactory;
private $productRepository;
private $linkManagement;
public function create()
{
// 1. Create grouped product
$groupedProduct = $this->productFactory->create();
$groupedProduct
->setTypeId('grouped')
->setAttributeSetId(4)
->setName('Dining Room Set')
->setSku('dining-room-set')
->setStatus(Status::STATUS_ENABLED)
->setVisibility(Visibility::VISIBILITY_BOTH);
$groupedProduct = $this->productRepository->save($groupedProduct);
// 2. Create associated products
$associatedProducts = [
$this->createSimpleProduct('Dining Table', 'dining-table', 599.99),
$this->createSimpleProduct('Dining Chair', 'dining-chair', 149.99),
$this->createSimpleProduct('Buffet Cabinet', 'buffet-cabinet', 399.99)
];
// 3. Link products
foreach ($associatedProducts as $index => $product) {
$link = [
'sku' => $groupedProduct->getSku(),
'link_type' => 'associated',
'linked_product_sku' => $product->getSku(),
'linked_product_type' => 'simple',
'position' => $index,
'qty' => 1
];
$this->linkManagement->setProductLinks($groupedProduct->getSku(), [$link]);
}
return $groupedProduct;
}
}Type Class: Magento\GroupedProduct\Model\Product\Type\Grouped
Key Methods:
getAssociatedProducts()- Returns associated simple productsprepareForCartAdvanced()- Adds all selected products to cart
Important Notes:
- Each associated product is added to cart separately
- Price is the sum of selected products
- Inventory is managed at the associated product level
- Only simple and virtual products can be associated
A composite product where customers can choose from multiple options for each bundle component, creating their own product combination.
- ✅ Multiple bundle options (components)
- ✅ Selectable items for each option
- ✅ Dynamic pricing based on selections
- ✅ Required or optional components
- ✅ Quantity selection per item
- ✅ Fixed or dynamic pricing
Use bundle products for:
- Build-your-own product scenarios
- Complex product configurations
- Custom packages
- Products with multiple customizable components
- Computer builder (choose CPU, RAM, storage, graphics card)
- Gift basket (choose items from different categories)
- Phone plan (choose device + plan + accessories)
- Custom pizza (choose size, crust, toppings)
Bundle Product
├── Option 1: Processor (Required)
│ ├── Intel i5 ($299)
│ ├── Intel i7 ($399)
│ └── AMD Ryzen ($349)
├── Option 2: RAM (Required)
│ ├── 8GB ($50)
│ ├── 16GB ($100)
│ └── 32GB ($200)
└── Option 3: Graphics (Optional)
├── Basic ($100)
└── Gaming ($300)
- Dropdown - Select one option
- Radio Buttons - Select one option (visual alternative)
- Checkbox - Select multiple options
- Multiple Select - Select multiple options from dropdown
- Create simple products for all bundle options first
- Create new product with type "Bundle Product"
- Set Price Type: Fixed or Dynamic
- Set SKU Type: Fixed or Dynamic
- Set Weight Type: Fixed or Dynamic
- Go to "Bundle Items" tab
- Click "Add Option"
- Configure each option:
- Option Title
- Input Type (dropdown, radio, checkbox, etc.)
- Required (Yes/No)
- Add products to each option
- Set pricing for each selection
- Save product
<?php
namespace Vendor\Module\Model;
class BundleProductCreator
{
private $productFactory;
private $productRepository;
private $bundleOptionFactory;
public function create()
{
// 1. Create bundle product
$bundleProduct = $this->productFactory->create();
$bundleProduct
->setTypeId('bundle')
->setAttributeSetId(4)
->setName('Custom Computer Bundle')
->setSku('custom-computer-bundle')
->setStatus(Status::STATUS_ENABLED)
->setVisibility(Visibility::VISIBILITY_BOTH)
->setPriceType(1) // 0 = Fixed, 1 = Dynamic
->setPrice(0) // Price determined by selections
->setShipmentType(0); // 0 = Together, 1 = Separately
$bundleProduct = $this->productRepository->save($bundleProduct);
// 2. Create bundle options
$this->createBundleOptions($bundleProduct);
return $bundleProduct;
}
private function createBundleOptions($bundleProduct)
{
$optionsData = [
[
'title' => 'Processor',
'type' => 'select', // dropdown
'required' => 1,
'selections' => [
['sku' => 'intel-i5-cpu', 'qty' => 1, 'price' => 299],
['sku' => 'intel-i7-cpu', 'qty' => 1, 'price' => 399],
['sku' => 'amd-ryzen-cpu', 'qty' => 1, 'price' => 349]
]
],
[
'title' => 'Memory',
'type' => 'radio',
'required' => 1,
'selections' => [
['sku' => 'ram-8gb', 'qty' => 1, 'price' => 50],
['sku' => 'ram-16gb', 'qty' => 1, 'price' => 100],
['sku' => 'ram-32gb', 'qty' => 1, 'price' => 200]
]
]
];
// Create options and selections (implementation details omitted)
}
}Fixed Pricing:
- Bundle has a fixed price
- Selection prices are discounts/additions to the fixed price
Dynamic Pricing:
- Bundle price is calculated based on selected items
- Final price = sum of all selected items
Type Class: Magento\Bundle\Model\Product\Type
Key Methods:
getOptions()- Returns bundle optionsgetSelectionsCollection()- Returns available selectionsprepareForCartAdvanced()- Processes bundle selections
A non-physical product that doesn't require shipping - typically services, digital goods, or warranties.
- ✅ No physical presence
- ✅ No weight or dimensions
- ✅ No shipping required
- ✅ Inherits from Simple product
- ✅ Can have custom options
Use virtual products for:
- Services and consultations
- Extended warranties
- Software licenses (without download)
- Subscriptions
- Online courses (without downloadable materials)
- Extended warranty (2-year protection plan)
- Consulting services (1-hour session)
- Software as a Service (SaaS) subscription
- Online course access
- Gift cards
- Create new product with type "Virtual Product"
- Fill in required fields (same as Simple Product)
- Note: No weight field (automatically set to 0)
- Note: Virtual products skip shipping calculation
- Save product
<?php
namespace Vendor\Module\Model;
class VirtualProductCreator
{
private $productFactory;
private $productRepository;
public function create()
{
$virtualProduct = $this->productFactory->create();
$virtualProduct
->setTypeId('virtual')
->setAttributeSetId(4)
->setName('Extended Warranty - 2 Years')
->setSku('warranty-2year')
->setDescription('2-year extended warranty coverage')
->setStatus(Status::STATUS_ENABLED)
->setVisibility(Visibility::VISIBILITY_BOTH)
->setPrice(99.99)
->setWeight(0) // Virtual products have no weight
->setStockData([
'use_config_manage_stock' => 0,
'manage_stock' => 0,
'is_in_stock' => 1
]);
return $this->productRepository->save($virtualProduct);
}
}Type Class: Magento\Catalog\Model\Product\Type\Virtual
Key Methods:
isVirtual()- Always returns truehasWeight()- Always returns false
Important Notes:
- Extends Simple product type
- Shipping is automatically skipped
- Often used with "Manage Stock = No"
- Can be used as children of Configurable products
A digital product that customers can download after purchase - extends Virtual product with download functionality.
- ✅ Extends Virtual product
- ✅ Downloadable files/links
- ✅ Download limits (times/days)
- ✅ Link expiration
- ✅ Sample downloads
- ✅ No shipping required
Use downloadable products for:
- E-books and documents
- Software downloads
- Music and video files
- Digital templates
- Downloadable courses
- E-book (PDF download)
- Software application (installer)
- Music album (MP3 files)
- Video course (MP4 files)
- Design templates (PSD, AI files)
Links - The actual downloadable files customers receive after purchase
- Can be URL or file upload
- Can have individual pricing
- Can limit number of downloads
- Can set expiration
Samples - Preview/demo files available before purchase
- Free to download
- Help customers make purchase decision
- Can be URL or file upload
- Create new product with type "Downloadable Product"
- Fill in basic information
- Go to "Downloadable Information" section
- Configure Links:
- Add Title
- Set Price (if additional to base price)
- Choose Link Type (URL or File)
- Set Number of Downloads (0 = unlimited)
- Check "Shareable" if link can be shared
- Configure Samples (optional):
- Add Title
- Choose Sample Type (URL or File)
- Save product
<?php
namespace Vendor\Module\Model;
class DownloadableProductCreator
{
private $productFactory;
private $productRepository;
private $linkFactory;
private $sampleFactory;
public function create()
{
// 1. Create downloadable product
$product = $this->productFactory->create();
$product
->setTypeId('downloadable')
->setAttributeSetId(4)
->setName('Programming E-Book')
->setSku('ebook-programming')
->setStatus(Status::STATUS_ENABLED)
->setVisibility(Visibility::VISIBILITY_BOTH)
->setPrice(29.99)
->setStockData([
'use_config_manage_stock' => 0,
'manage_stock' => 0,
'is_in_stock' => 1
]);
$product = $this->productRepository->save($product);
// 2. Add downloadable link
$link = $this->linkFactory->create();
$link->setData([
'product_id' => $product->getId(),
'title' => 'Programming E-Book (PDF)',
'price' => 0, // Included in product price
'number_of_downloads' => 5, // 5 downloads allowed
'is_shareable' => 0,
'link_url' => 'https://example.com/downloads/programming-ebook.pdf',
'link_type' => 'url',
'sort_order' => 1
]);
$link->save();
// 3. Add sample
$sample = $this->sampleFactory->create();
$sample->setData([
'product_id' => $product->getId(),
'title' => 'Free Preview',
'sample_url' => 'https://example.com/samples/preview.pdf',
'sample_type' => 'url',
'sort_order' => 1
]);
$sample->save();
return $product;
}
}After purchase, Magento creates downloadable link records for the customer:
// Customer's downloadable links are stored in:
// downloadable_link_purchased
// downloadable_link_purchased_item
// Download tracking:
// - Number of downloads used
// - Number of downloads bought
// - Link status (available, expired, pending)Type Class: Magento\Downloadable\Model\Product\Type
Key Methods:
getLinks()- Returns downloadable linksgetSamples()- Returns sample downloadshasLinks()- Checks if product has links
Important Notes:
- Extends Virtual product type
- Links become available after order is invoiced
- Download limits are enforced
- Customers can access downloads from "My Downloads" page
Magento 2 allows you to create custom product types for specialized business needs.
Create a custom product type when:
- Core product types don't meet your requirements
- You need specialized cart behavior
- You need custom pricing logic
- You need unique inventory management
- You have complex business rules
<?php
namespace Vendor\Module\Model\Product\Type;
class Custom extends \Magento\Catalog\Model\Product\Type\AbstractType
{
const TYPE_CODE = 'custom';
public function isSalable($product)
{
// Custom salability logic
return parent::isSalable($product);
}
public function prepareForCartAdvanced(\Magento\Framework\DataObject $buyRequest, $product, $processMode = null)
{
// Custom cart preparation logic
$product->setCartQty($buyRequest->getQty());
return [$product];
}
public function hasWeight()
{
return true; // or false for virtual custom types
}
}<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<type name="custom"
label="Custom Product"
modelInstance="Vendor\Module\Model\Product\Type\Custom"
indexPriority="50"
sortOrder="50"
isQty="true">
<priceModel instance="Vendor\Module\Model\Product\Type\Custom\Price" />
</type>
</config><?php
namespace Vendor\Module\Model\Product\Type\Custom;
class Price extends \Magento\Catalog\Model\Product\Type\Price
{
public function getPrice($product)
{
// Custom pricing logic
return parent::getPrice($product);
}
}Create forms, blocks, and templates for admin product creation/editing.
- Extend existing types when possible (Simple, Virtual, etc.)
- Follow Magento coding standards
- Implement all required abstract methods
- Add comprehensive tests
- Document custom behavior
- Consider upgrade compatibility
| Feature | Simple | Configurable | Grouped | Bundle | Virtual | Downloadable |
|---|---|---|---|---|---|---|
| Variations | No | Yes | No | Yes | No | No |
| Inventory | Direct | Children | Associated | Selections | None/Optional | None |
| Pricing | Fixed | Dynamic | Sum | Fixed/Dynamic | Fixed | Fixed + Links |
| Shipping | Yes | Yes | Yes | Yes | No | No |
| Complexity | Low | Medium | Medium | High | Low | Medium |
| Performance | Fast | Medium | Medium | Slow | Fast | Medium |
| Use Case | Single items | Variations | Collections | Build-your-own | Services | Digital files |
Choose Simple when:
- Basic product without variations
- Single SKU and price
- Straightforward inventory management
Choose Configurable when:
- Product has variations (size, color)
- Variations share most attributes
- Need variation-specific inventory
- Professional product presentation
Choose Grouped when:
- Selling related products together
- Customers can buy items separately
- Cross-selling scenarios
- Flexible quantity selection
Choose Bundle when:
- Build-your-own scenarios
- Complex configurations
- Dynamic pricing needed
- Multiple customization options
Choose Virtual when:
- Non-physical products
- Services and warranties
- Subscriptions
- No shipping needed
Choose Downloadable when:
- Digital file downloads
- E-books, software, media
- Need download tracking
- Limited downloads
Simple & Virtual: ⚡ Fastest
- Minimal database queries
- Single product load
- Best cache efficiency
Configurable & Grouped: ⚡ Medium
- Load child/associated products
- Moderate database queries
- Good cache efficiency with optimization
Bundle: ⚡ Slower
- Complex option/selection loading
- Many database queries
- Requires careful optimization
General Guidelines:
- Choose the simplest product type that meets requirements
- Use appropriate caching strategies
- Optimize database queries
- Implement lazy loading for related products
- Monitor performance metrics
Code Quality:
- Follow Magento 2 coding standards
- Use dependency injection
- Implement proper error handling
- Write comprehensive tests
- Document custom modifications
Maintenance:
- Keep type definitions updated
- Monitor performance
- Plan for Magento upgrades
- Document customizations
- Review and optimize regularly
❌ Don't:
- Use configurable products when simple would work
- Create bundle products with too many options
- Mix physical and virtual products in grouped/bundle
- Forget to set proper visibility on child products
- Skip caching for complex product types
- Ignore performance impact of product type choice
✅ Do:
- Choose the right product type for the use case
- Optimize complex product type queries
- Use proper attribute scope settings
- Test with realistic data volumes
- Monitor and optimize performance
- Document product type decisions
- Product Attributes and Attribute Sets
- Inventory Management (MSI)
- Pricing and Tax Rules
- Catalog Search and Indexing
For more detailed technical implementation, see Types.md which includes:
- Detailed code examples for each product type
- Product type architecture deep-dive
- API integration examples
- GraphQL schema definitions
- Performance optimization strategies
- Complete implementation guides
Understanding Magento 2 product types is essential for:
- Building an effective product catalog
- Optimizing store performance
- Providing the best customer experience
- Implementing custom functionality
Key Takeaways:
- Each product type serves specific business needs
- Simple products are the foundation - other types build upon them
- Performance impact varies significantly by type
- Choose the simplest type that meets requirements
- Custom types are possible but should be carefully planned
By mastering product types, you can create a flexible, performant catalog that serves your business needs effectively.