Templating Engine for HTML (special case AMP)

I’m usually working with Angular. But recently I started an AMP Project (www.tsmean.com). For those of you who don’t know AMP, it’s short for “Accelerated Mobile Pages” where you use only the “Official AMP JavaScript Libraries” but no JavaScript of your own and only prerendered HTML. The goal of this is to make webpages blazingly fast. Since a requirement is precompiled html I can’t use Angular as a templating engine since that dynamically compiles the html. Even though it has a static option with Angular Universal (don’t get me started on this…), the Angular Universal rendered page still includes JavaScript so it’s not possible to render an AMP compatible (=JavaScript-free) page with it.

So I’m kind of back in the “dark ages” where I’m stuck with templating engines such as Mustache, Handlebars, EJS or Pug (former Jade). Why I need a templating engine should be obvious: I don’t want to copy / paste code snippets all around and duplicate them like crazy. So I need a templating engine. Just which one’s right? So I set out to choose my templating engine for html. Which has been an absolute nightmare. Let’s review our options.

Mustache

Mustache, we’ve all heard of it. Logic-less templating. So the entry point to the “mustache experience” is this one: https://mustache.github.io/

Since mustache is basically just a spec, it can be implemented in any language. That’s why you see so many languages there. I first clicked on the node.js link which leads to this godforsaken project I’ve used now for a quarter year: https://github.com/raycmorgan/Mu

The owner of the repo doesn’t seem to give two sh*ts about it. Last commit somewhen in 2016. Four unmerged pull requests https://github.com/raycmorgan/Mu/pulls. One of them is mine. No response whatsover.

Then I tried the one when clicking on “JavaScript” in mustache:  https://github.com/janl/mustache.js . Aha, that seems to be the right one with 11k github stars! Okay, I can’t concentrate because of that gif with the dude with the mustache. Is it just me, or is it really annoying to put that gif there? Maybe I’m just having a bad day. But then again, the command line tool also doesn’t seem to be ideal for me because I have to specify all used partials:

mustache -p path/to/partial1.mustache -p path/to/partial2.mustache dataView.json myTemplate.mustache

Can someone explain to me why this is necessary? The partials are already specified in the template! The first mustache compiler I mentioned didn’t require me to pass in all partials at compile time. I mean my template.mustache looks like this:

blabla
{{ > path/to/partial.html }}
blablub

Why do I have to pass this partial as a compiler option again? Especially if you have many views with many partials this becomes very tedious. And if the partial uses another partial? How am I supposed to track the usage of my partials? Unless … I don’t track it and just include all my partials everywhere. Then I’ll just have to register them ONCE in a single file, which is okay.

For those of you coming from Angular like myself, you’ll ask how can I pass data to partials?! You’d expect a syntax like

{{> mybutton title="Cancel" }}
{{> mybutton title="Save" }}

but this doesn’t exist. Instead you’ll set the variable inside the partial by the context you surround it with. An example:

