Never forget UTM params again with this handy email template CSS

As we all know, adding the standard utm_* query params to email links is something Marketo can’t do automatically.

Storing UTM params in a Program-level {{my.token}} and building links from ${mktoString} variables are smart moves. But it’s tough to tokenize every single link. (Users must remember to UTM-ify links in Rich Text areas, for example.)

While there’s no magic hack to add params for you, wouldn’t it be nice to have visual feedback when you forget to add ’em? Check this out:

It’s crazy easy to do this with modern CSS. That CSS won’t work in most email clients, but that doesn’t matter because we only need it to work in Marketo’s Email Preview!

Just add this Velocity {{my.token}} to your template, substituting your LP domain for pages.example.com and your branding (email click tracking) domain for click.example.com:

#if( $mktmail.DefaultTrackingHost.equals("localhost") )
<style>
.is-preview {
  /* ignore links not expected to be UTM-ified */
  a:not([href]):after, /* internal links */
  a[href^="https://pages.example.com/index.php/email/emailWebview"]:after, /* View as Web Page */
  a[href^="https://click.example.com/"]:after, /* Forward to Friend */
  a[href^="mailto:"]:after,
  a[href^="tel:"]:after,
  #mkto-social a[href]:after, /* native social widget */
  a.no-utms-expected:after /* for custom use */
  {
    content: none !important;
  }

  a.missing-utms:after 
  {
    content: "missing utm! \A" attr(href);
    white-space: pre;
    text-align: left;
    text-transform: none;
    background-color: red;
    color: white;
    font: 10px/20px Verdana,Helvetica,sans-serif;
    padding: 4px 6px;
    margin: -10px 0 0 6px;
    position: absolute;
    border-radius: 4px;
    border: 1px solid white;
  }
}
</style>
<script>
if(document.location.hostname.endsWith(".marketodesigner.com")){
  document.documentElement.classList.add("is-preview");
  
  for( const link of document.links ) {
    try {
      const url = new URL(link.href);
      
      link.classList.add("missing-utms");
      for( const param of url.searchParams ){
        if( /utm_/.test(param) ) {
          link.classList.remove("missing-utms");
          break;
        }
      }
    } catch(e) {}
  };  
}
</script>
#end

Key points:

  • For simplicity, we require at least one query param starting with utm_. The code could be expanded to specifically require utm_campaign, utm_medium, etc.
  • The “ignore” section contains links that aren’t expected to have UTMs. You’ll likely find more such links. Let me know in the comments if there’s anything non-business-specific.
  • You can tag business-specific ignorables with <a class="no-utms-expected">.
  • Make sure to check Dynamic Content w/segmentations, Velocity-generated content, etc. not just the Default preview.
  • Obviously you can restyle the warning any way you want, just keep position: absolute so it doesn’t disrupt the layout.