pasted image 0.png

Common Form Questions and Answers

Casey_Grimes
Level 10
Level 10

Over the years here at the Marketing Nation, I've seen many basic form questions come over and over again with common functionalities. Just so there's a central repository of how to handle these requests, I've compiled a quick post that goes over form functions.

Do note that the vast majority of these response require you to know a little bit of HTML and JavaScript (or work with someone who can deploy JavaScript on your page) and are globally scoped—include the script and they'll fire on any form that's on the same page as the form. If you plan to use multiple forms on one page, you may need to alter these snippets to target specific forms.

Frequently Asked Questions

My team is asking me about form values being prefilled with the forms we have on our site. How do I do this?

Marketo's form code does not support prefill in places outside of Marketo landing pages due to security concerns. The only non-API way to use things like prefill is to create an iframe (and ideally something like pym.js to handle the iframe itself.)

How do I record Google Analytics events upon form submit?

My preferred method for doing this is simply to do a slight modification of your embed code to include a formName variable, so you'd go from something like

<script>MktoForms2.loadForm("//app-abc.marketo.com", "123-ABC-456", 1);</script>

to

<script>MktoForms2.loadForm("//app-abc.marketo.com", "123-ABC-456", 1); var formName = "Contact Us form";</script>

From there, it's simply a manner of adding the following to your site's overall JavaScript:

<script type="text/javascript">

MktoForms2.whenReady(function(form) {

form.onSuccess(function(vals, page) {

ga('send', 'event', {

eventCategory: 'Marketo Form',

eventAction: 'Form Submission',

eventLabel: formName,

hitCallback: function() {

document.location.href = page;

};

});

return false;

});

});

</script>

Do note that if you're using User ID tracking that you may need to explicitly set it in the onSuccess function before sending the event.

How do I show a thank you message on the same page upon a form being submitted rather than redirecting to a new page or just showing the form again?

You'll need to make a div containing the messaging you want to display and place it in the same parent element as your form, similar to the following:

<div class="container">

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

<form id="mktoForm_27"></form>

<script>MktoForms2.loadForm("//app-abc.marketo.com", "123-ABC-456", 1);</script>

<div id="confirmation" aria-hidden="true" style="display:none;">

<p>This is a sample thank you message. Thanks for viewing.</p>

</div>

</div>

Then, simply include the following in your site's JavaScript:

<script type="text/javascript">

MktoForms2.whenReady(function (form){

form.onSuccess(function(vals, page){

form.getFormElem().hide();

var confirm = document.getElementById('confirmation');

confirm.style.display = 'inline-block';

confirm.setAttribute('aria-hidden', false);

confirm.focus();

return false;

});

});

</script>

You can also get creative with this and use a mktoText area in your Marketo landing page template to allow dynamic thank you messages to be added without needing a second page!

How do I block certain domains from filling out my forms?

First off: please, don't do this. There are few reasons to do this, especially because most people want to block free domains or certain characters. There are quite a few people, especially in technical industries, who will use disposable addresses or character separators for filtering early in your funnel. Irritating people who want to engage with you, regardless of their email, is not going to help much. However, if you must:

<script type="text/javascript">

(function (){

// Please include the email domains you would like to block in this list

var invalidDomains = ["@gmail.","@yahoo.","@hotmail.","@live.","@aol.","@outlook."];

MktoForms2.whenReady(function (form){

form.onValidate(function(){

var email = form.vals().Email;

if(email){

if(!isEmailGood(email)) {

form.submitable(false);

var emailElem = form.getFormElem().find("#Email");

form.showErrorMessage("Must be Business email.", emailElem);

}else{

form.submitable(true);

}

}

});

});

function isEmailGood(email) {

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

var domain = invalidDomains[i];

if (email.indexOf(domain) != -1) {

return false;

}

}

return true;

}

})();

</script>

How can I improve email data quality entered from forms?

I like a little script called Mailcheck, which provides suggestions when people misspell email addresses. Include jQuery and mailcheck.js on your page (or reference it via cdnjs) and then use the following:

<script type="text/javascript">

