Перейти к содержанию

Динамический контент

В теме и теле email рассылок можно использовать FreeMarker — механизм шаблонизации. С его помощью можно управлять динамическим контентом писем.

Есть три вида разметки:

  • ${...}: будет заменено на значение или выражение, указанное внутри фигурных скобок.
  • <#tag> - теги: похожи на HTML, но название начинается с #.
  • <#-- ... --> - комментарии: не попадут в конечное письмо, в отличии от комментариев HTML.

Вывод значений и выражений

Для вывода значений используется разметка ${...}. В данном примере мы использовали атрибуты name и email объекта contact

<html lang="en">
<body>
    <h1>Hi, ${contact.name}</h1> 
    <p>Thanks for registration!</p>
    <p>If you need help visit <a href="https://example.com/help?email=${contact.email}">Help</a> page</p>
</body>
</html>

Для пользователя John Doe с адресом электронной почты john@customer.net HTML письма примет следующий вид:

<html lang="en">
<body>
    <h1>Hi, John Doe</h1>
    <p>Thanks for registration!</p>
    <p>If you need help visit <a href="https://example.com/help?email=john@customer.net">Help</a> page</p>
</body>
</html>

Для проведения расчётов можно использовать выражения прямо внутри ${}:

<html lang="en">
<body>
    <h1>${contact.name?capitalize}, special offer!</h1>
    <p>Buy goods in the category "Everything for home"
        with a ${(1 + contact.loyalty_discount_rate)*20}% discount!</p>
</body>
</html>

В данном примере loyalty_discount_rate – пользовательский атрибут контакта, в котором указывается коэффициент повышения процента скидки для каждого контакта. И чтобы рассчитать конечную скидку, мы умножаем её на базовую скидку в 20%.

Поддерживаемые выражения

Ниже мы указали самые популярные выражения, подробнее смотрите в документации по freemarker.

  • Переменные. Вывод значения переменной - основной вид использования динамического контента в сообщениях и письмах. Помимо contact, можно создавать свои переменные
  • Работа со списками.
    • используйте EventInfoList[0] для получения доступа к любому элемента из списка.
    • ?first, ?last возвращают первый и последний элементы списка.
    • ?join(sep) объединяет все элементы списка:
      my list: ${list?join(",")}}
      
      // Output
      my list: 0,1,2,3
      
    • ?min, ?max возвращают наименьший и наибольший объект списка.
    • ?size - число элементов в списке.
  • Строки.

    • ?upper_case, ?lower_case, ?capitalize - все слова в строке будут приведены к верхнему или нижнему регистру или будут начинаться с прописной буквы.
    • ?length рассчитывает длину строки.
    • ?truncate обрезает текст до указанной длины:

      • ${"Women Shoes"?truncate(10)} -> "Women[...]", потому что данная функция в после обрезания строки прибавляет [...]

      • ${product.name?truncate(5, '---')} -> "Wo---"

  • Числа.

    • ?round округляет до ближайшего целого числа. Если оно заканчивается на 0.5, оно округляется в большую сторону.
    • ?floor округляет число в меньшу сторону.
    • ?ceiling округляет число в бошьшую сторону.
    • ?string используется для перевода числа в строку и форматирования чисел.

Определение переменных

Создание произвольной переменной и присвоение ей значения:

  • <#assign positionSum = 4200000> - создает числовую переменную,
  • <#assign subscriberTitle = "Attention"> - создает строковую переменную.

Математические операции

Могут быть использованы чтобы:

  • рассчитать размер скидки в рублях,
  • рассчитать размер скидки в процентах,
  • рассчитать, сколько подписчику необходимо накопить баллов для перехода на следующий шаг программы лояльности,
  • пересчитать цены с учетом персональной скидки.

Примеры:

  • ${positionSum * 0.50}
  • ${positionSum * 0.25 / 100}%
  • <p class="sale">${(product.oldPrice-product.price)/product.oldPrice*100}%</p>

Форматирование чисел

Преобразование вывода и округление.

Если требуется выводить размер скидки с одним разрядом после запятой, чтобы не получить значение 12.23472100012%.

  • Для примера берем price = 12.234721
    • ${price?string["0"]} - выведет 12
    • ${price?string["0.#"]} - выведет 12.2
    • ${price?string["0.##"]} - выведет 12.23
    • ${price?string["0.###"]} - выведет 12.235
    • ${price?string["0.####"]} - выведет 12.2347

Теги

Логические условия

Допустимы следующие логические конструкции:

<#if condition>
  ...
<#elseif condition2>
  ...
<#elseif condition3>
  ...
...
<#else>
  ...
