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

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

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

Доступны три вида разметки:

  • ${...}: будет заменено на значение или выражение, указанное внутри фигурных скобок.
  • <#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.attr.

Базовые атрибуты контакта:

Параметр Описание
name Имя.
surname Фамилия.
phone Номер телефона.
email Адрес электронной почты.
gender Пол с возможными значениями gender.male и gender.female.
country Страна.
city Город.
birthdate Дата рождения.
creationDate Дата с временем создания контакта.
lastUpdate Дата с временем последнего изменения контакта.

Совет

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

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