Reposition Fields in a Marketo Form

Marketo Employee
Marketo Employee

While the Marketo form builder is quite powerful, there are some edge cases where it doesn't produce quite the result that you're looking for.  A common request is to reposition fields after the progressive profiling box, which is a capability that isn't currently available natively.  Fortunately, with some javascript tweaks, we can reposition fields freely.  Let's take a look at the code:

/*

jQuery must be loaded on the page

use moveMktoField to position the field designated by FieldName relative to the field designated by pivotName

*/

function moveMktoField(fieldName, pivotName, beforeOrAfter){

  //find the label element for the field which we want to move

  var labelForFieldToMove = $('[for="' + fieldName + '"]');

  //find the label element for the field we want to position relative to

  var labelForPivot = $('[for="' + pivotName + '"]');

  //get the mktoFormRow parent of each

  var fieldToMove = getParentWithClass(labelForFieldToMove, "mktoFormRow");

  var pivot = getParentWithClass(labelForPivot, "mktoFormRow");

  //insert the field before or after the pivot based on the setting

  if (beforeOrAfter == "before"){

       fieldToMove.insertBefore(pivot);

  } else if (beforeOrAfter == "after"){

       fieldToMove.insertAfter(pivot);

  } else {

       console.log("argument 'beforeOrAfter' must be one of 'before' or 'after'");

       return null;

  }

}

//inserts multiple fields in order where the first in the fields array is adjacent to the pivot, and the last is furthest

function moveMktoFields(fields, pivotName, beforeOrAfter){

  moveMktoField(fields[0], pivotName, beforeOrAfter);

  for ( i = 1; i < array.length; i++ ){

       moveMktoField(fields[i], fields[i - 1], beforeOrAfter);

  }

}

function getParentWithClass(elem, withClass) {

  //Check the parent to see if it has the desired class

  if ( elem.parent().hasClass(withClass) ) {

       return elem.parent();

  } else {

       //if not, call self recursively on the immediate parent

       return (getParentWithClass(elem.parent(), withClass) );

  }

}

With the above, we can use the moveMktoField function to reposition one field relative to another.  You can also use moveMktoFields to move the fields as a group when you pass an array of field names to it.  Click here to see a live demo, moving First Name after Last Name.

2162
43
43 Comments
Marketo Employee

Those links don't go anywhere right now.  You might be calling with a wrong field name since that error indicates that the call stack size is being exceeded by having too many things on the stack.  getParentWithClass is recursive so this could happen.  Should probably add a base case to avoid this.

Anonymous
Not applicable

Hi Ryan - I'm trying to use your code since it's the shortest in this thread and I'm not technical. At all.

I want to move my "global opt in" button to the bottom of my progressive profiling. The field name is "Global Opt In" so I placed it into the code (see italicized areas). However, there are other items like fieldname.length and .mktoformrow that I'm not sure about - do I need to put something into this? If so, where do I find that info?

function moveMktoFieldsToBottom(Global Opt In) {

  for ( i = 0; i < fieldNames.length; i++ ){

    var elementToMove = $('[for="' + Global Opt In[i] + '"]').parents(".mktoFormRow");

    try {

      elementToMove.insertBefore(".mktoButtonRow");

    } catch(err) {

      console.log("Error: " + err.message);

    }

  }

}

Anonymous
Not applicable

Hey Christina - you're almost there. You can use the code as-is from my original post, but all that does is define the function. You also need to call the function, and essentially just feed the names of your field(s) into the function. You'll need to go find the API name for Global Opt In (probably something like globalOptIn - you can find this in your field management settings). So, in your code, you will both define the function:

function moveMktoFieldsToBottom(fieldNames) {

  for ( i = 0; i < fieldNames.length; i++ ){

    var elementToMove = $('[for="' + fieldNames[i] + '"]').parents(".mktoFormRow");

    try {

      elementToMove.insertBefore(".mktoButtonRow");

    } catch(err) {

      console.log("Error: " + err.message);

    }

  }

}

And then you need to call it like this:

MktoForms2.whenReady(function(form){

    moveMktoFieldsToBottom(['globalOptIn']);

});

The way the code works is that you can tell it a list of the field names (should you have several) that you want to move to the bottom. In Javascript, lists are contained within brackets - this example doesn't look much like a list because there's only one value in it. But say you also wanted to move the email to the bottom for some reason, the function call would be something like:

