Carly, one thing you can do is have a separate field that is on the form, and then have some logic about how that field affects your true "Consent to Marketing Communications" field. This is what we are doing. Our use case is that if someone consents to communications the first time, but then fills out another form and doesn't check the box, we don't want to change "Consent to Marketing Communications" to false. So any time someone fills out the form on our site, it affects a field called "Consent to Marketing Communications - Web". We have a Smart Campaign so if that field changes to True, we change the regular "Consent to Marketing Communications" to True. But if "Consent to Marketing Communications - Web" changes to False but "Consent to Marketing Communications" is True, we don't change "Consent to Marketing Communications".
We use a similar process to keep the opt-in value persistent if a user doesn't check the opt-in field on subsequent form submits - primarily on our website where we use embedded forms and you can't evaluate the prefill value of another field (like "opt-in date") to determine visibility rules of the main opt-in field.
But I just came across something today that essentially eliminates the need for a "persistent" smart campaign when working with boolean fields. I believe this only works if you use a "checkboxes" field type (not "checkbox") within the forms editor. If you have your field defined something like this:
Where "yes" represents the boolean value of "1" (when the checkbox is ticked), then each time someone fills out another form in the future - but doesn't tick the checkbox - it will remove that value. And thus the need for the "keep field persistent" smart campaign.
BUT, if you instead use "TRUE" for the "checked" value:
...this value will persist - even if the checkbox isn't ticked on future form submits. And now, there's no need for a "keep field persistent" smart campaign.
Right, this is because "yes" triggers a bug in the Form Editor library code but "TRUE" does not...
I’d be interested to learn more about this bug - and the reason for the two different behaviors that occur when yes/TRUE are used.
First, I should've said "library" not "editor" above (now corrected). This isn't a bug in the UI.
It's because of a flawed variation of duck typing.
Contrast these 2 pieces of pseudo-code:
if isBooleanField(myField) then
// do boolean-specific stuff
else if isStringField(myField) then
// do string-specific stuff
vs.
if myField.equals("yes") or myField.equals("no") or myField.equals(true) or myField.equals(false) then
// do boolean-specific stuff
else
// do string-specific stuff
The first take accurately checks the type of the field, regardless of what value it currently holds.
The second take checks if the current value is one of the only allowed boolean values and attempts to infer the type from that. This inference fails to account for the case where the strings "yes" and "no" are used in non-boolean situations. So the code short-circuits and assumes the field is boolean instead of doing a more granular check.
A lot of JavaScript code out there uses this kind of logic, and while most of it still works, there's always a danger zone.
Just for reference/rambling, here's a similar type of code you'll see in the wild:
if (typeof myField.map == "function") {
// myField must be an array or array-like thing, since it has a property 'map' that's a function, and all arrays have 'map' built-in
}
The problem is this only works if all surrounding code obeys the rule Never create a custom function named 'map' to any objects. But this rule can't be enforced, as I can do:
var myField = "Sandy";
myField.map = function() {
alert("see, this is called 'map', but it's not Array#map")
})
and this will pass the above test, but myField is a string.
The correct way to check for an array is
Array.isArray(myField);
That's a built-in function that ensures the type is correct, instead of guessing/intuiting it.
Sometimes, there aren't built-in methods, so you do have to cobble together what amount to a series of duck type checks. Array.isArray doesn't exist in IE8, for example, so you have to do one of those "close enough" checks.
Thank you - I looked into doing something similar to this too. Glad I've not gone too off piste.