There are scenarios where you might want to include unique options for certain products in the cart, such as attaching a warranty, adding a gift item, or offering text or dropdown customizations.
Programmatically adding products with custom options is a robust feature that allows you to customize the shopping experience to meet specific customer needs.
Earlier we showed you How to create a custom price for a specific product and customer in Magento 2?
But what if you want to know how to add product to cart programmatically with custom options in Magento 2?
So, here’s the step-by-step guide and learn how to enhance your cart functionality with custom options!
Before We Begin…
Know that this solution can be beneficial for implementing an automatic “Add to cart” functionality for configurable products with custom options. For instance, the store might include a free product with a specific item, attach a warranty, or add a gift product, or add a custom option like text or with a dropdown option.
ON THIS PAGE
How To Create A Module To Add Custom Options With Products Into The Cart?
Let’s create a module to add some custom options with products into the cart.
Step 1: Create the Module Registration File
You need to register your custom module using registration.php.Path: app/code/Klizer/AdditionalOption/registration.php
<?php
/**
* Klizer
*
* @category Klizer
* @package Klizer_AdditionalOption
* @copyright Copyright © 2025 Klizer. All rights reserved.
* @author Klizer - info@klizer.com
*/
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Klizer_AdditionalOption',
__DIR__
);
Step 2: Define the Module in module.xml
Now define the module using the below path.
Path: app/code/Klizer/AdditionalOption/etc/module.xml
<?xml version="1.0"?>
<!--
/**
* Klizer
*
* @category Klizer
* @package Klizer_AdditionalOption
* @copyright Copyright © 2025 Klizer. All rights reserved.
* @author Klizer - info@klizer.com
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Klizer_AdditionalOption" setup_version="1.0.0">
</module>
</config>
Step 3: Create layout file : catalog_product_view.xml
Path : app/code/Klizer/AdditionalOption/view/frontend/layout/catalog_product_view.xml
<?xml version="1.0"?>
<!--
/**
* Klizer
*
* @category Klizer
* @package Klizer_AdditionalOption
* @copyright Copyright © 2025 Klizer. All rights reserved.
* @author Klizer - info@klizer.com
*/
-->
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="product.info.addtocart">
<action method="setTemplate">
<argument name="template" xsi:type="string">Klizer_AdditionalOption::product/view/addtocart.phtml</argument>
</action>
</referenceBlock>
<referenceBlock name="product.info.addtocart.additional">
<action method="setTemplate">
<argument name="template" xsi:type="string">Klizer_AdditionalOption::product/view/addtocart.phtml</argument>
</action>
</referenceBlock>
</body>
</page>
Step 4: Create phtml file : addtocart.phtml
Path : app/code/Klizer/AdditionalOption/view/frontend/templates/product/view/addtocart.phtml
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
/** @var $block \Magento\Catalog\Block\Product\View */
?>
<?php $_product = $block->getProduct(); ?>
<?php $buttonTitle = __('Add to Cart'); ?>
<?php if ($_product->isSaleable()) :?>
<!-- Custom Input Field Start-->
<div>
<label for="notes">
<?= __('Notes:'); ?>
</label>
<input type="text" name="notes" id="notes" maxlength="255" placeholder="Notes"/>
</div>
<!-- Custom Input Field End-->
<div class="box-tocart">
<div class="fieldset">
<?php if ($block->shouldRenderQuantity()) :?>
<div class="field qty">
<label class="label" for="qty"><span><?= $block->escapeHtml(__('Qty')) ?></span></label>
<div class="control">
<input type="number"
name="qty"
id="qty"
min="0"
value="<?= $block->getProductDefaultQty() * 1 ?>"
title="<?= $block->escapeHtmlAttr(__('Qty')) ?>"
class="input-text qty"
data-validate="<?= $block->escapeHtml(json_encode($block->getQuantityValidators())) ?>"
/>
</div>
</div>
<?php endif; ?>
<div class="actions">
<button type="submit"
title="<?= $block->escapeHtmlAttr($buttonTitle) ?>"
class="action primary tocart"
id="product-addtocart-button" disabled>
<span><?= $block->escapeHtml($buttonTitle) ?></span>
</button>
<?= $block->getChildHtml('', true) ?>
</div>
</div>
</div>
<?php endif; ?>
<script type="text/x-magento-init">
{
"#product_addtocart_form": {
"Magento_Catalog/js/validate-product": {}
}
}
</script>
Step 5: Create Observer file : SetAdditionalOptions.php
Path : app/code/Klizer/AdditionalOption/Observer/SetAdditionalOptions.php
<?php
/**
* Klizer
*
* @category Klizer
* @package Klizer_AdditionalOption
* @copyright Copyright © 2025 Klizer. All rights reserved.
* @author Klizer - info@klizer.com
*/
namespace Klizer\AdditionalOption\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Serialize\Serializer\Json;
class SetAdditionalOptions implements ObserverInterface
{
/**
* @var SerializerInterface|null
*/
private $serializer;
/**
* @param RequestInterface $request
*/
protected $_request;
public function __construct(
RequestInterface $request,
Json $serializer = null
)
{
$this->_request = $request;
$this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
->get(\Magento\Framework\Serialize\Serializer\Json::class);
}
/**
* @param \Magento\Framework\Event\Observer $observer
*/
public function execute(\Magento\Framework\Event\Observer $observer)
{
$product = $observer->getProduct();
$post = $this->_request->getParam('notes');
/*Set Notes Value When Product Add To Cart Start*/
$fullActionName = $this->_request->getFullActionName();
if(($fullActionName == 'checkout_cart_add') && $post)
{
$product = $observer->getProduct();
$additionalOptions = [];
$additionalOptions[] = array(
'label' => "Notes",
'value' => $post,
'option_value' => ''
);
$product->addCustomOption('additional_options', $this->serializer->serialize($additionalOptions));
}
/*Set Notes Value When Product Add To Cart End*/
}
}
You can set the multiple options using the same approach.
Using this approach you can set additional options in cart item and you will be able to view this information on all pages.
Product Page:

Mini Cart:

Cart Page:

Checkout Page:

Add Products To Cart Programatically Using Custom Options With Klizer
That’s it! This is how you can add products to cart programmatically with custom options.
By now, you should have a solid understanding of the concept of Observers in Magento 2. We have developed a custom module that added an additional option to the cart.
If you have any questions about the process or want to contribute to the discussion, feel free to leave a comment below. Don’t forget to share this article with your Magento developers and if you still have any doubts, contact us for Magento 2 solutions.