[How To] Add A Multi-Step Form 2.0


Userlevel 7
  • Former Unbouncer
  • 126 replies

When you’re building your landing pages in Unbounce, you want the conversion process to be as simple as possible. Nothing too distracting, and you certainly don’t want to scare your audience away with long, time-consuming forms.

We’ve built an easy solution for you because, hey, we’re marketers too! :unbounce:

Introducing Multi-Step Forms! 📈 🎉

No more scary, conversion killing forms!
Follow the steps below to implement this handy script into your landing page and try it for yourself! And, as always, remember to A/B test, and keep us posted on your results!

You can see this in action (built in Unbounce) here:


How to Install in Unbounce

Click Here for Instructions

🚨
This is not an official Unbounce feature. This functionality is based entirely on third party code, and has only been tested in limited applications. Since this isn’t a supported Unbounce feature, our support team will be unable to assist if things go awry. So if you are not comfortable with HTML, Javascript and CSS, please consider consulting an experienced developer.


Step 1.

Create your form in Unbounce.

Step 2.

Create a new button element for your ‘Next’ button and one for your ‘Previous’ button. Keep in mind when positioning these buttons (and your form submission button) that only one field will be shown at a time.

Step 3.

Copy this script and paste it into the Javascripts section of your page with placement ‘Before Body End Tag’:

<script type="text/javascript" src="https://rawgit.com/kimmobrunfeldt/progressbar.js/1.0.0/dist/progressbar.js"></script>

