WooCommerce 2 Step Checkout


Right, new year (nepali), new tutorial.

We’re going to be taking a dive into a custom WooCommerce Multistep Checkout.

If you rather just see the code then here or here is good 😀

The Scenario:

So here’s what I want to do, create a 2 – step checkout.

First Step:

The User Fills in their user details

Second Step:

The User reviews their order and completes payment.

For simplicity sake, this tutorial won’t go beyond that. We won’t be covering, changing user details once they enter the second step because well that’s just too much to cover.

Modifying the template:

I’m using the default twenty seventeen theme

So first things first, we need to figure out all the elements we’re going to be changing.

So as you may know woocommerce offer us the ability to change templates and modify them to our needs. We will be doing that.

The template in question is /plugins/woocommerce/checkout/form-checkout.php/.

We copy this template into our child-theme into a /woocommerce/checkout/ folder.

So if you have a look at this template you see it’s already very well segmented.

What we are going to do now is add our own wrappers around each segment.

The step-1 div wrapper will go around customer-details

And the step-2 div wrapper will go around step-2. Now using some CSS we hide the second div.

The final result should look something like this.

Adding the Verify Details Button:

At this time, the billing and shipping fields (if shipping is enabled) and order notes should be visible and, order review and payment forms are hidden.

Now we add the button at the very end of customer-details div as well as a hidden field called, current_step. The intention here is that we want the user to be able to verify all their details and show any and all error before moving to step-2. For this a little bit of trickery is required.

The Problem:

Ok we’re got everything setup, now. The Steps have been divided, the button added and now all we need to do is hide and show the fields using some very simple jquery. Right ? WRONG.

The PROBLEM here is that if a user, goes from step-1 to step-2 , without filling out every field correctly. They will encounter an error in step-2.

So imaging having to go back and forth each time just to correct one error. Troublesome right.

The Solution:

Part 1: THE PHP

Luckily that’s where the hidden button comes in, as well as some diving into the woocommerce core files.

Let’s go into, the normal flow of the checkout.

A user goes to checkout click on make payment, via ajax the order is validated and if any errors occur the process is halted otherwise checkout is completed.

My goal here is to pause this process on the validation and prevent the checkout from happening.

That way, if there are errors the errors will be displayed. Else, the user goes to step-2 and continues the checkout process.

So to do that lets go into the /plugins/woocommerce/class-wc-checkout.php and the public function process_checkout() line no 895, this is where the magic happens.

On line no 920 I noticed. $this->validate_checkout() and in the function it has a action.

do_action( ‘woocommerce_after_checkout_validation’, $data, $errors );

So. What I am doing now is in my child themes functions.php file. I check if there are errors and which step the user is on, if there are errors then fine, woocommerce will handle it itself.

If there aren’t any errors and the user is on step-1 however I forcibly add my own error and prevent the checkout process from continuing any further.

This I do in my child themes functions.php file

