Using a ${mktoVariable} on the <html> element itself

A question recently cropped up about adding the lang tag to the <html> element in a Marketo email — as the W3C has long recommended — but making the language a variable instead of a static value set in the template.

If you’re going to include lang, this flexibility makes sense, for sure. (Not convinced recipients’ mail clients care about the lang[1], but there’s no doubt it should be in your HTML for standards’ sake.)

So the person was trying this:

<!DOCTYPE html>
<html lang="${emailLanguage}">
<head>
<meta class="mktoString" default="en-us" id="emailLanguage" mktomodulescope="false" mktoname="Email Language" />
<meta class="mktoString" default="" id="emailTitle" mktomodulescope="false" mktoname="Email Title" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="width=device-width, minimal-ui, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>${emailTitle}</title>
<head>
<body>
<!-- content goes here -->
</body>
</html>

This won’t work, though, because ${emailLanguage} is being declared after the place you want to use it. Because of the order-of-operations of template parsing works, you can’t do that. (Though the parser didn’t have to work this way... that’s the way it was built!)

The solution is simple: declare the variable at the very top of your template, between the <!DOCTYPE> and the opening <html>. That’ll make it available to every element in the document.

Don’t blame you for not knowing this will work, but it does:

<!DOCTYPE html>
<meta class="mktoString" default="en-us" id="emailLanguage" mktomodulescope="false" mktoname="Email Language" /><html lang="${emailLanguage}">
<head>
<meta class="mktoString" default="" id="emailTitle" mktomodulescope="false" mktoname="Email Title" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta content="width=device-width, minimal-ui, initial-scale=1.0, maximum-scale=1.0, user-scalable=0;" name="viewport" />
<meta name="robots" content="noindex,nofollow">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>${emailTitle}</title>
<head>
<body>
<!-- content goes here -->
</body>
</html>

And no, this doesn’t make broken HTML! Marketo’s special <meta class="mkto*"> tags look like HTML meta tags, but they’re actually preprocessor tags. As such, they’re parsed and then clipped out of the final HTML. That’s why you see empty lines in the <head> where the tags were before. (Note I deliberately didn’t add a line break after the <meta> in this case, as no trace of the tag should be left behind.)

Notes

[1] In View as Web Page mode, it would certainly be important for screen readers and such, don’t get me wrong, but the <html> wrapper tag isn’t even mandatory for email clients.