# Basics

## Introduction

You can **personalize your push notifications** from the campaign editor using the data you have collected on your users. Batch provides a system of dynamic contents and a templating engine, allowing you to make dynamic messages for your campaigns.

Using the templating engine, you can reference and use user data inside your message. You can also add conditions to a message so that the content changes if some condition is fullfilled.

Here's a quick example to see how a dynamic content with a user attribute looks.

## Dynamic Content

Before diving deep let's review the dynamic contents.

We have implemented a dedicated interface to allow you to use **user attributes** in dynamic content and display custom data easily. When editing your message, just click on the **{...}** button, choose the custom attribute you want to personalize your message with and the formatting.

_That's it!_

As some of the targeted users might not possess the attribute you are using, you can add a default value. The preview will let you see how the notification will look for 10 random installs.

### Referencing attributes in your messages

If you are using APIs to send your notifications, here is the syntax to use dynamic contents in a message. All attributes usable in a query are available in dynamic contents.

They are:

* `attribute` or `c.attribute` will refer to an installation attribute, collected from the SDK.
* `u.attribute` will refer to a user attribute, collected via the Custom Data API.

```django
You're only on level {{ c.current_level }}, come back and play !
```

If the user's `c.current_level` attribute is `6` this evaluates to:

```
You're only on level 6, come back and play !
```

### Referencing properties in object attributes

If you have an object attribute, you can reference its properties using the dot notation. Suppose you have an attribute `address` that is an object with the following properties:

```json
{
  "city": "Paris",
  "zip_code": "75001",
  "street": "1 rue de Rivoli"
}
```

You can reference the properties like this:

```django
You live in {{ address.city }}, {{ address.zip_code }} {{ address.street }}
```

Please note that, for now, object attributes are only accessible through event attributes.

### Default values

Note that with the previous dynamic content, if the user doesn't have the attribute the resulting message will be:

```
You're only on level, come back and play !
```

This is probably not what you want, so you can add a default value. The default value is used when the attribute doesn't exist.

Here is how to use them:

```
Special offer: Get {{ u.special_offer|default('-5%') }} by subscribing today !
```

If the user's `u.special_offer` attribute is `-15%` then it evaluates to:

```
Special offer: Get -15% by subscribing today !
```

Otherwise it evaluates to:

```
Special offer: Get -5% by subscribing today !
```

### Referencing tag collections

All tag collections usable in a query are available in a dynamic content.

They are:

* `t.tag` will refer to an installation tag collection.
* `ut.tag` will refer to a user tag collection.

However, there's a catch: since a tag is a _collection_ of values and we can only output a single value using a dynamic content, we have to introduce the concept of _filters_. A filter is a function you can apply to a value to transform it.

In the case of a tag collection you can use the filter `join` to concatenate all values into a single string.

For example:

```
You've already beaten those levels: {{ t.levels_done|join(',') }}
```

Note that using a filter on a tag collection that doesn't exist always produces an empty string. Using the previous example, if the tag collection `t.levels_done` doesn't exist the dynamic content evaluates to:

```
You've already beaten those levels:
```

