Deciphering the AMP-List Logic

Getting Waist-Deep in Dynamic Content

Previously, we reviewed how using a JSON endpoint can bring dynamic content into an AMP page using amp-list. However, not discussed was how we go about taking that JSON data and translate it into content on a website using amp-list. 

Amp-list uses a templating framework called mustache.js in order to determine what content from a JSON object should be imported into an AMP page. The following is an example of a template that we can create, which will import product information and an add-to-cart form with options that can change based on whether the product’s in stock, has bulk purchase options, or if it’s out of stock.

<amp-list layout="fill" src="https://mysite.com/productID.json" template="addToCart" items="." single-item>
<template type="amp-mustache" id="addToCart">
<div class="productCard">
<div class="productImg">
<amp-img layout="responsive" height="16" width="9" src="{{Img}}"></amp-img>
</div>
<h2 class="productName">{{ProductName}}</h2>
<div class="productInfo">
{{#InStock}}
<div class="productPrice">{{ProductPrice}}</div>
<div class="productSavings">{{ProductSavingPercentage}}</div>
{{/InStock}}
{{^InStock}}
<h4 class="productOutOfStock">Sorry. This item is out of stock.</h4>
{{/InStock}}
</div>
<div class="addToCart">
{{#InStock}}
{{#HasBulk}}
<a href="#">Add 3 to Cart</a>
<a href="#">Add 6 to Cart</a>
<a href="#">Add 9 to Cart</a>
{{/HasBulk}}
{{^HasBulk}}
<a href="#">Add to Cart</a>
{{/HasBulk}}
{{/InStock}}
{{^InStock}}
<a href="#">Email Me When In Stock</a>
{{/InStock}}
</div>
</div>
</template>
</amp-list>
view raw amp-list.html hosted with by GitHub

Now that we can see what the finished product would look like, let’s break down what exactly is going on. To start, we’re going to need to declare the amp-list element and add attributes defining its layout, JSON endpoint source URL, template to use, what array in the JSON source to pull data from, and the number of items in that array to return. In our example case, we’re going to use the fill layout, productID.json endpoint, addToCart template, and take a single item from the array in the endpoint (Note: items=”.” will take whatever is the key for the parent array in the endpoint. If you want to use a child array, then you’ll need to declare the key for that child array in the items attribute.). We’ll also want to declare the template element and declare its template type and its template ID (in case we want to use the same template for other amp-lists in the same AMP page).

<amp-list layout="fill" src="https://mysite.com/productID.json" template="addToCart" items="." single-item>
<template type="amp-mustache" id="addToCart"></template>
</amp-list>

We can now start working on the addToCart template that our amp-list will use with the Mustache.js framework logic. Before we begin, let’s take a look at what our JSON endpoint looks like.

{
"Product": {
"ID": 123456,
"Img": "/img/ProductImg.jpg",
"ProductName": "A Cool Product",
"ProductPrice": "$0.99",
"ProductSavingPercentage": "83%",
"InStock": true,
"HasBulk": false
}
}
view raw amp-list.json hosted with by GitHub

By setting our amp-list to pull from items by using items=”.” it’ll automatically take the data from Product for the template. Now, let’s first start off by adding in actual content to our template. This can be done by grabbing the key for the content you want to place in the template and enclosing it with mustache brackets. For example, using {{ProductName}} in the template will result in “A Cool Product” displaying in the AMP page. You can also use these values for declaring ID, class, href, or src attributes, which we’ll be doing for the amp-img element with the Img key value.

<amp-list layout="fill" src="https://mysite.com/productID.json" template="addToCart" items="." single-item>
<template type="amp-mustache" id="addToCart">
<div class="productCard">
<div class="productImg">
<amp-img layout="responsive" height="16" width="9" src="{{Img}}"></amp-img>
</div>
<h2 class="productName">{{ProductName}}</h2>
<div class="productInfo">
<div class="productPrice">{{ProductPrice}}</div>
<div class="productSavings">{{ProductSavingPercentage}}</div>
</div>
<div class="addToCart">
<a href="#">Add to Cart</a>
</div>
</div>
</template>
</amp-list>

Here’s where things may get a bit tricky. We want to be able to show certain messages and add-to-cart features based on whether or not an item is in stock or has bulk-buying options. We can do this using a nifty conditional feature of the Mustache.js framework with the data from our endpoint. Looking back at our JSON data, we’ll find that the InStock and HasBulk values are boolean values. Using these values, what we can do is tell our template if the item has “true” for InStock and “false” for HasBulk to show the product price info and add-to-cart option. Then if the item has “true” for InStock and “true” for HasBulk to show the product price info and bulk add to cart options. Finally, if the item has “false” for InStock to show an “Out of Stock” message and a “Notify Me” button for when the product is in stock again. We do this by using the following patterns in our template.

{{#InStock}}
{{#HasBulk}}
<!-- Show Product Price Info and Bulk Add To Cart -->
{{/HasBulk}}
{{^HasBulk}}
<!-- Show Product Price Info and Add To Cart -->
{{/HasBulk}}
{{/InStock}}
{{^InStock}}
<!-- Show Out of Stock Message and Notify Me Button -->
{{/InStock}}

From the above pattern, we can gather that containing content within brackets that begin with {{#[KEY]}} and end with {{/[KEY]}} will return content if the key’s value is truthy, and if the brackets begin with {{^[KEY]}} and end with {{/[KEY]}} will return content if the key’s value is falsey. Unfortunately, it’s not possible to combine #[KEY] and ^[KEY] within the same brackets, which is why we have nested brackets for additional conditions. My biggest word of advice when needing to use conditionals, such as these, is to start with the overarching condition that accounts for all products first and then use nested conditions to narrow down results, set truthy conditions before falsey ones, and to separate conditionals within each wrapper container in an amp-list template so as to prevent any confusion. Once we have organized our conditionals based on the template we have made so far we will end up with the result introduced at the beginning of this entry.

<amp-list layout="fill" src="https://mysite.com/productID.json" template="addToCart" items="." single-item>
<template type="amp-mustache" id="addToCart">
<div class="productCard">
<div class="productImg">
<amp-img layout="responsive" height="16" width="9" src="{{Img}}"></amp-img>
</div>
<h2 class="productName">{{ProductName}}</h2>
<div class="productInfo">
{{#InStock}}
<div class="productPrice">{{ProductPrice}}</div>
<div class="productSavings">{{ProductSavingPercentage}}</div>
{{/InStock}}
{{^InStock}}
<h4 class="productOutOfStock">Sorry. This item is out of stock.</h4>
{{/InStock}}
</div>
<div class="addToCart">
{{#InStock}}
{{#HasBulk}}
<a href="#">Add 3 to Cart</a>
<a href="#">Add 6 to Cart</a>
<a href="#">Add 9 to Cart</a>
{{/HasBulk}}
{{^HasBulk}}
<a href="#">Add to Cart</a>
{{/HasBulk}}
{{/InStock}}
{{^InStock}}
<a href="#">Email Me When In Stock</a>
{{/InStock}}
</div>
</div>
</template>
</amp-list>
view raw amp-list.html hosted with by GitHub

And using the JSON data that we introduced, our resulting content will look like this.

This is just one of the approaches that you can use for building a template for amp-list. As an added note: There is another variable that you can use in an amp-list template called an escaped mustache variable, which looks like this: {{{[KEY]}}}. What this will do is return any HTML code that might be part of the value of the key you’re referencing as plaintext. Let’s take a look at this brief example using a regular variable call and the escaped mustache variable call.

JSON
Company: <strong>Wompmobile</strong>

Amp-list Template Format
{{Company}}
{{{Company}}}

Amp-list Template Format Outcome
&lt;strong&gt;Wompmobile&lt;/strong&gt
<strong>Wompmobile</strong>

Make note: This will only return the value as plaintext and will not actually render the HTML code when using the escaped mustache variable (though perhaps in the future Google’s AMP team will change this).

If you would like to know more about amp-list and how to use Mustache.js, check out the links below.

WompMobile is a full-service AMP development agency. If you have any questions, please don’t hesitate to reach out.