The Ultimate Mustache Tutorial

Learning Mustache is a lot faster if you understand properly what it’s all about and learn the underlying concepts. You’ll grasp a firmer understanding of Mustache by going through this tutorial, than by directly diving into the official docs, which often seem confusing at first.

What is Mustache?

The first thing to learn is that Mustache is NOT a templating engine. Mustache is a specification for a templating language. This specification can be found here, but don’t read that just yet. You’re not ready yet.

The idea is, that you write templates that adhere to the Mustache specification, that then can be compiled / rendered to create an output.

What’s a Templating Language and what’s it for?

Let’s say you want to send the same email to 100 people, except you want to personalize the salutation with their respective first names. You could replace the first name by some placeholder:

Dear *|FNAME|*

I hearby blablabla ...

Here I have invented (=stolen it from Mailchimp) a syntax for a placeholder: *|FNAME|*

The mustache syntax looks a bit different. This case would be covered by the following template:

Dear {{fname}}

I hearby blablabla ...

As you can see, in Mustache we have curly braces for placeholders, which look like a mustache when rotated 90 degrees clockwise:

Hence the name of the language. There’s more to the Mustache than that, but before diving any deeper into the language, it’s useful to first cover another concept.

By simply having specified a templating language and having written a template doesn’t produce 100 emails for me. Much like with a programming language, just learning the language doesn’t actually mean you know how to run a program. For example you might read in your first JavaScript tutorial that ” var x = 5 + 3 ;” is JavaScript, but you might not know exactly how you could run the code. Similarly with Mustache, you might learn about the language in a tutorial, but have no idea how to actually convert your templates to an output. Or to put it differently: How the heck can I create my 100 emails from 1 single Mustache template? You’ll need a …

Templating Engine

So once a syntax aka. templating language is defined, you need a tool that fills the placeholders in the template(s) with actual data and produces an output. This is called a templating engine:

To strech this point again, Mustache is not the templating engine. It’s the specification for how the template file must look like.

Or to come back to the example with programming languages. Mustache is the language. Not the execution environment. You can learn about the language in a book. But to actually use the language, you’ll need a computer and something that can interpret and run your code. The programming language JavaScript, for example can be ran and interpreted by Firefox, Chrome, Microsoft Edge and Safari, but they all use a different underlying engine to interpret and run it.

What’s the Templating Engine for Mustache?

Like for JavaScript there, isn’t just one thing that can compile Mustache. There’s a multitude of tools out there that can take a Mustache Template, some input data, and produce an output. The multitude of tools is actually overwhelming. There are tools that do their job well. And then there are obsolete ones that are badly maintained and don’t actually adhere to the Mustache specification. So which one should you choose from the multitude of options? The answer is: It depends on where and how you want to use Mustache. I will make some examples here, but I encourage you not to get lost in the actual links to those tools, but rather stick with the tutorial. When you leave now, you’ll be into the nitty gritty of how to use one tool without having the greater picture.

Example 1: You have a Java server and want to send out emails to users. So you use our Mustache Template from above for the emails and extend it a bit. So now you’d like to tell your Java code “hey, I’ve got a mustache template and 3 users that go by the name of [“Hans”, “Gertrude”, “Fritz”], can you send them a welcome mail”? Then your best bet would be to use the most popular Mustache Engine written in Javahttps://github.com/spullara/mustache.java . Why? Because you have the data already in your Java code. The Mustache template file you can load through regular I/O:

// DOESN'T ACTUALLY WORK THAT WAY, BUT WAS EASIER TO ILLUSTRATE
String[] users = {"Hans","Gertrude","Fritz"};
for (String user : users) {
  String renderedEmail = mf.compile("emailTemplate.mustache", user);
  // ...then send email to user...
}

Example 2: You have a Python server and want to send an E-Mail. Pretty much the same as above, except that you’d use the most popular Mustache Engine written for Pythonhttps://github.com/defunkt/pystache.

Example 3: You just want to print 100 personalized invitations to your birthday party, but have no idea about coding whatsoever (which is obvious, since coders don’t have 100 friends). Then unfortunately Mustache is not a good choice for you, since literally all engines for Mustache are connected to a programming language. There isn’t such a thing that takes an excel list of invitees plus a Mustache template and generates 100 pdfs out of it. At least I haven’t found something like that. Even though in principle it would work since it’s just a case of [Template + Input Data = Output] there just aren’t enough people that want to build their birthday cards that way…

Actually, this example 3 was really educational. We’ve learned that all available Mustache engines are connected to programming languages. Which ones are the available languages?

