Hello, I know there is a dynamic form thank you functionality in the Forms 2.0 builder where you can set the thank you page via form field values, but I was wondering how you can do it via script in the Marketo onSuccess function? The reason being, we have parameters building the thank you page URL based on the form entries and we cannot do that in the form builder.
Here is our script. Pretty much I want a dynamic "location.href" URL that varies based on what the user enters in the Postal Code field.
If it's one set of zip codes, go to a specified URL. If it's another set of zip codes, go to a different specified URL. And if the value typed in doesn't meet these 2 criteria, just go to a generic thank you page.
Any help would be appreciated! THANK YOU!
form.onSuccess(function() {
var appendFirstName = $('#FirstName').val();
var appendLastName = $('#LastName').val();
var appendEmail = $('#Email').val();
var appendPhone = $('#Phone').val();
var appendStreet = $('#Address').val();
var appendCity = $('#City').val();
var appendState = $('#State').val();
var appendZip = $('#PostalCode').val();
location.href = "OUR THANK YOU PAGE URL HERE" + '?first=' + appendFirstName + '&last=' + appendLastName + '&email=' + appendEmail + '&phone=' + appendPhone + '&street=' + appendStreet + '&city=' + appendCity + '&state=' + appendState + '&zip=' + appendZip;
return false;
});
var appendFirstName = $('#FirstName').val();
var appendLastName = $('#LastName').val();
Please don't write code like this: (a) it won't work, because you shouldn't looking at input values but the fields object that's already passed to onSuccess, and (b) it's really hard to maintain (even if it did work) and makes my head hurt.
onSuccess always gets 2 arguments:
If you want to serialize all the form values
Just map the fields object:
form.onSuccess(function(fields,tyUrl){
var excludeFields = ["munchkinId","formid","_mkt_trk"]; // skip internal fields
var fieldsUrlEncoded = Object.keys(fields)
.filter(function(field){
return excludeFields.indexOf(field) == -1
})
.map(function(field){
return [field,fields[field]]
.map(encodeURIComponent)
.join('=');
})
.join('&');
// fieldsUrlEncoded is now your query string with the fields
and you can switch based on whatever you want:
// continued from above
var zipBasedTYUrls = [
{
zipSet: ["10009","10006"],
baseUrl : "https://www.example.net/thanks-for-staying-east"
},
{
zipSet: ["90064"],
baseUrl : "https://www.example2.com/thanks-for-going-west"
}
]
var zipMatches = zipBasedTYUrls
.filter(function(zipInfo){
return zipInfo.zipSet.indexOf(fields.PostalCode) != -1
}),
zipTYUrl = zipMatches[0].baseUrl;
document.location.href = zipTYUrl + '?' + fieldsUrlEncoded;
return false;
});
Thanks! I appreciate the assist! I still consider myself a scripting newbie - the code does actually work and I do need to generate a thank you link in this format (URL+specific form-inputted parameters), because the thank you page contains a Docusign link where we're pre-populating a contract with what they filled out on the form, and it's URL parameter-dependent.
So the thank you page does need to be specific: location.href = "http://website.com/thank-you" + '?first=' + appendFirstName + '&last=' + appendLastName + '&email=' + appendEmail + '&phone=' + appendPhone + '&street=' + appendStreet + '&city=' + appendCity + '&state=' + appendState + '&zip=' + appendZip;
Would your script above still do that?
the code does actually work
It only seems to work because you haven't tested it enough.
Try it on a page with multiple forms, or with elements that aren't <input type="text">, or with elements that don't have a predictable #id (the field name for a form input isn't the id attribute, it's the name attribute).
When I say code "doesn't work" I usually mean "doesn't account for the real-world environments in which it could be run." That doesn't mean there aren't contrived/lucky cases in which it appears to work, but the moment you "shake the tree" it breaks without explanation (and without throwing a visible error).
On the other hand, if your code popped up a (deliberate) alert when it encountered fields other than text fields, or refused to run when there were multiple forms on the page, then I wouldn't say it "doesn't work" since it would be aware of its restrictions.
Anyway, beyond those issues, it simply isn't necessary to do what you're doing. The first argument passed to the Forms API onSuccess method (the variable named fields in my code above) is always a JS object with all the fields, and their values, exactly as posted to the server by that specific form. If you try to get the equivalent values from the DOM, that will only lead to headaches + errors. Remember, Marketo forms are not HTML <form>s, they're JavaScript objects with a code-mediated relationship to <form> elements. Thus you should use the JS API provided and not try to go around it.
Would your script above still do that?
Of course. I didn't change the final output (the URL-encoded string with the form data).
I changed the reliability of getting the final output in multiple real-world cases and made the code more maintainable (it automatically adjusts to the fields on your form, without restating them in the code, which is prone to error).
The function that sets fieldsUrlEncoded maps over the fields object to turn it into the URL-encoded string. Getting fluent with JS array methods like forEach, filter, map, reduce, some, and every -- and the venerable split and join -- is the first step to better code.
Thank you! Appreciate your insight!
So one more question for you... if I needed a default page for when a zip code doesn't match the 2 criteria mentioned above, how is that coded in? I'm used to "if/then, else" statements.
Thanks!
if I needed a default page for when a zip code doesn't match the 2 criteria mentioned above, how is that coded in? I'm used to "if/then, else" statements.
Add a wildcard set at the end.
var zipBasedTYUrls = [
{
zipSet: ["10009","10006"],
baseUrl : "https://www.example.net/thanks-for-staying-east"
},
{
zipSet: ["90064"],
baseUrl : "https://www.example2.com/thanks-for-going-west"
},
{
zipSet: ["*"],
baseUrl : "https://www.example2.com/thanks-wherever-you-are"
}
]
var zipMatches = zipBasedTYUrls
.filter(function(zipInfo){
return zipInfo.zipSet.indexOf(fields.PostalCode) != -1 || zipInfo.zipSet.indexOf("*") != -1
}),
zipTYUrl = zipMatches[0].baseUrl;
Because filter() runs from top to bottom, if anyone reaches the wildcard set that's because they didn't match any of the earlier ones.
This ended up working beautifully! Thank you so much!
Great!