<script>
  (function() {
    // Update the following IDs with your own button IDs
    var backButton = document.getElementById('lp-pom-button-14');
    var nextButton = document.getElementById('lp-pom-button-13');
    var showProgressBar = false;

    var submitButton = document.querySelector('.lp-pom-form .lp-pom-button');
    var formContainer = document.querySelector('.lp-element .lp-pom-form');
    var currentField = 0;
    var allFields = document.getElementsByClassName('lp-pom-form-field');
    var errorSpan = document.createElement('span');

    for (i = 0; i < allFields.length; i++) {
      allFields[i].classList.add('hide');
      allFields[i].style.top = '0px';
    }

    backButton.classList.add('hide');
    submitButton.classList.add('hide');

    allFields[0].classList.remove('hide');

    if (allFields[0].querySelector('input')) {
      allFields[0].querySelector('input').focus();
    }

    errorSpan.classList.add('hide');
    errorSpan.style.color = 'red';
    errorSpan.style.position = 'absolute';
    var labelHeight;
    if (allFields[0].querySelector('label')) {
      labelHeight = allFields[0].querySelector('label').clientHeight;
    } else {
      labelHeight = 25;
    }
    errorSpan.style.top = '-' + labelHeight + 'px';
    formContainer.appendChild(errorSpan);

    if (showProgressBar) {
      var progressContainer = document.createElement('div');
      progressContainer.id = 'container';
      formContainer.appendChild(progressContainer);

      var bar = new ProgressBar.Line(container, {
        strokeWidth: 4,
        easing: 'easeInOut',
        duration: 1400,
        color: '#FFEA82',
        trailColor: '#eee',
        trailWidth: 1,
        svgStyle: { width: '100%', height: '100%' },
        from: { color: '#FFEA82' },
        to: { color: '#74D16A' },
        text: {
          style: {
            // Text color.
            // Default: same as stroke color (options.color)
            color: '#fff',
            position: 'absolute',
            right: '0',
            top: '30px',
            padding: 0,
            margin: 0,
            transform: null,
          },
          autoStyleContainer: false,
        },
        step: function(state, bar) {
          bar.setText(currentField + 1 + ' of ' + allFields.length);
          bar.path.setAttribute('stroke', state.color);
        },
      });
    }

    function nextEvent() {
      allFields[currentField].classList.add('hide');

      currentField += 1;
      allFields[currentField].classList.remove('hide');
      if (allFields[currentField].querySelector('input')) {
        allFields[currentField].querySelector('input').focus();
      }

      if (currentField > 0) {
        backButton.classList.remove('hide');
      }

      if (currentField === allFields.length - 1) {
        submitButton.classList.remove('hide');
        nextButton.classList.add('hide');
      }

      updateProgress();
    }

    function backEvent() {
      allFields[currentField].classList.add('hide');
      submitButton.classList.add('hide');

      currentField -= 1;
      allFields[currentField].classList.remove('hide');
      if (allFields[currentField].querySelector('input')) {
        allFields[currentField].querySelector('input').focus();
      }
      if (currentField === 0) {
        backButton.classList.add('hide');
        nextButton.classList.remove('hide');
      }
      if (currentField <= allFields.length - 1) {
        nextButton.classList.remove('hide');
      }

      updateProgress();
    }

    function currentFieldInvalid() {
      var invalidInput = allFields[currentField].querySelector(':invalid');

      if (invalidInput) {
        errorSpan.textContent = invalidInput.validationMessage;
      }

      return Boolean(invalidInput);
    }

    function updateProgress() {
      if (showProgressBar) {
        var barSize = (currentField + 1) / allFields.length;
        bar.animate(barSize); // Number from 0.0 to 1.0
      }
    }

    updateProgress();

    nextButton.addEventListener('click', function(e) {
      if (currentFieldInvalid()) {
        if (allFields[currentField].querySelector('input')) {
          allFields[currentField].querySelector('input').classList.add('hasError');
        } else {
          allFields[currentField].children[1].classList.add('hasError');
        }

        errorSpan.classList.remove('hide');
        e.preventDefault();
      } else {
        if (allFields[currentField].querySelector('input')) {
          allFields[currentField].querySelector('input').classList.remove('hasError');
        } else {
          allFields[currentField].children[1].classList.remove('hasError');
        }

        errorSpan.classList.add('hide');
        nextEvent();
      }
    });

    backButton.addEventListener('click', backEvent);

    submitButton.addEventListener('click', function(e) {
      if (currentFieldInvalid()) {
        if (allFields[currentField].querySelector('input')) {
          allFields[currentField].querySelector('input').classList.add('hasError');
        } else {
          allFields[currentField].children[1].classList.add('hasError');
        }

        errorSpan.classList.remove('hide');
        e.preventDefault();
      } else {
        if (allFields[currentField].querySelector('input')) {
          allFields[currentField].querySelector('input').classList.remove('hasError');
        } else {
          allFields[currentField].children[1].classList.remove('hasError');
        }

        errorSpan.classList.add('hide');
      }
    });

    document.body.addEventListener('keydown', function(e) {
      var keyCode = e.keyCode || e.which;

      // Enter key
      if (keyCode === 13 && currentField < allFields.length - 1) {
        if (currentFieldInvalid()) {
          if (allFields[currentField].querySelector('input')) {
            allFields[currentField].querySelector('input').classList.add('hasError');
          } else {
            allFields[currentField].children[1].classList.add('hasError');
          }

          errorSpan.classList.remove('hide');
          e.preventDefault();
        } else {
          if (allFields[currentField].querySelector('input')) {
            allFields[currentField].querySelector('input').classList.remove('hasError');
          } else {
            allFields[currentField].children[1].classList.remove('hasError');
          }

          errorSpan.classList.add('hide');
          e.preventDefault();
          nextEvent();
        }
      } else if (keyCode === 13 && currentField === allFields.length - 1) {
        if (currentFieldInvalid()) {
          if (allFields[currentField].querySelector('input')) {
            allFields[currentField].querySelector('input').classList.add('hasError');
          } else {
            allFields[currentField].children[1].classList.add('hasError');
          }

          errorSpan.classList.remove('hide');
          e.preventDefault();
        } else {
          if (allFields[currentField].querySelector('input')) {
            allFields[currentField].querySelector('input').classList.remove('hasError');
          } else {
            allFields[currentField].children[1].classList.remove('hasError');
          }

          errorSpan.classList.add('hide');
        }
      }

      if (keyCode === 37) {
        // Left key
        if (currentField > 0) {
          backEvent();
        }
      } else if (keyCode === 39) {
        // Right key
        if (currentField < allFields.length - 1) {
          if (currentFieldInvalid()) {
            if (allFields[currentField].querySelector('input')) {
              allFields[currentField].querySelector('input').classList.add('hasError');
            } else {
              allFields[currentField].children[1].classList.add('hasError');
            }

            errorSpan.classList.remove('hide');
            e.preventDefault();
          } else {
            if (allFields[currentField].querySelector('input')) {
              allFields[currentField].querySelector('input').classList.remove('hasError');
            } else {
              allFields[currentField].children[1].classList.remove('hasError');
            }

            errorSpan.classList.add('hide');
            nextEvent();
          }
        }
      }
    });
  })();

  /**
   * Do not remove this section; it allows our team to troubleshoot and track feature adoption.
   * TS:0002-03-062
   */