Here’s a screenshot from the official Mustache page answering that question:

Okay, that’s quite a lot of implementations. As I mentioned, some are good, some are bad. For example, the one listed for “node.js” is not maintained and buggy, while the one under “JavaScript” actually also supports node.js. So as you can see this list isn’t the be-all end-all. Maybe some of the listed links are outdated. Maybe some other ones are not included. At the same time, it’s still the best list that I’m aware of.

So now that we’ve covered the conceptual basics, we can dive deeper into the Mustache Templating language. But let’s first repeat what we’ve learned so far:

  • Mustache is a templating language, not a templating engine
  • There are tons of implementations for mustache engines, but be careful when choosing since not all are good.

Learning the Mustache Template Syntax

Now for the rest of the tutorial you have two choices. Either you select a templating engine from above and learn how it works. Then you can actually test the examples on your machine, which makes it a bit more tangible. But since Mustache is just a language, you might also be lying at a beach right now, slurping your drink, and reading the rest of the tutorial.

The Basics

We already had saw our very first template above, but let’s repeat it in a similar fashion because it was so beautiful:

Hello {{planet}}
{
  "planet": "Earth"
}

We choose JSON to describe our data here, but this would depend on the engine you’re using.

The template plus the data would produce the output:

Hello Earth

Now depending on your tool this output might be stored in a variable of your program or written to the filesystem. For example, the JavaScript mustache engine has two modes: Either it can be used as a command line tool to produce files, or it could be used to dynamically render html files.

Like what you're reading?    Get the latest updates first!

No spam. Just great engineering posts.

Conditionals

In Mustache, there are no if and else statements and also no loops. That’s why they call it logic-less templating. At least they’re not directly represented as keywords in the templating language. It is however possible to conditionally show or hide a block of text. And this is how:

Mustache Template:

