How to Build a Custom Dynamic Pricing Engine in Magento 2

Why You Need a Custom Dynamic Pricing Engine in Magento 2
Dynamic pricing is a game-changer in eCommerce. Whether you're running flash sales, adjusting prices based on demand, or offering personalized discounts, a flexible pricing engine can boost conversions and maximize profits. While Magento 2 has built-in pricing rules, they often fall short for advanced use cases.
In this guide, we'll walk through building a custom dynamic pricing engine in Magento 2 that gives you full control over pricing logic. No more being limited by the default catalog price rules!
Understanding Magento 2's Pricing Architecture
Before we dive into coding, let's understand how Magento handles product pricing:
- Base Price: The standard price set in the product
- Tier Prices: Quantity-based discounts
- Catalog Price Rules: Store-wide discount rules
- Cart Price Rules: Discounts applied at checkout
Our custom engine will hook into this system to apply dynamic adjustments before prices are displayed or added to cart.
Step 1: Setting Up the Module Structure
First, create a new module in app/code/Magefine/DynamicPricing
:
DynamicPricing/
├── etc/
│ ├── module.xml
│ └── di.xml
├── Model/
│ └── PriceModifier.php
└── registration.php
Here's the basic module configuration:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magefine_DynamicPricing" setup_version="1.0.0">
<sequence>
<module name="Magento_Catalog"/>
<module name="Magento_Quote"/>
</sequence>
</module>
</config>
Step 2: Creating the Price Modifier Service
The core of our engine will be a service that intercepts price calculations. Here's a basic implementation:
<?php
namespace Magefine\DynamicPricing\Model;
use Magento\Catalog\Model\Product;
use Magento\Framework\Pricing\Adjustment\CalculatorInterface;
class PriceModifier
{
protected $calculator;
public function __construct(CalculatorInterface $calculator)
{
$this->calculator = $calculator;
}
public function modifyPrice(Product $product, $price)
{
// Apply your custom pricing logic here
$newPrice = $this->applyDynamicRules($product, $price);
return $newPrice;
}
protected function applyDynamicRules(Product $product, $price)
{
// Example: Time-based pricing
$hour = date('G');
if ($hour >= 9 && $hour <= 17) {
// 10% premium during business hours
return $price * 1.10;
}
return $price;
}
}
Step 3: Hooking Into Magento's Pricing System
We need to make Magento use our price modifier. Add this to your di.xml
:
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<type name="Magento\Catalog\Model\Product">
<plugin name="magefine_dynamic_pricing" type="Magefine\DynamicPricing\Plugin\ProductPricePlugin"/>
</type>
</config>
Then create the plugin:
<?php
namespace Magefine\DynamicPricing\Plugin;
use Magento\Catalog\Model\Product;
class ProductPricePlugin
{
protected $priceModifier;
public function __construct(\Magefine\DynamicPricing\Model\PriceModifier $priceModifier)
{
$this->priceModifier = $priceModifier;
}
public function afterGetPrice(Product $product, $result)
{
return $this->priceModifier->modifyPrice($product, $result);
}
}
Advanced Pricing Strategies
Now that we have the basic structure, let's implement some powerful pricing strategies:
1. Demand-Based Pricing
protected function applyDynamicRules(Product $product, $price)
{
// Get current inventory level
$stockItem = $product->getExtensionAttributes()->getStockItem();
$stockQty = $stockItem->getQty();
// Get sales in last 7 days
$salesCount = $this->getRecentSalesCount($product->getId());
// Adjust price based on demand
if ($salesCount > 50 && $stockQty < 20) {
return $price * 1.15; // Increase price when high demand + low stock
} elseif ($salesCount < 10 && $stockQty > 100) {
return $price * 0.90; // Discount when low demand + high stock
}
return $price;
}
2. Customer Segment Pricing
protected function applyDynamicRules(Product $product, $price)
{
$customerSession = $this->getCustomerSession();
if ($customerSession->isLoggedIn()) {
$customerGroupId = $customerSession->getCustomer()->getGroupId();
// Apply different pricing for wholesale customers
if ($customerGroupId == 2) { // Wholesale group ID
return $price * 0.80; // 20% discount for wholesale
}
// VIP customers get additional discount
if ($this->isVipCustomer($customerSession->getCustomerId())) {
return $price * 0.85; // 15% discount for VIPs
}
}
return $price;
}
3. Real-Time Competitor Price Matching
protected function applyDynamicRules(Product $product, $price)
{
$competitorPrice = $this->competitorPriceService->getPriceForProduct($product->getSku());
if ($competitorPrice && $competitorPrice < $price) {
// Match competitor price but never go below our minimum
$minPrice = $price * 0.85;
return max($competitorPrice, $minPrice);
}
return $price;
}
Optimizing Performance
Dynamic pricing can be resource-intensive. Here are some optimization tips:
- Cache Pricing Decisions: Store computed prices for a short period
- Batch Processing: For complex rules, pre-compute prices during off-peak hours
- Limit Real-Time Calculations: Only compute when absolutely necessary
Example caching implementation:
protected function modifyPrice(Product $product, $price)
{
$cacheKey = 'dynamic_price_' . $product->getId();
if ($cachedPrice = $this->cache->load($cacheKey)) {
return $cachedPrice;
}
$newPrice = $this->applyDynamicRules($product, $price);
$this->cache->save($newPrice, $cacheKey, [], 300); // Cache for 5 minutes
return $newPrice;
}
Testing Your Pricing Engine
Before going live, thoroughly test your pricing logic:
- Verify price calculations for different customer segments
- Test edge cases (out of stock items, guest users, etc.)
- Monitor performance impact
- Check integration with other pricing rules (tier prices, cart rules)
Going Further: Admin Interface
For a complete solution, consider adding:
- A grid to manage pricing rules
- Rule priority system
- Preview functionality to see price changes before saving
- Import/export capabilities
Conclusion
Building a custom dynamic pricing engine in Magento 2 gives you unparalleled flexibility to implement sophisticated pricing strategies. While the initial setup requires some development work, the business benefits can be substantial - from increased margins to better competitive positioning.
Remember to start simple, test thoroughly, and gradually add more complex rules as needed. And if you'd rather not build this from scratch, check out Magefine's Magento 2 extensions for ready-made solutions.
Have you implemented custom pricing in your Magento store? Share your experiences in the comments!