This article show you how to add Magento Custom Checkout Fields without using any third-party extension. And here’s how!
As you know, cart abandonment is a big problem for any business. And in eCommerce stores, the cart abandonment rate varies between 60% and 80%.
Luckily, there are a lot of practices to help you reduce the cart abandonment rate. And adding custom fields to the Magento checkout page is one of the best solutions. By collecting additional information, you can fulfill customers’ demands better. Therefore they would be more likely to complete their orders.
However, if you know little to nothing about coding or want to save your time, we strongly recommend using Magento 2 Checkout Custom Field by BSS. This extension provides you with many advanced features to add custom check fields and improve checkout experiences.
The Downside Of Default Magento 2 Checkout Page
By default, the Magento checkout page only shows mandatory informative fields, and it doesn’t offer extra checkout fields.
However, your business usually requires more than that basic information to:
- Understand your customers better
- Collect data to do some research
- Fulfill customers’ additional demands
Therefore, the default checkout page can bring down the competitiveness of your store.
EXPLORE NOW 9 Magento 2 Checkout Customization Techniques to improve the process!
Instruction To Add Magento Custom Checkout Fields Programmatically
Note: In this intrusion, we will show you how to add the “Delivery Date” field as an example. But you can add any custom checkout field following these steps.
Step 1: Create a module
The first step you need to do is to create the registration.php file as below:
registration.php <?php use \Magento\Framework\Component\ComponentRegistrar; ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Deliverydate', __DIR__); 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="Magezon_Deliverydate" setup_version="1.0.0"> <sequence> <module name="Magento_Sales"/> </sequence> </module> </config>
You can change the Module name accordingly to the additional field you want to add.
In the code, we are using the name “Deliverydate.”
Step 2: Add a new column to some tables
Next, you need to add a new column for your new custom field to the following tables:
- quote
- sales_order
- sales_order_grid
<?php namespace Magezon\Deliverydate\Setup; 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(); $installer->getConnection()->addColumn( $installer->getTable('quote'), 'delivery_date', [ 'type' => 'datetime', 'nullable' => false, 'comment' => 'Delivery Date', ] ); $installer->getConnection()->addColumn( $installer->getTable('sales_order'), 'delivery_date', [ 'type' => 'datetime', 'nullable' => false, 'comment' => 'Delivery Date', ] ); $installer->getConnection()->addColumn( $installer->getTable('sales_order_grid'), 'delivery_date', [ 'type' => 'datetime', 'nullable' => false, 'comment' => 'Delivery Date', ] ); $setup->endSetup(); } }
Because we are creating a “Delivery Date” checkout field in this example, the field type is set as “datetime.”
You can also set the input type to “text” to collect string data.
Step 3: Add this order attribute field to the checkout page
etc\frontend\di.xml <?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <type name="Magento\Checkout\Block\Checkout\LayoutProcessor"> <plugin name="add_delivery_date_field" type="Magezon\Deliverydate\Plugin\Checkout\LayoutProcessorPlugin" sortOrder="10"/> </type> </config> Magezon\Deliverydate\Plugin\Checkout\LayoutProcessor.php: <?php namespace Magezon\Deliverydate\Plugin\Checkout; class LayoutProcessorPlugin { /** * @param \Magento\Checkout\Block\Checkout\LayoutProcessor $subject * @param array $jsLayout * @return array */ public function afterProcess( \Magento\Checkout\Block\Checkout\LayoutProcessor $subject, array $jsLayout ) { $jsLayout['components']['checkout']['children']['steps']['children']['shipping-step']['children'] ['shippingAddress']['children']['before-form']['children']['delivery_date'] = [ 'component' => 'Magento_Ui/js/form/element/date', 'config' => [ 'customScope' => 'shippingAddress', 'template' => 'ui/form/field', 'elementTmpl' => 'ui/form/element/date', 'options' => [], 'id' => 'delivery_date' ], 'dataScope' => 'shippingAddress.delivery_date', 'label' => __('Delivery Date'), 'provider' => 'checkoutProvider', 'visible' => true, 'validation' => [], 'sortOrder' => 200, 'id' => 'delivery_date' ]; return $jsLayout; } }
After this step, you can check how it looks in the front end.
Step 4: Save the selected attribute value of the custom field
There are several ways to do this, but we use Knockout JS as the simplest way in this instruction.
First, override some .js files by adding them to the requirejs-config.js.
var config = { config: { mixins: { 'Magento_Checkout/js/action/place-order': { 'Magezon_Deliverydate/js/order/place-order-mixin': true }, } };
For the place-order-mixin.js file, save the attribute value of your new custom field to the quote by using Ajax.
define([ 'jquery', 'mage/utils/wrapper', 'Magento_CheckoutAgreements/js/model/agreements-assigner', 'Magento_Checkout/js/model/quote', 'Magento_Customer/js/model/customer', 'Magento_Checkout/js/model/url-builder', 'mage/url', 'Magento_Checkout/js/model/error-processor', 'uiRegistry' ], function ( $, wrapper, agreementsAssigner, quote, customer, urlBuilder, urlFormatter, errorProcessor, registry ) { 'use strict'; return function (placeOrderAction) { /** Override default place order action and add agreement_ids to request */ return wrapper.wrap(placeOrderAction, function (originalAction, paymentData, messageContainer) { agreementsAssigner(paymentData); var isCustomer = customer.isLoggedIn(); var quoteId = quote.getQuoteId(); var url = urlFormatter.build('mgzcustom/quote/save'); var deliveryDate = $('[name="delivery_date"]').val(); if (deliveryDate) { var payload = { 'cartId': quoteId, 'delivery_date': deliveryDate, 'is_customer': isCustomer }; if (!payload.delivery_date) { return true; } var result = true; $.ajax({ url: url, data: payload, dataType: 'text', type: 'POST', }).done( function (response) { result = true; } ).fail( function (response) { result = false; errorProcessor.process(response); } ); } return originalAction(paymentData, messageContainer); }); }; });
Then create the Controller\Quote\Save.php file.
<?php namespace Magezon\Deliverydate\Controller\Quote; class Save extends \Magento\Framework\App\Action\Action { protected $quoteIdMaskFactory; protected $quoteRepository; public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Quote\Model\QuoteIdMaskFactory $quoteIdMaskFactory, \Magento\Quote\Api\CartRepositoryInterface $quoteRepository ) { parent::__construct($context); $this->quoteRepository = $quoteRepository; $this->quoteIdMaskFactory = $quoteIdMaskFactory; } /** * @return \Magento\Framework\Controller\Result\Raw */ public function execute() { $post = $this->getRequest()->getPostValue(); if ($post) { $cartId = $post['cartId']; $deliveryDate = $post['delivery_date']; $loggin = $post['is_customer']; if ($loggin === 'false') { $cartId = $this->quoteIdMaskFactory->create()->load($cartId, 'masked_id')->getQuoteId(); } $quote = $this->quoteRepository->getActive($cartId); if (!$quote->getItemsCount()) { throw new NoSuchEntityException(__('Cart %1 doesn\'t contain products', $cartId)); } $quote->setData('delivery_date', $deliveryDate); $this->quoteRepository->save($quote); } } }
Now we need to create a file etc/frontend/routes.xml to set up a router so that Ajax can send the data of your new custom checkout field to the controller.
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd"> <router id="standard"> <route id="mgzcustom" frontName="mgzcustom"> <module name="Magezon_Deliverydate" /> </route> </router> </config>
After that, you save the selected values of your custom field to the sale_order.table.
It’s time to create the etc/events.xml file.
<?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="sales_model_service_quote_submit_before"> <observer name="save_delivery_date_to_order" instance="Magezon\Deliverydate\Observer\SaveToOrder" /> </event> </config>
Và file Observer\SaveToOrder.php
<?php namespace Magezon\Deliverydate\Observer; class SaveToOrder implements \Magento\Framework\Event\ObserverInterface { public function execute(\Magento\Framework\Event\Observer $observer) { $event = $observer->getEvent(); $quote = $event->getQuote(); $order = $event->getOrder(); $order->setData('delivery_date', $quote->getData('delivery_date')); } }
Step 5: Display the attribute value in the sales order grid
To show the attribute value of the custom field in the order grid, you need to create the sales_order_grid.xml.
Then you add an extra column named as the name of your custom field (it’s Delivery Date in this example) to the path: View\adminhtml\ui_component\sales_order_grid.xml.
<?xml version="1.0"?> <listing xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Ui:etc/ui_configuration.xsd"> <columns name="sales_order_columns"> <column name="delivery_date"> <argument name="data" xsi:type="array"> <item name="config" xsi:type="array"> <item name="visible" xsi:type="boolean">true</item> <item name="label" xsi:type="string" translate="true">Delivery Date</item> <item name="dateFormat" xsi:type="string">Y-MM-dd</item> <item name="component" xsi:type="string">Magento_Ui/js/grid/columns/date</item> <item name="dataType" xsi:type="string">date</item> </item> </argument> </column> </columns> </listing>
As you can see in the image below, we have had a new column named Delivery Date.
Conclusion
Above, we have shown you how to add Magento Custom Checkout Fields programmatically.
We hope this article is helpful and good luck to you!
CHECK OUT guide to Remove Magento 2 Checkout Fields without using third-party extensions HERE!
BSS Commerce is one of the leading Magento extension providers and web development services in the world. With experienced and certified Magento developers, we commit to bringing high-quality products and services to optimize your business effectively. Furthermore, we offer FREE Installation – FREE 1-year Support and FREE Lifetime Update for every Magento extension.
CONTACT NOW to let us know your problems. We are willing to support you every time.