Create Customizable Options for products programmatically in Magento 2

Magento 2 is a popular CMS used widely used in eCommerce stores selling varied products.
Serving the options to customize the product the way customers to attract customers is a key success for any business. and Magento 2 allows you to do the same by creating multiple custom options from the admin side. Generally, These custom options are displayed on the eCommerce store front-end and allow your customer to customize the product as per the need of a set of different Custom options.
There are many Best Magento 2 Extension for eCommerce Store to Customizable the Product as his requirements.
In Magento 2 is offering a different event to create Customizable Options to products on the ‘checkout_onepage_controller_success_action’ event.

You can manually create custom options for the product by navigating the backend product edit page by using the Coding Technique.

Let’s dive deep into step by step process.

Creating a new module skeleton :

you need to create a new module for implementing (basically two files registration.php and module.xml files)

Vendor: Excellence
Module: GiftCard

registration.php (magento_root/vendor/module/registration.php)

<?php
    \Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Excellence_GiftCard',
    __DIR__
);

module.xml (magento_root/vendor/module/etc/module.xml)

<?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="Excellence_GiftCard" setup_version="1.0.0"/>
</config>

events.xml (magento_root/vendor/module/etc/events.xml)

Now here i am defining my observer to trigger on save after event of product.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="catalog_product_save_after">
        <observer name="add_giftcard_custom_options" instance="Excellence\GiftCard\Observer\Adminhtml\GiftCardOptions" />
    </event>    
</config>

GiftCardOptions.php (magento_root/vendor/module/Observer/Adminhtml/GiftCardOptions.php)

Now I am observer file mentioned into the event file at a specified location to create pre-determined customizable options to create along with products.

<?php
namespace Excellence\GiftCard\Observer\Adminhtml;
use Magento\Framework\Event\ObserverInterface;
 
class GiftCardOptions implements ObserverInterface
{
    protected $_productOptions;
    protected $_productRepository;
    protected $_giftCardHelper;
 
    public function __construct(
        \Magento\Catalog\Model\Product\Option $productOptions,
        \Magento\Catalog\Model\Product $productRepository,
        \Excellence\GiftCard\Helper\Data $giftCardHelper
    ){
        $this->_productOptions = $productOptions;
        $this->_productRepository = $productRepository;
        $this->_giftCardHelper = $giftCardHelper;
    }
 
    public function execute(\Magento\Framework\Event\Observer $observer){
        $product = $observer->getProduct();
            $optionsStatus = $this->isOptionsExists($product);
            if(!$optionsStatus){
                $productId = $observer->getProduct()->getId();
                $productFromRepo = $this->_productRepository->load($productId);
                $values = [
                            [
                                'record_id'=>0,                                        
                                'title'=>'Gift Card',
                                'price'=>10,
                                'price_type'=>"fixed",
                                'sort_order'=>1,
                                'is_delete'=>0
                            ],
                            [
                                'record_id'=>1,                    
                                'title'=>'Gift Card',
                                'price'=>20,
                                'price_type'=>"fixed",
                                'sort_order'=>1,
                                'is_delete'=>0
                            ],
                            [
                                'record_id'=>2,                    
                                'title'=>'Gift Card',
                                'price'=>30,
                                'price_type'=>"fixed",
                                'sort_order'=>1,
                                'is_delete'=>0
                            ]
                ];

                $options = [
                            [
                                "sort_order"    => 0,
                                "title"         => "Gift Card Value",
                                "price_type"    => "fixed",
                                "type"          => "drop_down",
                                "is_require"    => 1,
                                "values"        => $values
                            ],[
                                "sort_order"    => 1,
                                "title"         => "Sender Name",
                                "price_type"    => "fixed",
                                "price"         => "",
                                "type"          => "field",
                                "is_require"    => 1
                            ],[
                                "sort_order"    => 2,
                                "title"         => "Sender Email",
                                "price_type"    => "fixed",
                                "price"         => "",
                                "type"          => "field",
                                "is_require"    => 1
                            ],[
                                "sort_order"    => 3,
                                "title"         => "Receiver Name",
                                "price_type"    => "fixed",
                                "price"         => "",
                                "type"          => "field",
                                "is_require"    => 1
                            ],[
                                "sort_order"    => 4,
                                "title"         => "Receiver Email",
                                "price_type"    => "fixed",
                                "price"         => "",
                                "type"          => "field",
                                "is_require"    => 1
                            ],[
                                "sort_order"    => 5,
                                "title"         => "Message",
                                "price_type"    => "fixed",
                                "price"         => "",
                                "type"          => "area",
                                "is_require"    => 0
                            ],[
                                "sort_order"    => 6,
                                "title"         => "Scheduled Date",
                                "price_type"    => "fixed",
                                "price"         => "",
                                "type"          => "date",
                                "is_require"    => 1
                            ]
                ];

                $productFromRepo->setHasOptions(1);
                $productFromRepo->setCanSaveCustomOptions(true);
                foreach ($options as $arrayOption) {
                    $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); //instance of Object manager
                    $option = $objectManager->create('\Magento\Catalog\Model\Product\Option')
                    ->setProductId($productId)
                    ->setStoreId($product->getStoreId())
                    ->addData($arrayOption);
                    $option->save();
                    $productFromRepo->addOption($option);
                }
                $productFromRepo->save();
        }        
    }
    
    public function isOptionsExists($product){
        foreach ($product->getOptions() as $value) {
            return true;
    }
        return false;
    }
}

The above file creates product customizable options along with product which can be visible under product customizable options tab.

Product Customizable Options View

You can also browse this product on store front to verify the same

Store Front View