Magento Tutorials

How to Customize the Magento 2 Checkout Process

In Magento 2, the checkout process is redesigned for a faster and easier experience. The Checkout page leads the customer through 2 easy steps of the process. Customers who are logged into their accounts can complete checkout quickly, because much of the information is already in their accounts. The first step of the Magento 2 checkout process is for the customer to complete the shipping address information, and to choose the shipping method. During the second step, the customer chooses the payment method, and applies any coupons to complete the purchase.

Customize the default checkout of Magento 2

You can either add a new checkout step or change the view of an existing checkout  to customize the default checkout in your own way.

Add a new checkout step

You can add a custom checkout step, it should be implemented as a UI component. For the sake of compatibility, upgradability and easy maintenance, do not edit the default Magento code, add your customizations in a separate module.

Step 1: Create the view part of the checkout step component

To create the view part of the new checkout step:

  1. Add a module directory. All custom files must be stored there. For your checkout customization to be applied correctly, your custom module should depend on the Magento_Checkout module. Do not use Ui for your custom module name, because %Vendor%_Ui notation, required when specifying paths, might cause issues.
  2. Create the .js file implementing the view model.
  3. Create an .html template for the component.

Each step is described in details below:

1. Add the JavaScript file implementing the new step

A new checkout step must be implemented as UI component. That is, its JavaScript implementation must be a JavaScript module.

The file must be stored under the <your_module_dir>/view/frontend/web/js/view directory.

<your_module_dir> notation stands for the path to your module directory from the root directory. Usually it will be one of the following: app/code/<YourVendor>/<YourModule> or vendor/<yourvendor>/module-<module>-<name>.

A sample my-step-view.js with comments follows:

define(
    ['ko', 'uiComponent', 'underscore', 'Magento_Checkout / js / model / step - navigator'],
    function(
        ko,
        Component,
        _,
        stepNavigator
    ) {'
        use strict';
        /**
         *
         * mystep – is the name of the component's .html template,
         * <Vendor>_<Module> – is the name of the your module directory.
         *
         */
        return Component.extend({
            defaults: {
                template: ' < Vendor > _ < Module > /mystep'
            },

            //add here your logic to display step,
            isVisible: ko.observable(true),

            /**
             *
             * @returns {*}
             */
            initialize: function() {
                this._super();
                // register your step
                stepNavigator.registerStep(
                    //step code will be used as step content id in the component template
                    'step_code',
                    //step alias
                    null,
                    //step title value
                    'Step Title',
                    //observable property with logic when display step or hide step
                    this.isVisible,

                    _.bind(this.navigate, this),

                    /**
                     * sort order value
                     * 'sort order value' < 10: step displays before shipping step;
                     * 10 < 'sort order value' < 20 : step displays between shipping and payment step
                     * 'sort order value' > 20 : step displays after payment step
                     */
                    15
                );

                return this;
            },

            /**
             * The navigate() method is responsible for navigation between checkout step
             * during checkout. You can add custom logic, for example some conditions
             * for switching to your custom step
             */
            navigate: function() {

            },

            /**
             * @returns void
             */
            navigateToNextStep: function() {
                stepNavigator.next();
            }
        });
    }
);
2. Add the .html template

In the module directory, add the .html template for the component. It must be located under the <your_module_dir>/view/frontend/web/template directory.

A sample mystep.html follows:

<!–The 'step_code' value from the .js file should be used–>
<li id="step_code" data-bind="fadeVisible: isVisible">
    <div class="step-title" data-bind="i18n: 'Step Title'" data-role="title"></div>
    <div id="checkout-step-title" class="step-content" data-role="content">

        <form data-bind="submit: navigateToNextStep" novalidate="novalidate">
            <div class="actions-toolbar">
                <div class="primary">
                    <button data-role="opc-continue" type="submit" class="button action continue primary">
                        <span><!– ko i18n: 'Next'–><!– /ko –></span>
                    </button>
                </div>
            </div>
        </form>
    </div>
</li>

Step 2: Add your step to the Checkout page layout

For the new step to be displayed on the page, you need to declare it in the Checkout page layout, which is defined in checkout_index_index.xml.

So you need to add an extending checkout_index_index.xml layout file in the following location: <your_module_dir>/view/frontend/layout/checkout_index_index.xml