add_action('woocommerce_after_checkout_validation', 'digthis_two_step_checkout_validate', 9999, 2);
function digthis_two_step_checkout_validate($data, $errors) {

$step = filter_input(INPUT_POST, ‘current_step’);

if( empty( $errors->errors ) && $step == ‘step-1’ ){
$errors->add( ‘digthis’, __( ‘<span id=”digthis-prevent-error”>Digthis Error</span>’, ‘woocommerce’ ) );


Now lets take a moment to stop here and take a look at our progress. What should be happening is.

If there are errors, errors should show. Otherwise, Digthis Error should show.


Part 2 : THE JS

Now comes the second part of our solutioin. After we’ve successfully validated the form fields and prevented auto checkout. We now need to go to step-2.

WooCommerce triggers  a ‘checkout_error’ event when an error occurs and this allows us to hook in and find if “digthis-prevent-error” div is present and move on to step-2.

Here is the complete files, for your convience in a zip format. Hope this helps someone out.

And if anyone has a better way to do this. I’m all ears.


21 responses to “WooCommerce 2 Step Checkout”

  1. Stephen Avatar

    Im so excited to see this as it is exactly what i am looking for . I set this up on my current theme but im running into an issue, After completing the first step and clicking verify it automatically completes the order and goes to the order completed details page . it is skipping the second step with order table and choice of shipping . I am using wordpress 4.6.5 and woocommerce 3.0 so im not sure if these versions have factors in this or if it is my theme .

    Any help or advice would be greatly appreciated

    1. Digamber Pradhan Avatar
      Digamber Pradhan

      Hi Stephen,
      Just went tested it on WooCommerce version 3.0.5 is working well for me.
      Have you made sure this code is running ?

      To make sure try to stop the Checkout Process here, otherwise it will cause you to Process order.

  2. Brandon Avatar

    I was trying to figure out a 2 step checkout process and I found this article from google, a very great solution! I’m definitely gonna use it.

    1. Digamber Pradhan Avatar
      Digamber Pradhan

      Thanks Brandon, glad to be of help 😀

  3. Francesco Avatar

    Hi Digamber Pradhan,

    sorry for my english. Congratulations to the solution. But i have a question, for a problem.
    I have add custom special field

    add_action(‘woocommerce_before_checkout_billing_form’, ‘customise_checkout_category_user’, 0);

    function customise_checkout_category_user($checkout) {

    woocommerce_form_field( ‘inscription_textbox_cf’, array(
    ‘type’ => ‘text’,
    ‘class’ => array( ‘inscription-text_cf form-row-wide’ ),
    ‘label’ => __( ‘Codice Fiscale’ ),
    ‘required’ => true,
    ), $checkout->get_value( ‘inscription_textbox_cf’ ) );

    woocommerce_form_field( ‘inscription_textbox_iva’, array(
    ‘type’ => ‘text’,
    ‘class’ => array( ‘inscription-text_iva form-row form-row-last’ ),
    ‘label’ => __( ‘Partita Iva’ ),
    ‘required’ => true,
    ), $checkout->get_value( ‘inscription_textbox_iva’ ) );

    The validation of these fields takes place only at the end of the second step, when I click on the “finish order” button, after payment method choice’s.

    Thanks in advance.

    1. Digamber Pradhan Avatar
      Digamber Pradhan

      Hey Francesco,
      I haven’t had the chance to look into what you are saying yet. I will give it a go and come back to you as soon as i can

      1. Digamber Pradhan Avatar
        Digamber Pradhan

        Hey Francesco,
        I was able to try out your screnario. The question would be how are you validating those fields.
        you should definelty have used “woocommerce_after_checkout_validation” hook for this.
        here’s a modified gist, with both your code and validation of the code done.


        hope this was helpful

  4. Tine Avatar

    I have tried your solution and it works. I played with code, but can’t reproduce “thank you” page look on your “review before payment” page. Besides that, I would like to include item price on first step (when filling out form) and on a second step I’d like to add contact info from step 1.

    Also, I use a delivery date plugin, which doesn’t get validated on step one, but does on step 2, so i would appriciate some help around that too 🙂
    Plugin link: https://wordpress.org/plugins/order-delivery-date-for-woocommerce/

    Hope you will answer soon 🙂 🙂

    Best regards, Tine

    1. Tine Avatar

      Oops, I forgot to mention a few important things 😛
      WP runs in Multisite mode and I use WPML Multilingual

  5. David Andrew Avatar

    Hi Digamber

    Thanks for your post!

    I combined it with this post [1] and it worked out pretty well. What really helped was this post [2] and realising the two parameters that woocommerce_after_checkout_validation() has:

    – $data
    – $errors


    [1] https://mircian.com/2016/10/12/hooking-woocommerces-js-events/
    [2] http://woocommerce.wp-a2z.org/oik_api/wc_checkoutvalidate_checkout/

  6. fenil kalal Avatar

    Hi there,
    getting error “Please read and accept the terms and conditions to proceed with your order.”
    which is in second step of the checkout page.
    how to solve this.

    1. Digamber Pradhan Avatar
      Digamber Pradhan

      Hi Fenil,
      You have terms and conditions enabled please check if it’s showing on the second step itself.

      1. Digamber Pradhan Avatar
        Digamber Pradhan

        Hi Fenil –
        I think your issue is the same one as Timo had so please review this gist https://gist.github.com/digamber89/e9f2c2d160feae563b2edfc15d24eb4f and make the code adjustments accordingly.

  7. Ram Avatar

    Hey thanks this has been a live saver for me. It saved a lot of time. I have one question, is it possible to check if user already exists in step 1. It says user already exists on step 2. Can this be done along with validation in step 1.

    1. Digamber Pradhan Avatar
      Digamber Pradhan

      Hi Ram,
      You will need to hook in before WooCommerce Validates and run your own validation. I hope that helps.

  8. Timo Avatar

    Love that one. So I immediately put this on the site. When validating step-1, there’s an error message: “Please read and accept the terms and conditions to proceed with your order.” So I can not proceed to step-2. But the checkbox for accepting terms is shown on step-2. So, pretty much unable to proceed checkout.

    Can you give me a helping hand on how to remove terms & conditions – validation from step-1 please? I’m running WP 5.03 and Woo 3.5.4.

    Thanks a lot 🙂

    1. Digamber Pradhan Avatar
      Digamber Pradhan

      Hi Timo,
      yes i hadn’t really thought of the terms and conditions.
      I’ve modified the code slightly – please check this public gist
      and make the modifications to your code accordingly.

      I’ll update the article once i get more time.

      1. Timo Avatar

        Great, thank you! Works fine now.

        If you’re willing to enhance this one day, you may enhance by adding some kind of progress-bar for the checkout. So one could (a) go back and forth plus (b) have an idea of how many steps to take in the whole checkout process.

        Thanks again

        1. Digamber Pradhan Avatar
          Digamber Pradhan

          actually on my own implementation – i did create those progress bars.
          I just wanted anyone accessing this post to be able to get the core idea about the implementation.
          So – that’s why no shiny stuff 😀 maybe i’ll create a progress bar version too for reference.

          1. Timo Avatar

            I see. Fair enough 🙂
            Maybe I get back to you for implementing.

  9. NewbieWoocommerce Avatar

    Care to share how to add back button on step-2? i am trying to add a button with this JS, but when i click it is placing the order instead of going back to step-1.

    function checkoutBackButton() {
    var currentsteplocation = document.getElementById(“digthis-step-2”);
    var previoussteplocation = document.getElementById(“digthis-step-1”)

    currentsteplocation.style.display = “none”;
    previoussteplocation.style.display = “block”


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.