MktoForms2.whenReady(function (form){

var domains = ["aol.com", "att.net", "comcast.net", "facebook.com", "gmail.com", "gmx.com", "googlemail.com","google.com", "hotmail.com", "hotmail.co.uk", "mac.com", "me.com", "mail.com", "msn.com","live.com", "sbcglobal.net", "verizon.net", "yahoo.com", "yahoo.co.uk", "email.com", "games.com", "gmx.net", "hush.com", "hushmail.com", "icloud.com", "inbox.com","lavabit.com", "love.com" , "outlook.com", "pobox.com", "rocketmail.com" ,"safe-mail.net", "wow.com", "ygm.com", "ymail.com" , "zoho.com", "fastmail.fm","yandex.com","iname.com","bellsouth.net", "charter.net", "cox.net", "earthlink.net", "juno.com","btinternet.com", "virginmedia.com", "blueyonder.co.uk", "freeserve.co.uk", "live.co.uk","ntlworld.com", "o2.co.uk", "orange.net", "sky.com", "talktalk.co.uk", "tiscali.co.uk","virgin.net", "wanadoo.co.uk", "bt.com", "sina.com", "qq.com", "naver.com", "hanmail.net", "daum.net", "nate.com", "yahoo.co.jp", "yahoo.co.kr", "yahoo.co.id", "yahoo.co.in", "yahoo.com.sg", "yahoo.com.ph","hotmail.fr", "live.fr", "laposte.net", "yahoo.fr", "wanadoo.fr", "orange.fr", "gmx.fr", "sfr.fr", "neuf.fr", "free.fr", "gmx.de", "hotmail.de", "live.de", "online.de", "t-online.de", "web.de", "yahoo.de", "mail.ru", "rambler.ru", "yandex.ru", "ya.ru", "list.ru", "hotmail.be", "live.be", "skynet.be", "voo.be", "tvcablenet.be", "telenet.be", "hotmail.com.ar", "live.com.ar", "yahoo.com.ar", "fibertel.com.ar", "speedy.com.ar", "arnet.com.ar", "yahoo.com.mx", "live.com.mx", "hotmail.es", "hotmail.com.mx", "prodigy.net.mx", "yahoo.com.br", "hotmail.com.br", "outlook.com.br", "uol.com.br", "bol.com.br", "terra.com.br", "ig.com.br", "itelefonica.com.br", "r7.com", "zipmail.com.br", "globo.com", "globomail.com", "oi.com.br"];

var topLevelDomains = ["co.uk", ".ca", "com", "net", "org", "info", "edu", "gov", "mil"];

var selector = '#Email, .mktoEmailField, .mktFormEmail, input[type=email]';

$(selector).on('blur', function(){

$(this).mailcheck({

domains: domains,

topLevelDomains: topLevelDomains,

suggested: function(element, suggestion) {

var $parent = $(selector).parent();

$('.mailcheck-msg', $parent).remove();

$parent.append('<span class="mailcheck-msg">Did you mean <a href="#" class="mailcheck-suggestion">' + suggestion.full + '</a>?</span>');

}

});

$('a.mailcheck-suggestion').on('click', function(){

$(selector).val( $(this).html() );

$(this).parent().remove();

return false;

});

});

});

});

</script>

How do I include links (or other HTML) on a Marketo field label?

This is commonly used to link to terms and conditions, privacy policies and the like on checkboxes. Simply grab the API name of the field you're trying to manipulate and use the following structure:

<script type="text/javascript">

MktoForms2.whenReady(function(form)

{

var termsBox = document.querySelector("[for='acceptTerms']");

termsBox.innerHTML = "Check here to indicate that you have read and agree to the terms of the <a href='privacy-policy-link'>Privacy Policy</a>.";

}

);

</script>

How can I prevent spam entries to my form?

One of the biggest ongoing problems Marketo users who have forms run into is ensuring their forms are free of automated spam. As spam bots have become more sophisticated, traditional honeypot and captcha methods haven’t worked, but at the same time, end users don’t want to have to prove they’re not a robot!

Google introduced the Invisible reCAPTCHA in late 2016 to handle this problem more elegantly, and building the technology into your forms is a straightforward affair. To get started, visit https://www.google.com/recaptcha/admin and fill out the “Register a New Site” section:

pasted image 0.png

Select “Invisible reCAPTCHA” and add any domains you plan on having forms on in the Domains box. Do note that you only need your base domain, so go.example.com and pages.example.com will be covered by example.com. Accept the terms and register. Once you register, you’ll see an area with two keys:

pasted image 0 (1).png

Keep both of these keys handy, because we’ll be using them!

Meanwhile, head over to Marketo and create two fields in Admin->Field Management>: a string called “spamCheck” and a boolean field called “Verified”. These will be used to check the spam challenge and route your records accordingly.

If you don’t have jQuery installed on your page already, make sure you have a copy of jQuery, and then implement the following script after jQuery loads:

<script type="text/javascript">

MktoForms2.whenReady(function (form) {

$( "button[type='submit']" ).addClass( "g-recaptcha" ).attr( "data-sitekey", "YOUR-SITE-KEY" ).attr("data-callback","letsGo");

$.getScript( "https://www.google.com/recaptcha/api.js",);

letsGo = function() {

MktoForms2.whenReady(function (form) {

var v = grecaptcha.getResponse();

form.vals({"spamCheck" : v});

form.submit();

});

};

});

</script>

This will load Google’s reCAPTCHA API on your page. In short, what will happen is that when a user submits your form, the form will quickly call Google’s reCAPTCHA service to check that the submitter isn’t a spam bot. Google then returns a response, which we’ll store in the spamCheck field in Marketo. However, this is only half of the equation: we need to use our private key to check that the response is valid. Thankfully, we can do this with a simple webhook.

Head to Admin->Webhooks> and create a new webhook with the following values:

Webhook Name: ReCAPTCHA Validation

URL: https://www.google.com/recaptcha/api/siteverify?secret=YOUR-SECRET-KEY&response={{lead.spamCheck}}

Request Type: GET

Response Type: JSON