A sample checkout_index_index.xml follows:

<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="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                                <item name="steps" xsi:type="array">
                                    <item name="children" xsi:type="array">
                                        <!– The new step you add –>
                                        <item name="my-new-step" xsi:type="array">
                                            <item name="component" xsi:type="string">%Vendor%_%Module%/js/view/my-step-view</item>
                                            <!–To display step content before shipping step "sortOrder" value should be < 1–>
                                            <!–To display step content between shipping step and payment step 1 < "sortOrder" < 2 –>
                                            <!–To display step content after payment step "sortOrder" >2 –>
                                            <item name="sortOrder" xsi:type="string">2</item>
                                            <item name="children" xsi:type="array">
                                                <!–add here child component declaration for your step–>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

Customize the view of an existing checkout

In Magento applications, checkout is implemented using UI components. You can customize each step by changing the JavaScriptimplementation or template for a component, adding, removing or disabling a component.

Step 1: Change the component’s .js implementation and template

To change the .js implementation and template used for components rendering, you need to declare the new files in the checkout page layout. To do this, take the following steps:

  1. In your custom module directory, create the following new file: <your_module_dir>/view/frontend/layout/checkout_index_index.xml. (For your checkout customization to be applied correctly, your custom module should depend on the Magento_Checkout module.)
  2. In this file, add the following:
<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="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <!– Your customization will be here –>
                    …
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>
  1. In the <Magento_Checkout_module_dir>/view/frontend/layout/checkout_index_index.xml file, find the component that you need to customize. Copy the corresponding node and all parent nodes up to <argument>. There is no need to leave all the attributes and values of parente nodes, as you are not going to change them.
  2. Change the path to the component’s .js file, template or any other property.

Example:

The Magento_Shipping module adds a component rendered as a link to the Shipping Policy info to the Shipping step:

<Magento_Shipping_module_dir>/view/frontend/layout/checkout_index_index.xml

 looks like following:

<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="checkout.root">
            <arguments>
                <argument name="jsLayout" xsi:type="array">
                    <item name="components" xsi:type="array">
                        <item name="checkout" xsi:type="array">
                            <item name="children" xsi:type="array">
                                <item name="steps" xsi:type="array">
                                    <item name="children" xsi:type="array">
                                        <item name="shipping-step" xsi:type="array">
                                            <item name="children" xsi:type="array">
                                                <item name="shippingAddress" xsi:type="array">
                                                    <item name="children" xsi:type="array">
                                                        <item name="before-shipping-method-form" xsi:type="array">
                                                            <item name="children" xsi:type="array">
                                                                <item name="shipping_policy" xsi:type="array">
                                                                    <item name="component" xsi:type="string">Magento_Shipping/js/view/checkout/shipping/shipping-policy</item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body>
</page>

Step 2: Add the new component to the checkout page layout

Any UI component is added in the checkout_index_index.xml similar to the way a checkout step component is added.

Make sure that you declare a component so that it is rendered correctly by the parent component. If a parent component is a general UI component (referenced by the uiComponent alias), its child components are rendered without any conditions. But if a parent component is a an extension of a general UI components, then children rendering might be restricted in certain way. For example a component can render only children from a certain displayArea.

Step 3: Disable a component

To disable the component in your checkout_index_index.xml use the following instructions:

<item name="%the_component_to_be_disabled%" xsi:type="array">
    <item name="config" xsi:type="array">
        <item name="componentDisabled" xsi:type="boolean">true</item>
    </item>
</item>

Step 4: Remove a component

To remove a component from layout rendering, you need to create a plugin for the \Magento\Checkout\Block\Checkout\LayoutProcessor::process method. In your plugin, implement the around method removing the corresponding layout nodes at run-time.

The following sample is an example of the around method removing a component:

unset($jsLayout['components']['checkout']['children']['steps'][%path_to_target_node%]); //%path_to_target_node% is the path to the component's node in checkout_index_index.xml
return $jsLayout;

(If you want to use this sample in your code, replace the %path_to_target_node% placeholder with real value.)

*Disable vs remove a component: If you disable a component, it is loaded but not rendered. If you remove a component, it is not loaded.

Related posts:
How to Add Discount Code to Checkout in Magento
How to Add a Custom Payment to Magento 2 Checkout