Sanford Whiteman

Why do I see my form fields in the URL, instead of seeing the Thank You page?

Blog Post created by Sanford Whiteman on Mar 12, 2019

A clear symptom of broken custom JS is when you see form fields, in URL-encoded format, in the location bar after clicking Submit:

 

5c886b174c52a500bf5f9c28_fields_in_url_url.png

 

You should get to know the cause on sight: an uncaught error has been thrown in a custom Forms API onSubmit function.

 

To replicate this, just set up an otherwise empty page with your form embed and this purposely bad JS:

 

MktoForms2.whenReady(function(form){
form.onSubmit(function(form){
form.oohlala(); // the property `form.oohlala` will never exist
});
});

 

This code won't throw any early errors on page load, because it doesn't have a syntax error. There's no way for the JS engine to know that form.oohlala will end up being a nonexistent method at runtime, it just adds the onSubmit listener happily onto the form.

 

However, when the form is actually being submitted, Marketo runs your custom onSubmit function. Then the browser gets serious and throws a hard TypeError, as you can see in the Dev Tools console (make sure to check off Preserve Log or you'll miss it people don't realize this behavior is always, without exception, a JavaScript error because they fail to prepare their debugging environment ahead of time).

 

Here's the runtime error:

 

5c886b174c52a500bf5f9c28_fields_in_url_console_error.png

 

But why does a JS error result in fields in the URL?

It's simple. Marketo forms use a true HTML <form> tag (this is A Very Good Thing™) and standard <input>/<select>/etc. elements under the hood.

 

The Forms API, among many other things, is responsible for transforming the standard W3C submit event into an elegant cross-domain POST to your Marketo instance.

 

In an error-free environment, the standard submit is swallowed by the Forms API's robust set of handlers. The event is triggered, but its default action that is, sending fields to the form's action (destination URL) using its method (HTTP method) is turned off. The API's non-default actions take over.

 

But when there's an error thrown within the Forms API listener stack, the form reverts to standard HTML form behavior as the default action doesn't get a chance to be turned off.

 

The Marketo <form> element doesn't have a specific action or method[1], i.e. it looks basically like so:

 

<form>
<input name="Something">
<input name="SomethingElse">
<button type="submit">Submit</button>
</form>

 

The default value for method is GET, and the default value for action is the empty string which represents the current URL. So the effective markup is:

 

<form
method="GET"
action="https://whatever.example.com/the_current_page.html">
<input name="Something">
<input name="SomethingElse">
<button type="submit">Submit</button>
</form>

 

When the button is clicked with this markup, and there's a JS error, the browser reverts to a standard GET of the current URL with form fields in the query string:

 

https://whatever.example.com/the_current_page.html?Something=a%20value&SomethingElse=another%20value

 

Whenever you see this behavior in your browser, realize your forms aren't working at all (even though the form seemingly "posts" somewhere). So fix em!

 

 

 


Notes

[1] Nor does the <button> have the newfangled formaction or formmethod attributes, which would be used if present.

Outcomes