Hello
{{#myCondition}}
  la di da
{{/myCondition}}

Data:

{
  "myCondition": false
}

Output:

Hello

Loops through Arrays / Lists

Loops are also not represented directly in the mustache language, but indirectly via the data and how the mustache specification specifies behaviour when the data is an array.

Data:

{
  "users": ["Hans", "Fritz", "Geraldine"]
}

Mustache Template:

{{#users}}
  {{.}}
{{users}}

Output:

Hans
Fritz
Geraldine

If you want all names on the same line, you’ll have to write {{#users}}{{.}} {{/users}} on one line in the template (and put a space in there for legibility).

The elements could also be objects instead of strings, in which case access is given by just writing the property names into the brackets:

Data:

{
  "users": [{
    "name": "Hans"
  }, {
    "name": "Fritz"
  }, {
    "name": "Geraldine"
  }]
}

Mustache Template:

{{#users}}
  {{name}}
{{users}}

Output:

Hans
Fritz
Geraldine

Using templates inside of templates: “Partials”

One Mustache template can load another template. The specification states that this should work with the syntax

I am a template and I'm loading
{{> template2 }}
and now I continue

This works fine as long as template2 doesn’t require template1, then you’ll get an infinite recursion which your templating engine can’t handle.

Passing Data to Partials

Passing data to partials is actually a bit tricky and one of the things that took me the longest to figure out. It works like this:

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

and in the data 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>

Comments

Comments begin with an exclamation point and are ignored. The following template:

<h1>Hello{{! ignore me }}.</h1>

Will render as follows:

<h1>Hello.</h1>

Comments may contain newlines.

Summarized Learnings

Grasping the concepts at first isn’t easy because there are so many different implementations of Mustache and they’re often confused with the actual Mustache specification. Yet through a clear separation, the Mustache language can be learned independently, and then the skills can be used together with a carefully chosen engine (since not all of them are good or adhere to the official Mustache specs). Thanks for reading the tutorial, I hope you learned a lot, don’t forget to subscribe if you’re interested in Web Development and share the post with friends!

 

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!

What’s up with Angular Universal?

I was excited when I heard Angular 2 would support server-side rendering since SEO was a huge PITA (pain in the ass) with Angular 1. It was said that server-side rendering would be possible through Angular Universal.

Yet, this Angular Universal thing, what’s up with that? Seems to have a really small team on that and there doesn’t really seem to be any documentation. Well at least there’s a getting started repo, so I thought. However, this repo (https://github.com/robwormald/ng-universal-demo) doesn’t even have a readme…

Also, when you check out some of those files, they don’t seem very professional. For example: https://github.com/robwormald/ng-universal-demo/blob/master/src/express-engine.ts

First line of code: //hacky express wrapper thingy.

Seriously?

Then of course, there’s also some confusion as to where to go and look for resources. You’ll find quite a few.

When you just google “Angular Universal” (as of September 2017) you’ll get to https://universal.angular.io/. However, this page is a bit out of date.

Just have a look at the date:

Or the actual site:

Angular 2 is now Angular 4 and --ambient is also not a thing anymore. So the only purpose of universal.angular.io is to confuse people with outdated material and to link to github (https://github.com/angular/universal).

Github, even though being the best resource on Angular Universal, isn’t really documented either. Meh.

Well, I guess switching to React isn’t such a bad idea after all?

PS: I wrote this article in May 2017, I’ve checked again in September and now, even though the docs are still a mess, there’s a working demo here: https://github.com/angular/universal-starter/tree/master/cli

Blocking Browser APIs

Tip of the week:

Don’t use alert, confirm or prompt browser APIs in your production code. They are blocking and thus problematic for performant websites.

Host websites with high availability and low latency for less than 1$/month, SSL included

I’ve been deploying static websites the wrong way all of my life. My procedure used to look like this:

  • Choose a server (EC2, Digitalocean) in a region (US, Europe, …)
  • Set up some nginx / apache configuration
  • Maybe add SSL through letsencrypt

I’ve always been aware that there are several drawbacks to this:

  • The smallest EC2 / digital ocean instances cost ~5$ which is quite a lot if you have many websites.
  • To make this cheaper, you start putting everything on one server (e.g. one ec2 small instance for 20$ / month), but if this instance crashes ALL your websites are down. You’ll have a very fragile availability.
  • By selecting a server in a specific region, the other regions have high latency
  • Adding SSL is kind of a pain, even if it’s free through letsencrypt
  • It’s not scalable
  • You need to mess with complicated config files from nginx / apache and need to ssh into your instance.

I’ve just never been aware that there’s a much better and easier solution!

The solution is called … (drumroll) … : AWS CloudFront.

Or to be less product specific, the solution is called: Put a CDN in front of some highly available data store.

Here’s what that means:

Your users will access the content through servers in the region closest to them.

This eliminates all of the previously mentioned drawbacks:

  • It’s cheap: AWS charges less than 1$/month for this setup
  • It’s got high availability: S3 has 99.9999999% uptime (I’ve randomly added 9’s)
  • It’s got low latency: Content is served through the data center closest to you.
  • You get a free SSL certificate from AWS that you can easily, no config file hacking.
  • AWS takes care of scaling for you
  • It’s simple to set up & deploy!

How to set up AWS CloudFront

AWS CloudFront is pretty simple to set up, but there are a few pitfalls, so here’s a tutorial with pictures to guide you.

Step 1: Host website with AWS CloudFront

Go to https://console.aws.amazon.com/quickstart-website/home; you also have that link on your dashboard.

Next, fill out the wizard:

and hit create. Your website needs to have an index.html file for this to work.

Tada. You have a working hosted website at some crazy url.

Step 2: Setup domain

Hit “Buy domain” on the website dashboard. This is the right button even when you’ve already bought you’re website through Route 53.

If you already have a domain, you can simply select it here:

Step 3: Set up SSL

Back on the website’s main page, select “Manage settings in Amazon CloudFront”:

There, click edit:

and select Custom SSL Certificate:

If you don’t have one yet, you can request a new one. It’s easy to set up, but you’ll need to have a working email address for the domain. E.g. when you want to set up example.com, you need e.g. admin@example.com to be working. I’m not going too much into detail here, since that’s a topic on it’s own.

Once the certificate has been issued and connected, SSL works:

Step 4: Pretty URLs and Subdirectories

By default, the files are hosted as they are: example.com/articles/my-article.html. Now how can you get rid of the html extension? You can either just remove the html extension or have a folder example.com/articles/my-article/index.html.

Unfortunately, there’s also one setting that needs to be changed for this to work. Head over to s3 > website bucket > properties > static website hosting and copy the “Endpoint” URL:

Then in Cloudfront > Origins

select the right website and hit edit, then replace the “Origin Domain Name” with what you’ve copied from the S3 bucket (without the http://).

Congrats, you’re all set up!

Step 5: Deployment

It’s a bit annoying to always have to upload a zip if you’re more the command line type of guy. Fortunately, it’s still possible to upload through command line with AWS cli:

aws s3 cp dist s3://<bucket-name>/ --recursive

You’ll need to set up IAM for this to work. Create a new user, give him S3 access, and hit:

aws configure

once the aws command line cli is installed.

Additional Tips & Tricks

There are a few gotchas you’ll have to be aware of when setting up CloudFront.

Forwarding the Naked (Apex) Domain to the WWW domain

In order to achieve a forward from https://example.com to https://www.example.com you’ll have to use a really weird workaround: Create a new S3 bucket with the name example.com. It HAS to be example.com, you can’t give the bucket any other name. Then in properties > static website hosting redirect all requests:

Finally, in Route53 resolve example.com (or here tsmean.com) to this S3 bucket:

If the S3 bucket name IS EQUAL TO THE RECORD NAME, the S3 website bucket should show up when you select Alias Target. That’s it, that way requests to the naked (apex) domain can be forwarded to a www domain.

Cache Invalidation

If you’ve followed the “one server deployment paradigm” so far, you’re probably used to seeing your changes visible immediately after deployment. This is not the case when using AWS CloudFront. Since it’s a distributed system with servers at edge locations that cache your assets, those caches have to be invalidated first. AWShas two articles on this, first http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Invalidation.html and second http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/ReplacingObjectsSameName.html.

They advise you against using their built-in cache invalidation mechanism since it becomes expensive above a certain number of requests. However, this free limit is 1000 requests per month as of August 2017. That’s more than enough for most people since you can declare wildcard paths and those are counted only once, even if thousands of requests are made! So you could just specify “*” as invalidation and your cache is cleared with one request:

I personally prefer this to versioned object / directory names since I find it easier.

Conclusion

Compared to AWS CloudFront, deploying to single instances just feels hacky and wrong now. It’s simpler, cheaper and safer with AWS CloudFront. It’s the solution I’ve always wanted, but didn’t know existed. Hope this tutorial helps someone!

Convert Latex to HTML online

Yesterday I wanted to convert a snippet of latex code to html. Unfortunately, the results when Googling for “latex to html online” are only cr*p. I knew a tool that was really great at converting latex files to html files. This tool is called Pandoc. However, it seemed like a bit of overhead to always create a file, store the latex snippet, remember what the pandoc command was to convert, enter the entire command (e.g. pandoc mysnippet.tex -o mysnippet.html), open the html file and get the snippet… That’s why I’d much prefer an online tool that does this chore for me. Since I couldn’t find any, I implemented it myself.

This is the result:

It’s open sourced, the code can be found on Github at https://github.com/bersling/latex2html.

It’s a small self-contained piece of code with one html file and one TypeScript file at its core.

But here’s the interesting part, if I hadn’t been so bad at googling, I would have found that there is the exact same functionality available at

… So there might be even a better learning for me than the additional coding experience I gained: Before you build something, Google, google, google if it already exists. For example had I tried googling “convert with pandoc online” this converter would have been the first hit. For me, it was a small price to pay, since I built the solution in little time and it was quite fun, but if you’re working on a larger project and didn’t research what’s already out there, you’re gonna have a bad time.

UseNeXT Review

tl;dr: Don’t use UseNeXT. To cancel the free trial you’ll have to call them. That’s insane…

What’s UseNeXT?

UseNeXT is a provider to connect you to the useweb. Since I had problems with the GigaNews signup form, I decided to try UseNeXT since they had a well designed homepage.

The setup with UseNeXT

The setup and everything worked great and within minutes I was able to download from the usenet. The only weird thing was their invitation email which was formatted nearly non-legible.

Download speeds maxed out my bandwitdh, so that was good.

However the usenet didn’t prove as useful as I hoped it would, after trying it out I decided to leave it be for now.

The cancellation – and why I give UseNeXT a bad review

Cancellation is made extremely difficult. After 5 screens of asking if you don’t just wanna buy another option, UseNext tells you to call them. Hence the bad review for UseNeXT. So think about that twice before using UseNeXT’s free trial…

Mircoservice Architecture vs Service-Oriented Architecture (SOA)

It’s interesting how microservices are the new hype and SOA is detrending:

What’s the difference between the two? To me, the best description seemed to come from this StackOverflow answer:

So, SOA is an architectural pattern in which application components provide services to other components. However, in SOA those components can belong to the same application. On the other hand, in microservices these components are suites of independently deployable services.

A manifestation of this is for example, that often in SOA you’ll still just use one programming language, whereas in a microservice architecture you could choose the language that suits the service best.

So what do you think, are the trends justified or is it just because SOA is now “old” and Microservice Architecture a bit hyped? Leave your comments below.

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: