Standard ask: “Can we ‘prime’ a form with selections based on the query string?”

 

That is, if the query string includes “GC5000 series” and “GC3000 series,” check those boxes automatically, letting the user change those selections if desired:

SanfordWhiteman_0-1741157002528.png

 

We sure can, with a few lines of JS! The question is what does it mean for a query string to “include” multiple field values?

 

The standards-based way: multiple params

The standard[1] — and strongly recommended — way is to include the same query param multiple times, clearly indicating a multivalued param:

productInterest=GC5000+series&productInterest=GC3000+series

 

Frustratingly, lots of people don’t know about that, probably because their URL parser is poorly written and doesn’t understand it. But since URLSearchParams is available everywhere now, that’s no excuse:

const currentURL = new URL(document.location.href);
const initialProductInterest = currentURL.searchParams.getAll("productInterest");
// initialProductInterest is an array with zero or more values

 

And Forms 2.0 already supports that array:

MktoForms2.whenReady(function(readyForm){
  readyForm.setValues({
    productInterest: initialProductInterest
  });
});

 

The non-standard way: semicolon-delimited

When people don’t know the standard way, they decide on a sub-delimiter character(s) to separate values, like:

productInterest=GC5000+series;GC3000+series
productInterest=GC5000+series,GC3000+series
productInterest=GC5000+series|GC3000+series

Even seen this unholy format:

productInterest=*!GC5000+series!*+*!GC3000+series!*

 

All that just to avoid using the standard!

 

The Forms 2.0 API supports the first of these, the semicolon. Therefore these 2 snippets have the same effect:

MktoForms2.whenReady(function(readyForm){
  readyForm.setValues({
    productInterest: ["GC5000 series","GC3000 series"]
  });
});
MktoForms2.whenReady(function(readyForm){
  readyForm.setValues({
    productInterest: "GC5000 series;GC3000 series”
  });
});

 

Remember, an arbitrary sub-delimiter means that character can’t appear within a value. Marketo sees ; as special, and there’s no way to escape it — it can’t be made non-special. If a field is multivalued[2], tl;dr will represent the values tl and dr.

 

If the query string is known in advance to be semicolon-flavored, it’s similarly easy to get and set the value:

const currentURL = new URL(document.location.href);
const initialProductInterest = currentURL.searchParams.get("productInterest");

MktoForms2.whenReady(function(readyForm){
   readyForm.setValues({
      productInterest: initialProductInterest
   });
});

 

Both flavors at once

I was interested in supporting both methods simultaneously. Say your existing URLs use semicolons, but all new URLs will use multiple params, and you don’t want anything to break.

 

Turns out to be pretty easy:

const currentURL = new URL(document.location.href);
const initialProductInterest = currentURL.searchParams.getAll("productInterest");
const initialProductInterestCoerced = initialProductInterest.flatMap( itm => itm.split(";") );

MktoForms2.whenReady(function(readyForm){
   readyForm.setValues({
      productInterest: initialProductInterestCoerced
   });
});
  • first, getAll() parameter values
  • within that array of values, there might be semicolon-delimited sub-values, which we split() out, creating another (temporary) dimension
  • finally, flatten the array so it’s single-dimensional and ready to be passed to setValues()

 

So the array might initially be ["apples;oranges", "cranberries"] and we transform it to ["apples", "oranges", "cranberries"]. Conversely, if getAll() returns ["cranberries", "grapes"] we keep it that way; an empty array [] also stays empty.

 

flatMap is a cool method to have in your back pocket!

 

Be aware of whenReady vs whenRendered

The examples use whenReady on the assumption the field is always shown. If the field is subject to Visibility Rules, use whenRendered instead, plus dirty checking logic to avoid overwriting the person’s custom selections. More on dirty checking in a future post.

 

Notes

[1] That’s how HTML forms work when multiple inputs have the same name. For example, if the 2 bottom checkboxes are checked:

<form method="POST">
   <label><input type="checkbox" name="pw_cc__ProductInterest__c" value="GC1000 series">GC1000 series</label>
   <label><input type="checkbox" name="pw_cc__ProductInterest__c" value="GC5000 series">GC5000 series</label>
   <label><input type="checkbox" name="pw_cc__ProductInterest__c" value="GC3000 series">GC3000 series</label>
   <input type="submit" value="Submit">
</form>

 

The POST payload will be:

productInterest=GC5000+series&productInterest=GC3000+series

 

Standard forms pass + for space. When constructing URLs by hand, you can use either + or %20: both are understood by URLSearchParams and any other URL parser worth its salt.

 

[2] If a string field is always read/written as a single value, then there’s no problem if it has a literal ;.