</script>

Step 4.

Update the script with the ID of your ‘Previous’ and ‘Next’ button elements. Tip: Make sure you exclude the ‘#’ in the ID.

Step 5.

Copy this script and paste it into the Stylesheets section of your page:

<style>
  #container {
    margin-top: -45px;
    width: 100%;
    height: 8px;
    position: relative;
  }
  .lp-form-errors {
    display: none !important;
  }
  .hasError {
    border: 1px solid tomato !important;
    box-shadow: 0px 0px 5px 1px tomato !important;
  }
  .hide {
    display: none !important;
  }
  .lp-pom-form-field,
  .lp-pom-button {
    -webkit-animation: KEYFRAME-NAME 2s;
    -moz-animation: KEYFRAME-NAME 2s;
    -o-animation: KEYFRAME-NAME 2s;
    animation: KEYFRAME-NAME 2s;
  }

  @-webkit-keyframes KEYFRAME-NAME {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @-moz-keyframes KEYFRAME-NAME {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @-o-keyframes KEYFRAME-NAME {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
  @keyframes KEYFRAME-NAME {
    0% {
      opacity: 0;
    }
    100% {
      opacity: 1;
    }
  }
</style>

You’re done!

Now sit back and let the conversions roll in… :gif_master:


Can’t see the instructions? Log in or Join the Community to get access immediately. 🚀


Want to take your Unbounce landing pages + Convertables™ to the next level?
:spinbounce: Check out the Ultimate List of Unbounce Tips, Scripts & Hacks


224 replies

Userlevel 7
Badge +3

Hey @ygivechi,

Yes, I can land you hand.

Please feel free to DM me or fill out the contact form at the bottom of my Unbounce Services page with a bit more details on the problem you are trying to solve.

Best,
Hristian

Would the latest script sumbit the info after each of the steps?

For example: In the first step I will be asking for Name, Email, Phone Number, and then in the next steps I will be asking for more pre-qualifying questions.

The idea is to get name, email and phone number regardless of if the answered questions that come after step 1.

Userlevel 7
Badge +3

Hi @vastashevskii,

No, the information is submitted only after all the steps are completed.

Everything else is just hiding/showing fields based on the step you are on.

If you need to submit the information from each step separately, you’ll have to write a custom submit function or split up the form through multiple pages.

Best,
Hristian

Hello everyone,

I have dug and dug through this community trying to find a simple solution for a multi-step form that we could implement across multiple client pages. There are some good options, but I kept finding them to be a fit for one specific situation and not very flexible.

So my team and I spent about 15 working hours simplifying the code originally published in v1 of this thread and testing it to make sure it is workable across both pages and popups and fully allows the editing functions that we all love in Unbounce.

I don’t know if I’m allowed to post the blog article here or not, so I’m going to try, no subscription wall or bs, just simple steps to implement. I really hope this helps everyone. (It’s like a 2 minute read.)

How to build a multi-step form in Unbounce, instructions, downloadable docs and Q&A

Userlevel 5
Badge +4

Hello @ScienceInAdvertising !

Thanks for the time taken to do this !
I’ve been using the Multistep form 2.0 since it appears and then i have switched to Jotform.
Multi step was a game changer in performance for us.
A shame it’s not working with AMP pages.

About your Script, is it different from this one ? Multi-Field, Multi-Step Form 🔥

Hi team,I have created my own code for unbounce multistep form.I have implemented it on 500+ pages.It is very flexible for both mobile and desktop.You can contact me personally through email.Thanks

With this multi-step form is Unbounce (or whatever data repository you have integrated it with) collecting the data from the initial steps if the prospect/ visitor doesn’t complete the last step.

It is not possible in unbounce because we can’t write our own logics for saving leads in unbounce leads database but we can give an option to user to submit form at any step.It may help you I think.Thanks

Have you or anyone else tried to submit steps that were completed to a different source? e.g. post to external data source so when users drop off you have an opportunity to re-market/re-contact assuming contact info is on the initial step? I don’t think getting the user to submit is viable unless its something like save and come back but that comes with a different set of complication with Unbounce.

Yes we can pre fill unbounce form box if we are already filled some value on other source.We don’t need to ask to user again to fill the value twice.I have done this before with many clients.Thanks

How about capturing the data though? There is nothing to pre-fill if you cannot capture. e.g. user fills out step one which includes email and name and goes to step two and leaves the form.

I realize you cannot get step one data to unbounce but has anyone figured out how to post data to some other source so you can send the user an email (now that you have their email address) with a link to the form where email and name is prefilled.

The key is data capture.

Thanks in advance.

yes, but we can save previous step data by using cookies. whenever a user will go to another source, we can get the cookies data…

Userlevel 7
Badge +3

Hey @Nick_Abramovich,

The key is actually consent. You might get into trouble if you start using data the user hasn’t actually submitted. So be careful.

To answer you question, you have to do an AJAX POST to where you want the data to go.

Best,
Hristian

yes .Ajax is the other way to send data to other source.

thanks for doing this, i found one problem installing it. When I downloaded the zip the JS files are not on Notes so it´s not easy to copy paste them if you dont have a JS reader as I do.

would you send the content of those JS files to try your solutions?

thanks!

https://community.unbounce.com/t/multi-field-multi-step-form/13718

http://unbouncepages.com/multipul-from-testing/

Hello, Noah. Can you help me ? Why the nest button dose not working? Thank you

How can I make 2 form fields appear?

Userlevel 5
Badge +4

Hello Kyle,

use this script : Multi-Field, Multi-Step Form 🔥

Amazing! Took me 2 minutes and it works like magic! Thanks a lot Noah!

One question I have (and if the answer is NO, then we won’t be able to use your code, unfortunately).

Is it possible to capture the user data even before he submit the form?

We have 3 steps:

  1. Email
  2. Name
  3. Phone

I want him to enter Email, hit “next” and then if he left the website, we’ll still have his email.

That’s super important, otherwise all the steps and clicks can actually reduce conversions.

Userlevel 5
Badge +4

Hello @davigol.

As said by someone a few post earlier it’s not possible with this script.
You need AJAX and there is also a question of consent.

@Noah or someone on the unbounce team, maybe you should add these information on the script instructions ?

Hello - I have followed the above instructions and all works well apart from my privacy policy and the box don’t appear, meaning they can’t complete the form. Is this something I’m doing wrong? Thanks!

Hi, I am trying to build a drop down menu where each drop down option leads to a different website. I have been trying to work with this Java script but when I publish and run the website, the different drop down options just keep bringing me back to the same website the dropdown menu is on in the first place. I am also unsure as to what to input in the Form Confirmation field, as there is no one page I want the page to lead to, but three.

Any help would be appreciated!

I can do this and already done such work.lets talk on Skype newtechguru4563@gmail.com

Hi Caroline,

I’ve tried implementing your code on my form but unfortunately it doesn’t seem to be implementing to the form when I preview it.

Would anyone be able to assist me here on what I may be doing wrong?

Thanks!

Reply