Hit “Save”. From there, hit the “Edit” button next to Response Mappings. For your response attribute, type in success (all lowercase) and for Marketo Field, choose the Verified boolean field you created earlier. The final product should look like the following:

pasted image 0 (2).png

From there, using the reCAPTCHA validation is simple; when you set up a trigger for a form to be processed, you’ll simply call the webhook, wait 1 minute, and then do what you wish with the form fillout:

pasted image 0 (3).png

And that’s all there is to it! Do note that per Google's reCAPTCHA policy, you'll be required to show the reCAPTCHA logo and terms of service. This is added by the script itself by default, but you can change how it appears as needed.




55863
79
79 Comments
SanfordWhiteman
Level 10 - Community Moderator

spam can’t complete to fill out form and we don’t need point 2.

You cannot stop a bot from submitting the form.

reCAPTCHA is not designed to prohibit non-human form posts from going on the wire to the server; it's designed to authenticate form posts on the server side to determine whether they were done by a human.

Yuji_Takamura
Level 2

Sanford Whiteman

Thank you for your quick answer!  Now I understood and will try using invisible reCAPTCHA.

Supporto_BOARD
Level 2

Hi Sanford,

I was able to make the Invisible reCAPTCHA work, but now the issue is how to test it effectively. I can't trick it into thinking I'm a bot (because obviously I'm not), but most of the time I'm not even asked to complete the quiz in order to validate the reCAPTCHA; I tried with dummy data, in incognito mode and by using a proxy, but it still lets me through about 95% of the time no questions asked. Is this normal behavior? Is there a way to test it against bot-like behavior that doesn't require me to actually write a script (mainly because I can't do that )?

My impression is that Google is being a little bit "permissive" with my test fillouts, but maybe it will actually work as intended when the bots will come. I just want to make sure of its strength before an actual bot attack.

Thanks,

Francesco

SanfordWhiteman
Level 10 - Community Moderator

Good question, Francesco.  AFAIK there isn't a way to both get the reCAPTCHA widget to pop up (or not) and force it to fail in a representative fashion.

Of course you can force it to fail from the server's standpoint by adding a random string to the form instead of adding the actual response from the widget. Or of course adding no value to the form at all (which is what a bot would do if it were not aware/didn't care that you were using reCAPTCHA).

Supporto_BOARD
Level 2

So you're saying it's all in Google's hands? During testing, the only thing we could do was to blank the variable in the script that would write Google's response into the Spam Check field, but while Marketo effectively takes this response and acts like it's a bot, in reality this is a false positive because Google is actually throwing the "missing-input-response" error, so the test does not reflect a real-life scenario.

The thing is that we implemented the script with the "form.addHiddenFields" part because I wanted to avoid having to re-edit all forms to include a new field, but this is preventing us to do any action on the field before submitting because the field only gets added and filled out when pressing the button (so I was told by a colleague that worked with me on this).

I don't actually mind letting Google handle it once I know our code is sound and behaves like it should, I'm just a bit wary of putting it on the site before extensively testing it and knowing it does work against most bots.

SanfordWhiteman
Level 10 - Community Moderator

But any test that is expected to fail is inherently synthetic.

Take the EICAR sample virus and GTUBE sample spam messages -- these can tell you if mail protection is working at all but not if other zero-day attacks would be stopped.

To impersonate a bot that doesn't try to fill out the reCAPTCHA at all, you'd submit the form without the field.

To impersonate a bot that tries to fill out the reCAPTCHA with a random string, put a random string in place.

But to impersonate a bot that tries to hack the reCAPTCHA by generating a valid response offline (using AI or something) -- you can't do that because you don't know what vulnerability you're trying to exploit, unless there's a known attack kit out there.

The thing is that we implemented the script with the "form.addHiddenFields" part because I wanted to avoid having to re-edit all forms to include a new field, but this is preventing us to do any action on the field before submitting

I don't see why this would be the case... if you can call form.addHiddenFields then you can call it with a random string instead of the reCAPTCHA-generated response string.

Rick_Galan
Level 1

Thanks so much for your work and guidance on this Sanford!

What have you done about false negatives? Real people failing the invisible recaptcha, getting removed from the flow? Do you have a good process for catching those?

I believe we have issues with some folks going through the form with the recaptcha not loading (probably due to js blockers on their browser?).

Thoughts?

SanfordWhiteman
Level 10 - Community Moderator

Put people in a quarantine list, then age them out after hand-inspection (well, somebody else does the inspection ).

There's no simple solution if you don't require JS to submit the form (and once you don't require JS then you're not requiring reCAPTCHA.)

Note a tracked email link won't work without JS, so they'll never get to the page via email if they have a blanket block on scripts.

Rick_Galan
Level 1

That makes sense. I guess I have to figure out how to add these folks back into a flow after they've been booted. Any pointers? The only thing I can think of is creating a secondary, program-specific logic that runs them back through the flow steps. Would have to do that for each flow though. 😕

SanfordWhiteman
Level 10 - Community Moderator

Right, you'd need a separate "resume" flow for each path you've provisionally kicked them out of.

Or you could set up a webhook that could replay their form submission if you want to them to reenter from the top.