Behold a very simple Marketo form that auto-fills 3 familiar fields from the current query string:

(Of course this setup is wildly insufficient for multitouch tracking, but that's another matter!)

Now, a couple of questions:

1. What will be the value of Last UTM Campaign if this is the URL?

https://www.example.com/mypage?utm_campaign=2022Q2-waterparks&utm_campaign=2022-06-outdoors

https://www.example.com/mypage?utm_campaign=2022Q2-waterparks&utm_campaign&utm_campaign=

Both mistakes are quite possible in the real world. You might include a {{my.utm params}} token in the URL as well as adding the param in Email Editor, not realizing it’ll be a duplicate. (In fact, someone did exactly that, leading to this blog post!)

2022Q2-waterparks,2022-06-outdoors

And #2 (note the trailing commas):

2022Q2-waterparks,,

So the outcome is consistent: multiple params with the same name become an Array, which is then stringified using the default JS behavior (running toString() on an Array is akin to join(",")).

No parameter is ever ignored, even when it appears to have an undefined or empty value.

This behavior is formalized in the URLSearchParams standard (though even before the standard came out, custom URL parsers typically did the same thing):

The getAll(name) method steps are to return the values of all name-value pairs whose name is name, in this’s list, in list order, and the empty sequence otherwise.

(In a JS implementation, “list” means Array.)

## Multiple occurrences are perfectly valid

To be clear, multiple params with the same name are valid — the standard wouldn’t have the method getAll() if they weren’t!

But there’s a difference between purposely sending a list of values to your server and accidentally creating a valid URL which has an unwanted outcome.

If you have the Whoops! moment that you sent out a link with duplicate params, and you don’t want to have weird stuff in your database as a result, here’s a little emergency Forms 2.0 JS you can roll out.

MktoForms2.whenReady(function(mktoForm){

let trimCommasFromFields = ["lastUTMCampaign"],
alsoRemoveDuplicates = true,
keepOnlyNth = false;

/* no need to mod below this line */

let currentValues = mktoForm.getValues();
let mktoFieldsObj = {};

trimCommasFromFields.forEach(function(fieldName){
let allValues = currentValues[fieldName].split(",");

let simplifiedValues = allValues.reduce(function(acc, value, idx){
if(
( value !== "" ) &&
( alsoRemoveDuplicates === false || acc.indexOf(value) == -1 ) &&
( keepOnlyNth === false || idx == keepOnlyNth )
) {
acc.push(value);
}
return acc;
},[]);

mktoFieldsObj[fieldName] = simplifiedValues.toString();
});

});

Rather than reparsing the URL (which requires an additional library for cross-browser compatibility) the code waits for the Forms 2.0 library to grab and parse it, then simplifies a value like ,,2022Q2-waterparks,, to just 2022Q2-waterparks.

You can also set alsoRemoveDuplicates to dedupe values if they appear more than once, so you don’t end up with a value like:
And set keepOnlyNth to keep only the Nth (0-based) occurrence of the same name. For example, if you know the first occurrence was messed up...
... then set keepOnlyNth to 1.