Thank you to all the answers on here, after a day of head scratching I managed to work out how to get this working with vanilla js (using vue). I thought I'd post here to help avoids any poor soul going through the same frustration.
Success/Error js files to be on the same domain
success.js:
logResult({ result: 'success' });
error.js:
logResult({ result: 'error' });
Add these URLs to the "Success Location" and "Error Location" fields in the Pardot Form Handler
Jsonp function
I used vue to build this site so I added the below function to /asses/js/util.js
// Copyright (c) 2017 Ziqiang Li - copied and edited from https://github.com/liziqiang/simple-jsonp-promise/blob/master/src/index.js
// Callback index.
let count = 0;
function jsonp(url, options) {
options = options || {};
const prefix = options.prefix || 'logResult';
const callback = options.callback || 'callback';
const callbackName = options.callbackName;
const params = options.data || {};
const target = document.getElementsByTagName('script')[0] || document.head;
let script;
let timer;
// Generate a unique id for the request.
const id = callbackName || prefix + count++;
function noop() {}
function cleanup() {
// Remove the script tag.
if (script && script.parentNode) {
script.parentNode.removeChild(script);
}
window[id] = noop;
if (timer) {
clearTimeout(timer);
}
}
function serialize(params) {
let param = '';
for (const key in params) {
if (params.hasOwnProperty(key)) {
param += `&${key}=${encodeURIComponent(params[key])}`;
}
}
return param;
}
function handleUrl(url, params) {
if (!~url.indexOf('?')) { url += '?'; }
url += serialize(params);
url = url.replace('?&', '?');
return url;
}
return new Promise((resolve, reject) => {
window[id] = function(data) {
cleanup();
resolve(data);
};
if (!callbackName) {
params[callback] = id;
}
url = handleUrl(url, params);
// Create script.
script = document.createElement('script');
script.src = url;
window.logResult = function(json) {
if (json.result === 'success') {
resolve();
} else if (json.result === 'error') {
reject(new Error('Error'));
}
};
script.onerror = function() {
cleanup();
reject(new Error('Network Error'));
};
target.parentNode.insertBefore(script, target);
});
}
export default jsonp;
Note: the callback function name (logResult) needs to be the same function name that is in your success/error js files
Submit function
Script in my vue component (should be easily transferrable to vanilla js/other frameworks):
<script>
import jsonp from '@/assets/js/util';
export default {
name: 'FormTest',
data() {
return {
firstname: '',
lastname: '',
email: '',
};
},
methods: {
submit() {
const options = {
data: {
firstname: this.firstname,
lastname: this.lastname,
email: this.email,
},
};
jsonp('PARDOT_FORM_HANDLER_URL', options).then(() => {
console.log('success');
}).catch(err => {
console.error(err);
});
},
},
};
</script>