Loops are also available for tag collections, you can iterate over the values of a tag collection using the `for` loop, as explained in the [loop section](#loops).

### Formatting

Using raw data like this is great but you might want to format the attributes yourself.

Formatting is done by using the following filters:

* [formatDate](../advanced#general-filters) to format a date attribute
* [formatNumber](../advanced#general-filters) to format a number attribute

The two filters are explained in details in the reference but here is a small example:

```
You have accumulated {{ u.points|formatNumber(decimals=2) }} points, make sure to use them before {{ u.points_expiration_date|formatDate('yyyy-MM-dd') }}
```

This evaluates to:

```
You have accumulated 20.68 points, make sure to use them before 2017-02-30
```

Be sure to check out the reference documentation to learn about all options !

## Templating

Dynamic contents are already really powerful but they're not always enough.

For example, what if you want to display a completely different message based on which level a user is on, or how much fidelity points he has ?

This is a job for _templates_.

Templates allow you to do conditional statements, define variables and even do some light arithmetic.

### Conditions

Suppose you want to congratulate a user based on how far he is into your game.

You could write something like this:

```django

<div data-gb-custom-block data-tag="if" data-0='3' data-1='3' data-2='3' data-3='3' data-4='3' data-5='3' data-6='3' data-7='3' data-8='3'>

Good job on beating level 3 ! You're now halfway through the game, keep pushing !

<div data-gb-custom-block data-tag="else" data-0='5' data-1='5' data-2='5' data-3='5' data-4='5' data-5='5' data-6='5' data-7='5' data-8='5' data-9='5'></div>

Almost there ! One more level and you beat the game !

<div data-gb-custom-block data-tag="else" data-0='6' data-1='6' data-2='6' data-3='6' data-4='6' data-5='6' data-6='6' data-7='6' data-8='6' data-9='6' data-10='6'></div>

Amazing ! You've beat the game ! Go take a look at the amazing perks you unlocked !

</div>

```

Now depending on the value of the user's `current_level` attribute, the message will be one of the 3 possibilities.

### Loops

You might want to exploit a list of values, for example to display a list of products a user has bought. `for` loops are here for you, you can iterate over a list of values (like a tag collection or array attribute) and display them.

```jinja

<div data-gb-custom-block data-tag="for">

  You've bought {{ $product.name }} for {{ $product.price }}$ !

</div>

```

### Variables and arithmetic

Sometimes it might be handy to compute some value and keep a _reference_ to it so you can reuse it multiple times inside your template.

It is mainly a quality of life improvement but still useful.

For example, suppose you want to compute an expiration date based on multiple user attributes and remind the user when their subscription will expire.

Given the following rules:

* premium users have 90-days subscription
* users subscribed to the newsletter have a 75-days subscription
* users younger than 25 and not premium have a 60-days subscription
* all other have a 50-days subscription

You could write something like this:

```django

<div data-gb-custom-block data-tag="if">

<div data-gb-custom-block data-tag="set" data-0='90' data-1='90' data-2='90' data-3='90' data-4='90' data-5='90' data-6='90' data-7='90' data-8='90' data-9='90' data-10='90' data-11='90' data-12='90' data-13='90' data-14='0'></div>

<div data-gb-custom-block data-tag="else"></div>

<div data-gb-custom-block data-tag="set" data-0='75' data-1='75' data-2='75' data-3='75' data-4='75' data-5='75' data-6='75' data-7='75' data-8='75' data-9='75' data-10='75' data-11='75' data-12='75' data-13='75' data-14='5'></div>

<div data-gb-custom-block data-tag="else" data-0='25' data-1='25' data-2='25' data-3='25' data-4='5'></div>

<div data-gb-custom-block data-tag="set" data-0='60' data-1='60' data-2='60' data-3='60' data-4='60' data-5='60' data-6='60' data-7='60' data-8='60' data-9='60' data-10='60' data-11='60' data-12='60' data-13='60' data-14='0'></div>

<div data-gb-custom-block data-tag="else"></div>

<div data-gb-custom-block data-tag="set" data-0='50' data-1='50' data-2='50' data-3='50' data-4='50' data-5='50' data-6='50' data-7='50' data-8='50' data-9='50' data-10='50' data-11='50' data-12='50' data-13='50' data-14='0'></div>

</div>

Hey {{ c.first_name ~ c.last_name }}, friendly reminder that your subscription will expire on {{ $expiration_date|formatDate('yyyy-MM-dd') }}
```

This evaluates to:

```
Hey John Smith, friendly reminder that your subscription will expire on 2018-01-03
```

Obviously the date will change based on what kind of subscription the user has.

There are a couple of new features here:

* Defining a variable with `set $variableName = <expression>`. A valid expression has to return a single value of any type.&#x20;
* Arithmetic. You can do simple math inside a template. Conveniently, you can add also do arithmetic on a _date_ by using a [duration](../advanced#duration)
* Concatenation. You can concatenate multiple values into a single one using the `~` operator.

## Referencing custom app data

Dynamic contents and templating also allow you to reference custom application data to use in your messages.

These are tables of _key_/_value_ pairs that you can upload using our dashboard.

For example, given a table with the name `population_by_city` with the following content:

```
2988507,2244000
2996944,484344
2995469,850726
2973783,271782
3031582,239157
```

These are the population of Paris, Lyon, Marseille, Strasbourg and Bordeaux respectively.

You can now use them like this.

```
You live in a city of {{ lookup('population_by_city', b.city_code) }}
```

For someone in Paris, this evaluates to:

```
You live in a city of 2244000
```

You can use any attribute or literal value as the lookup key. This works too:

```
You live in a city of {{ lookup('population_by_city', 2988507) }}
```

However by doing this you lose the benefit of the custom app data table. This also works:

```
You live in a city of {{ lookup('population_by_city', c.my_custom_city_code) }}
```

## Language matching

The `speaks` function allows to customize contents according to the user language. It's recommended to use this function instead of the `b.language` native attribute as its value is not guaranteed to be stable. It accepts one or more languages as parameters, and returns true if the user language matches one of them according to the language matching rules.

## Referencing trigger event data

In the context of a trigger campaign, using data from the trigger event is possible by using the attribute named `trigger_event`. It is an object attribute that contains the attributes of the trigger event that triggered the campaign.

Here is how you can use it:

```
Your {{ trigger_event.product_name }} is waiting for you !
```

You can still access the trigger event label, tags and attributes using 3 specific functions:

* `triggerEventLabel()`: returns the label of the trigger event
* `triggerEventTags()`: returns the tag collection attached to the trigger event. It can be used the same way as the tag collections.
* `triggerEventAttr(attribute_key)`: returns the attribute value corresponding to the given key, it is the equivalent of `trigger_event.attribute_key`

Here are a few examples of how you can use them.

Using the product name the user added to its cart:

```
Your {{ triggerEventAttr('product_name') }} is waiting for you !
```

Or if the products are listed in the tag collection:

```
{{ triggerEventTags() | count }} items are still waiting for you in your cart !
```

## Use cases

After looking into how it works, let's look at some use cases for dynamic contents and templates that would otherwise be hard or even impossible to do.

### Electoral results

Suppose you want to report on electoral results for every city in France. There are currently 35416 cities in France and you want each user to have the result from their city when receiving the notification.

Without dynamic contents you could only do this by creating one campaign per city with a query matching the city. In that case you'd need more than 35k campaigns, this is obviously not good.

Instead you can do the following:

* create a table named `electoral_results_201710` for example.
* each row in the table should be `$city_code => $result`.

Example:

```
2988507,Yes 20.3% - No 79.7%
2996944,Yes 48.5% - No 51.5%
2995469,Yes 74% - No 26%
2973783,Yes 38% - No 62%
3031582,Yes 93.2% - No 6.8%
```

These are the results of Paris, Lyon, Marseille, Strasbourg and Bordeaux respectively.

* Then, create a message containing a lookup on the table and city code.

Example:

```
Election day result: {{ lookup('electoral_results_201710', b.city_code) }}
```

For someone in Paris this will evaluate to:

```
Election day result: Yes 20.3% - No 79.7%
```

Each user will have a customised message based on where he is.

### Loyalty program goals

Suppose you have a loyalty program for your application where the user can gain points and at some threshold you gain a loyalty level. Here is an example of a points scale:

* 100 points - regular
* 500 points - silver
* 1000 points - gold
* 5000 points - platinum

Suppose also that you attach special one time discounts every time the user gains a level.

Finally, suppose you want to remind a user that they're about to reach the next level with the following message:

```
Gain 55 more points to reach Gold and get a one time discount of 15%!
```

Let's break down what we need:

* the number of points to reach to get to a level
* the number of points that a user has to gain
* the discount for a level

**Prerequisites**

For this to work you need to feed us the data we'll be working with; you can do so using custom attributes or the Custom Data API.

We imagine the following user attributes:

`u.loyalty_points` an `integer` value representing the current number of points a user has

We also need two custom app data tables:

`loyalty_thresholds` containing this:

```
regular,100
silver,500
gold,1000
platinum,5000
```

**The query**

Before diving into the template let's look at what query we should use:

```
{
  "$or": [
    "$and": [
      "u.loyalty_points": {
        "$gte": 85
      },
      "u.loyalty_points": {
        "$lt": 100
      }
    ],
    "$and": [
      "u.loyalty_points": {
        "$gte": 475
      },
      "u.loyalty_points": {
        "$lt": 500
      }
    ],
    "$and": [
      "u.loyalty_points": {
        "$gte": 850
      },
      "u.loyalty_points": {
        "$lt": 1000
      }
    ],
    "$and": [
      "u.loyalty_points": {
        "$gte": 4950
      },
      "u.loyalty_points": {
        "$lt": 5000
      }
    ]
  ]
}
```

This will match any user that is just about to reach the next level.

**The template**

Here is how the template could look like:

```
Gain {{ $remaining }} more points to reach {{ $nextLevel|upper }} and get a one time discount of {{ $discount }}
```

### Special discounts after a purchase

Suppose you want to give a user a special discount if they didn't buy anything after a month, and at the same time you want to remind them what they bought.

Suppose also that the discount changes based on how much time has passed since the purchase:

* 20% after a month
* 40% after more than two months

For example you could have the following message:

```
Did you like your Nike Air Max ? Get a 20% discount on all purchase today!
```

Let's break down what we need:

* the product name of the last purchase
* the date of the last purchase

**Prerequisites**

Like before, for this to work you need to feed us the data we'll be working with; you can do so using custom attributes or the Custom Data API.

In this use case we'll use custom events so you need to have that working too.

We image the following user attributes:

`u.last_purchase_product_name` a `string` containing the product name of the last purchase. It should be a properly formatted string.

We also need one custom event:

`e.purchase` which tracks every time a user has purchased something.

**The query**

The query needs to filter users that haven't purchased anything since at least a month:

```
{
  "age(e.purchase)": {
    "$gte": "30d"
  }
}
```

**The template**

Here is how the template could look like:

Did you like your \{{ u.last\_purchase\_product\_name \}} ? Get a \{{ $discount \}} discount on all purchase today!
