Clearing lead fields based on unanswered form questions

Another one to file under “More tricky than it seems.” As Marketo users MS and JI note in these posts, when a lead doesn't click any of the available options for a form field, the form sends an empty string value to the server, and such a response is considered a no-op — that is, the existing value on the lead will be preserved.

(By the way, when it comes to checkboxes and radio buttons, standard HTML forms do not post anything at all — not even the field name, let alone an empty value — in such cases. So we're starting off on a proprietary foot here. As I've mentioned in other posts, though Forms 2.0 uses standard HTML inputs, there's much more going on under the hood.)

So take a form like this:

ss

If submitted as-is, neither Product Interest nor Other Interest will be updated in Marketo. This is the case whether the lead was deliberately omitting either of those non-required fields, or simply didn't look at them.

On the other hand, if Product Interest has A checked on the form, and the lead's current value in the Marketo database is B — or even if the current value is D, which isn't exposed on this particular form — the stored value will be updated to simply A.

In other words, not selecting a value is the same as if the field weren't on the form, while selecting any value means a full override of all existing values.

I don't mean this is counterintuitive, exactly. It's just… the way it is. (Best to abandon intuition when dealing with any form-to-database technology and just learn product-specific rules!)

Adding a literal “not-answered” answer

Now, suppose you want all questions to represent a progressive action, rather than no action. That is, allow the lead to indicate they have no product interest at all, rather than that they have no new product interest. With the default behavior, this is impossible.

One workaround is to reframe the questions with options that specifically say None at this time, N/A, etc. and make the fields required:

ss

I'm not a big fan of the UX, though, as the rule of thumb with forms is it should take leads as few clicks/taps as possible to submit data. Yes, you could make the None at this time options selected by default, but that seems defeatist and bad marketing juju (IMO).

(Granted, the Product Interest in this case should probably be required, since if they have no product interest they probably shouldn't be filling out the form! But I'm working off the sample form MS linked to, so I don't want to question the premise. And even if that particular field can be changed to required, others should be optional and thus fall into the problem area.)

Making Unanswered into an answer

In cases like MS's, the desired balance of UX and data management is to [a] allow the lead to ignore non-required questions, but [b] transform that non-response into a progressive None response behind the scenes, clearing the field in Marketo.

In a moment, we'll see how that's done.

Sidebar: the magic value “NULL”

If you don't know already, the string value “NULL” has special meaning in Marketo.

If you have SQL experience, this isn't the same as SQL's NULL. In SQL, NULL (note the lack of quotation marks) is a reserved keyword with special meaning. Without quotes, it's special; with quotes, ‘NULL’ is like any other string. So, with apologies for the digression, you can have a SQL CHAR(4) NOT NULL that holds the string NULL. For the same reason, the condition IF 'NULL' IS NULL is always false, since it's comparing a 4-character string to the special keyword representing “no value.”

Anyway, back to Marketo-world. In Marketo, the string “NULL” is a reserved value. It's pretty strange to have values be reserved anywhere in computing (those inclined to debate could point out use strict in JavaScript, I guess).

Yet because of the primitive ways marketers access the Marketo database (i.e. not via an API and/or language which can distinguish between “NULL”, ‘NULL’ and NULL) and also (I presume) a failsafe to make sure you really meant to clear a field, “NULL” is used to clear a field in flows. And it's used for the same purpose in form fields.

(If you're following, this means a Marketo field can't actually have the 4-character value “NULL” for what that's worth.)

Wiring up your form for clearing fields

Despite my typically long preamble, this is actually pretty easy.

In Form Editor, add an additional value to your Checkboxes or Select field for the Stored Value “NULL” :

ss

ss

Note that in the second example (the Select) the Display Value is actually a single space, not empty. This is to compensate for a visual quirk of the forms library.

Then, add form CSS to hide any <INPUT> or <OPTION> tag that has that special value, and any associated <LABEL>:

INPUT[type="checkbox"][value="NULL"],
OPTION[value="NULL"],
INPUT[type="checkbox"][value="NULL"] + LABEL {
	display: none !important;
}

And add some simple Forms 2.0 API JS:

MktoForms2.whenReady(function(form) {
	const arrayify = getSelection.call.bind([].slice);
	
	let formEl = form.getFormElem()[0],
		  NULL_PLACEHOLDER_STOR = 'INPUT[type="checkbox"][value="NULL"],INPUT[type="radio"][value="NULL"], OPTION[value="NULL"]';

	form.onSubmit(function(form) {
		let currentVals = form.getValues(),
			  nullPlaceholderEls = formEl.querySelectorAll(NULL_PLACEHOLDER_STOR);
		
		let mktoFieldsObj = {};

		arrayify(nullPlaceholderEls)
		.map(function(itm) {
			return itm.name || itm.parentNode.name
		})
		.forEach(function(fieldName) {
			if (!currentVals[fieldName]) {
				mktoFieldsObj[fieldName] = "NULL";
			}
		});

		form.setValues(mktoFieldsObj);
	});
});

The JS is straightforward:

  • hook the form submit
  • get all form options/checkboxes with a value of "NULL" (i.e. the same elements hidden via CSS)
  • loop over 'em to find out the fieldname each one is associated with
  • if that fieldname currently has an empty/falsy value (meaning none of the visible options has been clicked) then change the value to literal "NULL"
  • continue with submit

Voilà, a form that'll clear values in the Marketo database when no options are selected:

ss

Enjoy!