</#if>

Пример с незаполненным именем подписчика

Например, если нужно вывести имя подписчика, то можно вывести его так: "Привет, ${contact.name}!"

При отсутствии имени у подписчика, он увидит текст с лишними запятой и пробелом "Привет, !"

Подходящие варианты:

  • "Привет<#if (contact.name?length>1)>, ${contact.name?capitalize}<!--#if-->!"
  • "Привет<#if contact.name??>, ${contact.name?capitalize}<!--#if-->!"
  • "Привет<#if contact.name?has_content>, ${contact.name?capitalize}<!--#if-->!"

Пример с выводом/сокрытием блока для подписчиков по условию

В письме магазина товаров для животных должно содержаться 3 баннера. Владельцу собаки не нужно показывать баннер, который подойдет владельцу кошки или попугая.

Если не указывать условия:

<a href="#"><img src="/banner-dog.png"></a><br />
<a href="#"><img src="/banner-cat.png"></a><br />
<a href="#"><img src="/banner-bird.png"></a>

С условием:

<#if ${contact.pet}="собака">
    <a href="#"><img src="/banner-dog.png"></a>
<#else>
    <a href="#"><img src="/banner-cat.png"></a>
    <a href="#"><img src="/banner-bird.png"></a>
</#if>

Циклы

Пример вывода массива товаров для триггеров

Верстальщик оформляет код одной карточки товаров, который с помощью цикла можно размножить по количеству выбранных для вывода в письме товаров.

<#list contact.EventInfoList as event>
    <div class="product">
        <a href="${event.productURL}"><img src="${event.productImg}" /></a>
        <p class="product-title"><a href="${event.productURL}">${event.productName}</a></p>
        <p class="product-price"><a href="${event.productURL}">Цена ${event.productPrice} руб.</a></p>
    </div>
</#list>

Пример фильтра в цикле

Клиент решает не показывать подписчикам товары дешевле 1500 рублей.

<#list contact.EventInfoList as event>
    <#if ${event.productPrice}<1500 ><#continue></#if>
    <div class="product"><a href="${event.productURL}"><img src="${event.productImg}" /></a>
    <p class="product-title"><a href="${event.productURL}">${event.productName}</a></p>
    <p class="product-price"><a href="${event.productURL}">Цена ${event.productPrice}} руб.</a></p>
</#list>

Пример проверки на наличие значений в цикле

Если цикл пустой - вывести сообщение о том, что нет товаров.

<#list contact.EventInfoList as event>
    <div class="product"><a href="${event.productURL}"><img src="${event.productImg}" /></a>
    <p class="product-title"><a href="${event.productURL}">${event.productName}</a></p>
    <p class="product-price"><a href="${event.productURL}">Цена ${event.productPrice}} руб.</a></p>
    <#else>
    No products
</#list>

Пример добавления разделителя между элементами цикла

Для добавления разделителя между элементами цикла можно использовать директиву <#sep>, которая добавлет код после каждого элемента цикла, кроме последнего.

<#list contact.EventInfoList as event>
    <p class="categoryTitle"><a href="${event.categoryUrl}">${event.categoryTitle}</a></p>
    <#sep>, </#sep>
</#list>

Отмена отправки сообщения

В некоторых ситуациях, особенно при обработке событию с вашего сайта, может понадобиться отмена отправки. Для этого используйте функцию cancelMessage(reason) в комбинации с проверкой по условию <#if>:

<html lang="en">
<body>
    <#if ${contact.loyalty_level} == 0>
        <#return cancelMessage("Низкий loyalty_level") />
    <#/if>
    <h1>${contact.name?capitalize}, special offer!</h1>
    <p>Buy goods in the category "Everything for home"
        with a ${(1 + contact.loyalty_discount_rate)*20}% discount!</p>
</body>
</html>

Объект "Contact"

Contact - объект, доступный в тексте сообщений и писем как contact для предоставления доступа к контактной информации из базы контактов.

Для доступа к атрибуту контакта вызовите его через точку: contact.attr. Базовые атрибуты контакта:

  • name - имя,
  • surname - фамилия,
  • phone - номер телефона,
  • email - адрес электронной почты,
  • gender - пол с возможными значениями gender.male и gender.female,
  • country - страна,
  • city - город,
  • birthdate - дата рождения,
  • creationDate - дата с временем создания контакта,
  • lastUpdate - дата с временем последнего изменения контакта,

Tip

Доступ возможен не только к базовым, но и пользовательским атрибутам.

Если сообщение отправляется по событию с вашего сайта, то у контата становится доступным атрибут EventInfoList - список передаваемых с сайта объектов.