Caching the result of a resource-expensive function (think network fetch or giant DOM traversal) for the lifetime of a page makes sense if:
- there may be small differences across runs, but users wouldn’t expect real-time updates, or
- there would be significant differences across runs, yet it’s so expensive and bad for UX (and/or health of your back end) that the lesser of two evils is keeping the initial value
On the other hand, permacaching an extremely cheap operation that’s known to give significantly different results during the same user session is bad.
Unfortunately, the Marketo forms library does the bad thing in one specific area.
The _mktoReferrer
is cached when forms2.min.js
is loaded — before forms themselves are loaded — and all forms use that cached value. Reading document.location.href
is as cheap as you can get, but the lib insists on only doing it once.
The _mktoReferrer
becomes the all-important Referrer constraint in Smart Lists. That’s how we know the page someone was on when they submitted an embedded form.
For a multi-page site — I’d guess 85%+ of corporate brochure sites are multi-page, not sure though! — caching is fine, because a new main document loads when you navigate. Thus forms2.min.js
reloads and reads the new document.location.href
.
But single-page applications (SPAs), by definition, change content and update the Location bar without loading a new document. In this case, forms2.min.js
will not load again, which is a problem.
With an SPA, the displayed and business-logical URL can change from https://www.example.com/first-product
to https://www.example.com/schedule-meeting
to https://www.example.com/totally-different-product
but the Referrer for all forms will be https://www.example.com/first-product
. This fundamentally breaks attribution!
(It’s confusing to troubleshoot, too. If someone clicks the browser’s reload ⟳ button when on https://www.example.com/totally-different-product
, that becomes the new main document and the Referrer changes accordingly. That’s how you get reports like “It randomly doesn’t work” when it’s not random, except in the sense that across a wide audience, end users do fundamentally different things.)
Get the code
It’s easily fixed with a little JS:
MktoForms2.whenReady(function(readyForm){
const nativeGetValues = readyForm.getValues;
readyForm.onSubmit(function(submittingForm){
submittingForm.getValues = function(){
const values = nativeGetValues();
Object.defineProperty(values, "_mktoReferrer", { value: document.location.href, enumerable: true });
return values;
};
});
});