{{#buttonOne}}
  {{> mybutton}}
{{/buttonOne}}
{{#buttonTwo}}
  {{> mybutton}}
{{/buttonTwo}}

and in the data.json you’d specify

{
  "buttonOne": {
    "title": "Cancel"
  },
  "buttonTwo": {
    "title": "Save"
  }
}

In the partial there could be the code

<button class="my-cool-button">{{title}}</button>

The result would print

<button class="my-cool-button">Cancel</button>
<button class="my-cool-button">Save</button>

It’s a bit of a change a first, but workable.

On a sidenote, there’s another small issue problem with the command line tool. The doc’s state:

The command line tool is basically a wrapper around Mustache.render so you get all the features.

But then their example is actually a demonstration that this doesn’t work:

var view = {
  title: "Joe",
  calc: function () {
    return 2 + 4;
  }
};

var output = Mustache.render("{{title}} spends {{calc}}", view);

where the view object is what’s supposed to go to  dataView.json (see above) which is obviously not possible since a JSON can’t hold a function value…

Handlebars

Remember how I said my project can’t have any extra JavaScript libraries? Now, the precompilation of handlebars seems to be so stupid, that it still requires a JavaScript library on runtime:

<script src="/libs/handlebars.runtime.js"></script>

Duuuudes, come on, you’re killin me…

Pug

Since the name “Jade” was copyright infringement, they changed it to pug. In case you don’t know it, it’s a html templating engine, that doesn’t look like html at all. It’s whitespace sensitive and you’ll have to learn a new language. For me, I don’t like it that they deviated so much from the standard html for a couple of reasons:

  • No copy / pasting of code snippets from nowhere (one might say that’s a actually a good thing…)
  • You’ll have to learn a “new language”
  • All team members will have to learn a new language.
  • Larger chance of getting out of fashion than when sticking with something similar to html like mustache (yet small chance, since it’s been here for a while and has too many users to be completely abandoned)
  • I don’t really find the whitespace based syntax better
  • My IDE doesn’t do it’s job as well

So all in all I have very little incentive to use pug, I just see a point of deviating that much from HTML.

EJS

EJS has horribly little documentation: http://ejs.co/

It doesn’t seem to be what I’m looking for: A command line tool to precompile some html templates. Rather you put your html as strings into into JavaScript files, which neither me nor my IDE like very much. As for storing html snippets in a separate file, then requiring them through JS, then paring to a string, and then storing that string again in a file, that’s just too complicated.

Conclusion

Mustache is the winner. Clean syntax that integrates well with html. Large community supporting it. Been here for a while. Not going anywhere anytime soon. Once you get it, you got it. However, it took me a while getting it, since the approach to handling templates and data seems weird when you come from Angular. This article on “passing variables to partials” has been a bit of an eyeopener for me, so thanks Pawel!

Tips & Tricks for Google Analytics (GA) + Google Tag Manager (GTM) + Accelerated Mobile Pages (AMP)

Setting up GTM + GA + AMP can be a “pull your hairs out” experience. So let me help you with this list of tips, tricks and pitfalls to avoid when setting up AMP with GTM and GA.

Event Logging in Google Analytics

So far the greatest pitfall has been with events. Events have 4 dimensions: category, action, label and value.

Now there is an article about events here https://support.google.com/analytics/answer/1033068?hl=en and it tells you that value needs to be an integer. But it doesn’t tell you what happens when you don’t adhere to value being an integer. What happens is that your event won’t get logged at all, even though your request to google analytics will get a 200 OK. It also doesn’t tell you, that having an undefined variable will result in the same problem. For example, if you have in GTM value = {{someValue}} , but someValue is undefined, the request being sent to GA is https://www.google-analytics.com/collect?…&ev=&… which results in the event not being logged.

Submitting information about a clicked element

Now in the regular tag manager, you get the Element Id / Click Id as built-in variable for clicked html elements. Not so for AMP. I thought you can’t transport information about a html element in AMP through GTM until I found this: https://github.com/ampproject/amphtml/blob/master/extensions/amp-analytics/analytics-vars.md

Somewhere hidden in the darkest corner of some github repository’s readme lies a very important information on how to send information about html elements: through the data-vars-* attribute. So for example you could use data-vars-event-id , which you could then use in GTM’s variables like so:

So the dash-case from the html attribute gets transformed to camel case for the variable configuration. Or as the they put it in the github doc:

The variables passed as data attributes should follow the format data-vars-*.

Example:

<span id="test1" class="box" data-vars-event-id="22"> Click here to generate an event </span>

And in the request url the token would be of the format ${eventId} (follows camelcase).

(BTW: I only stumbled on it by reading through https://github.com/ampproject/amphtml/issues/1298 . Reading through github issues is so much fun…)

Generic Click Trigger

To log every click as an event, you can use the following trigger in GTM:


Subscribe to stay posted.

AMP Project Starter

From the www.tsmean.com project, a nice little side project developed. The homepage of tsmean.com was built with AMP – Accelerated Mobile Pages. Those are pages that load freakishly fast on mobile, and hence also on the web. It’s actually really amazing for the user experience.

AMP has a quite great documentation with ampproject.org and ampbyexample.com. What was still lacking was how to build an actual website. In their example, they always only had single pages, so in order to build an actual website with multiple pages, you’ll have to do the work yourself. It’s not that it’s very complicated, after all it’s just some html and css. However, I found that I’d reuse the same basic setup on all of my amp pages and my friends started to use the same code as well. So I thought why not make an “Amp Project Starter” out of it? It gives you a working app out of the box. You can find more information about it here: