How to Create a Custom "Back in Stock" Notification System in Magento 2

Why You Need a Custom "Back in Stock" Notification System in Magento 2
Running an eCommerce store means dealing with out-of-stock products—it’s inevitable. But what happens when customers miss out on their favorite items? A well-implemented "Back in Stock" notification system keeps shoppers engaged and boosts conversions by alerting them when products are available again.
While Magento 2 has basic stock alerts, a custom solution gives you more control—better branding, automated workflows, and deeper analytics. Let’s build one from scratch!
Step 1: Setting Up the Database Table
First, we need a table to store customer notifications. Create a custom module (let’s call it Magefine_StockAlert
) and define the table in Setup/InstallSchema.php
:
<?php
namespace Magefine\StockAlert\Setup;
use Magento\Framework\DB\Ddl\Table;
use Magento\Framework\Setup\InstallSchemaInterface;
use Magento\Framework\Setup\ModuleContextInterface;
use Magento\Framework\Setup\SchemaSetupInterface;
class InstallSchema implements InstallSchemaInterface
{
public function install(SchemaSetupInterface $setup, ModuleContextInterface $context)
{
$installer = $setup;
$installer->startSetup();
$table = $installer->getConnection()->newTable(
$installer->getTable('magefine_stock_alert')
)->addColumn(
'alert_id',
Table::TYPE_INTEGER,
null,
['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
'Alert ID'
)->addColumn(
'product_id',
Table::TYPE_INTEGER,
null,
['unsigned' => true, 'nullable' => false],
'Product ID'
)->addColumn(
'customer_email',
Table::TYPE_TEXT,
255,
['nullable' => false],
'Customer Email'
)->addColumn(
'status',
Table::TYPE_SMALLINT,
null,
['nullable' => false, 'default' => 0],
'Alert Status (0=Pending, 1=Sent)'
)->addColumn(
'created_at',
Table::TYPE_TIMESTAMP,
null,
['nullable' => false, 'default' => Table::TIMESTAMP_INIT],
'Creation Time'
)->addIndex(
$installer->getIdxName('magefine_stock_alert', ['product_id']),
['product_id']
)->setComment('Stock Alert Subscriptions');
$installer->getConnection()->createTable($table);
$installer->endSetup();
}
}
Step 2: Creating the Frontend Form
Add a "Notify Me" button on product pages when an item is out of stock. In your theme’s catalog_product_view.xml
:
<referenceContainer name="product.info.form.content">
<block class="Magefine\StockAlert\Block\Product\View\StockAlert" name="product.stock.alert" template="Magefine_StockAlert::product/view/stock_alert.phtml" after="product.info.addtocart"/>
</referenceContainer>
Then, create the template (stock_alert.phtml
):
<?php if (!$block->isProductInStock() && !$block->isCustomerSubscribed()): ?>
<div class="stock-alert">
<form method="post" action="<?= $block->getSubmitUrl() ?>" id="stock-alert-form">
<div class="field email required">
<label for="email"><?= __('Notify me when available') ?></label>
<input type="email" name="email" id="stock-alert-email" class="input-text" placeholder="your@email.com" />
</div>
<button type="submit" class="action primary"><?= __('Subscribe') ?></button>
</form>
</div>
<?php endif; ?>
Step 3: Handling Form Submissions
Create a controller (Controller/Product/Subscribe.php
) to save subscriptions:
<?php
namespace Magefine\StockAlert\Controller\Product;
use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Message\ManagerInterface;
use Magefine\StockAlert\Model\StockAlertFactory;
class Subscribe implements HttpPostActionInterface
{
protected $resultFactory;
protected $messageManager;
protected $stockAlertFactory;
public function __construct(
ResultFactory $resultFactory,
ManagerInterface $messageManager,
StockAlertFactory $stockAlertFactory
) {
$this->resultFactory = $resultFactory;
$this->messageManager = $messageManager;
$this->stockAlertFactory = $stockAlertFactory;
}
public function execute()
{
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
$productId = $this->getRequest()->getParam('product_id');
$email = $this->getRequest()->getParam('email');
try {
$stockAlert = $this->stockAlertFactory->create();
$stockAlert->setProductId($productId)
->setCustomerEmail($email)
->setStatus(0)
->save();
$this->messageManager->addSuccessMessage(__('You will be notified when this product is back in stock!'));
} catch (\Exception $e) {
$this->messageManager->addErrorMessage(__('There was an error with your subscription.'));
}
$resultRedirect->setUrl($this->_redirect->getRefererUrl());
return $resultRedirect;
}
}
Step 4: Sending Notifications Automatically
Create an observer (Observer/ProductSaveAfter.php
) to trigger emails when stock updates:
<?php
namespace Magefine\StockAlert\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magefine\StockAlert\Model\ResourceModel\StockAlert\CollectionFactory;
use Magento\CatalogInventory\Api\StockStateInterface;
use Magento\Framework\Mail\Template\TransportBuilder;
class ProductSaveAfter implements ObserverInterface
{
protected $stockAlertCollection;
protected $stockState;
protected $transportBuilder;
public function __construct(
CollectionFactory $stockAlertCollection,
StockStateInterface $stockState,
TransportBuilder $transportBuilder
) {
$this->stockAlertCollection = $stockAlertCollection;
$this->stockState = $stockState;
$this->transportBuilder = $transportBuilder;
}
public function execute(Observer $observer)
{
$product = $observer->getEvent()->getProduct();
$stockQty = $this->stockState->getStockQty($product->getId());
if ($stockQty > 0) {
$alerts = $this->stockAlertCollection->create()
->addFieldToFilter('product_id', $product->getId())
->addFieldToFilter('status', 0);
foreach ($alerts as $alert) {
$this->sendNotification($alert, $product);
$alert->setStatus(1)->save();
}
}
}
protected function sendNotification($alert, $product)
{
$transport = $this->transportBuilder
->setTemplateIdentifier('stock_alert_notification')
->setTemplateOptions(['area' => 'frontend', 'store' => $product->getStoreId()])
->setTemplateVars([
'product' => $product,
'product_url' => $product->getProductUrl()
])
->setFromByScope('general')
->addTo($alert->getCustomerEmail())
->getTransport();
$transport->sendMessage();
}
}
Step 5: Creating the Email Template
Add a transactional email template in view/frontend/email/stock_alert.html
:
<!--@subject Your product is back in stock! @-->
<!--@vars {
"var product.name":"Product Name",
"var product_url|raw":"Product URL"
} @-->
<p>Hello,</p>
<p>The product you were waiting for is now available!</p>
<p><strong>{{var product.name}}</strong></p>
<p><a href="{{var product_url}}">Click here to purchase now!</a></p>
<p>Thanks for shopping with us!</p>
Final Thoughts
With this custom system, you’ll:
- ✅ Reduce cart abandonment by keeping customers informed
- ✅ Increase conversions when products restock
- ✅ Gain full control over notification design and timing
Want to skip the coding? Check out Magefine’s premium extensions for ready-made solutions with advanced features like SMS alerts and analytics!