MktoForms2.whenReady(function(form){

   moveMktoFieldsToBottom(['globalOptIn','email']);

});

The function will be triggered when the form is "ready" (that's the whenReady stuff), then cycles through each of these values and moves it to the bottom of the form, right above the button row.

Make sure that you have included the forms 2.0 javascript code before that function is called, or else the browser will not know what MktoForms2 means:

<script src="//app-ab11.marketo.com/js/forms2/js/forms2.min.js"></script>

Hope that helps!

Anonymous
Not applicable

Huh, I must be doing something wrong. I put this code exactly as is below into my LP on top of my footer (by adding an HTML element and dragging it there). I tried to have opening and closing scripts just once, but it didn't work since I added the script below. Any suggestions for what I'm doing wrong?

<script>

function moveMktoFieldsToBottom(globalOptIn) {

  for ( i = 0; i < fieldNames.length; i++ ){

    var elementToMove = $('[for="' + globalOptIn[i] + '"]').parents(".mktoFormRow");

    try {

      elementToMove.insertBefore(".mktoButtonRow");

    } catch(err) {

      console.log("Error: " + err.message);

    }

  }

}

</script>

<script src="//app-ab11.marketo.com/js/forms2/js/forms2.min.js"></script>

<script>

MktoForms2.whenReady(function(form){

    moveMktoFieldsToBottom(['globalOptIn']);

});

</script>

Anonymous
Not applicable

You've modified the original function - just use it as-is from my post. Note the differences in bold. Here's yours:

function moveMktoFieldsToBottom(globalOptIn) {

  for ( i = 0; i < fieldNames.length; i++ ){

    var elementToMove = $('[for="' + globalOptIn[i] + '"]').parents(".mktoFormRow");

    try {

      elementToMove.insertBefore(".mktoButtonRow");

    } catch(err) {

      console.log("Error: " + err.message);

    }

  }

}

Here's mine:

function moveMktoFieldsToBottom(fieldNames) {

  for ( i = 0; i < fieldNames.length; i++ ){

    var elementToMove = $('[for="' + fieldNames[i] + '"]').parents(".mktoFormRow");

    try {

      elementToMove.insertBefore(".mktoButtonRow");

    } catch(err) {

      console.log("Error: " + err.message);

    }

  }

}

Anonymous
Not applicable

It's magic! I guess I'm confused because there's nothing in this code that says "take this specific field and move it", how does it know I wanted Global Opt in to move instead of first name?

Anonymous
Not applicable

This line tells the function what to move:

moveMktoFieldsToBottom(['globalOptIn']);

Level 2

Hi Ryan,

I am struggling to get this to work. Here is my from: Test Form

I want to move the field "ZOpComplianOptin" to the bottom. I do have a visibility rule set for when country = canada.

Here is my code:

<script src=“https://s3-us-west-2.amazonaws.com/aws-marketo-m2-resources/js/mkto-field-placement-pp/FieldPlacemen...”</script> <script src="https://s3-us-west-2.amazonaws.com/aws-marketo-m2-resources/js/mkto-field-placement-pp/Marketoforms2..."></script> <script> MktoForms2.whenReady(function(form){     moveMktoFieldsToBottom(['zOPComplianceOptin']); }); </script>

Thanks!

Level 10 - Community Moderator

Wouldn't bother with this method. Use my code at MktoForms2 :: Override Field Order . Open a new thread if you have questions.

Hi Ryan,

My name is Rajesh. I tried implementing your code it worked in edit mode of landing page, but when i see it in browser, the field does not moves.

What can be the reason. Here is my code for your reference.

<script>

function moveMktoFieldsToBottom(fieldNames) {

  for ( i = 0; i < fieldNames.length; i++ ){

    var elementToMove = $('[for="' + fieldNames[i] + '"]').parents(".mktoFormRow");

    try {

      elementToMove.insertBefore(".mktoButtonRow");

    } catch(err) {

      console.log("Error: " + err.message);

    }

  }

}

</script>

<script src="//app-sj04.marketo.com/js/forms2/js/forms2.min.js"></script>

<script>

MktoForms2.whenReady(function(form){

    moveMktoFieldsToBottom(['Optin']);

});

</script>