Кастомная авторассылка в MailChimp из RSS-ленты

Все знают, как сделать рассылку. Многие умеют создавать триггерные цепочки. Кто-то умеет настроить рассылку из RSS-ленты блога. Нам пришлось закопаться глубже, потому что мы хотели, чтобы наша рассылка была не простой, а красивой и детальной. Ведь она делается из интересного блога, на который мы тоже потратили немало сил.


За каждую детальку в простом на вид письме пришлось побороться с этой симпатичной обезьянкой. Все получилось. Рассказываем — как.


MailСhimp — англоязычный и иногда нелогичный в интерфейсе сервис. Но он столько всего умеет и настолько популярен, что для него написали дотошные инструкции о доставке контента до читателей всеми возможными способами.


Мы для рассылок блога компании PromoPult также выбрали MailСhimp. Одна из фич MailСhimp — автокампании. Можно запланировать регулярные рассылки, отдельные письма, настроить приветственные письма и много всего.


Эта история — про настройку авторассылки постов из блога. Дайджест свежих материалов в почту подписчика один раз в неделю.



Стандартный вариант для авторассылки и почему он нам не подошел


У самого MailСhimp есть прекрасная документация по любым функциям, и конкретно об этом тоже есть: Share Your Blog Posts with Mailchimp. Переводы на русский язык тоже найдутся, разной степени адекватности.


Кратко, что нужно, чтобы сделать авторассылку:


  1. Создать отдельную RSS-ленту для MailChimp (или даже не создавать, а использовать стандартную ленту).
  2. Создать кампанию, указать источник, настроить условия отправки.
  3. Создать и выбрать шаблон.
  4. Готово. Вы — восхитительны!

Что не устроило нас — какие-то собственные вещи добавить просто невозможно.


Есть базовые данные из RSS-ленты, которые прекрасно понимает MailСhimp:


  • Базовая информация о ленте (название, ссылка, описание, дата формирования или обновления ленты) — *|RSSFEED|*.
  • Ссылка на отдельный пост — тег *|RSSFEED:URL|*, смотрит на <link> внутри <item> (здесь и далее).
  • Заголовок отдельного поста — тег *|RSSITEM:TITLE|*, смотрит на <title>.
  • Дата публикации отдельного поста — тег *|RSSITEM:DATE|*, смотрите на <pubDate>.
  • Текстовый анонс отдельного поста — тег *|RSSITEM:CONTENT|*, смотрите на <description>, если этого тега внутри <item> нет — MailChimp смотрит на <content:encoded>. Внутри можно использовать HTML-теги.
  • Полное содержание отдельного поста — тег *|RSSITEM:CONTENT_FULL|*, смотрит на <content:encoded>.
  • Изображение поста, часто — превью (миниатюра — в терминах WordPress) — тег *|RSSITEM:IMAGE|*, смотрит на <media:content> и не забудьте про дополнительные теги и атрибуты для медиа-вложений: возрастные маркировки, информация о самом файле и проч.

А у нас есть дополнительные штуки у отдельного поста:


  • Счётчик комментариев;
  • Счётчик просмотров;
  • Счётчик лайков;
  • Дату публикации поста хочется показывать в человеческом формате: во-первых, на русском языке, со склонениями и если пост опубликован в текущем году — не показывать год публикации (сейчас в блоге так всё и работает, в письмах хочется такого же внимания к деталям);
  • Отдельная кастомная обложка поста, до которой нужно как-то достучаться;
  • Категория с ссылкой на все посты из категории.

И в обычную RSS-ленту такое не засунуть — нет соответствующих тегов. Кастомные же теги MailСhimp не понимает и не стоит его винить в этом. Нужно искать решение, которое устроит всех и не сломается.


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


Кастомная авторассылка в MailChimp из RSS-ленты

Карточка поста блога PromoPult в еженедельном дайджесте



Как мы решили задачу


Создание RSS-ленты


Первым делом важно создать отдельную RSS-ленту для MailChimp. В блоге PromoPult уже есть несколько подобных лент: для Яндекс.Дзена и для Турбо-страниц.


Создать новую ленту можно через add_feed(). Вот такой код в файле функций темы:


functions.php:


/* start Добавляем ленту для рассылки постов через MailChimp */
  add_action( 'init', 'customRSSforMC' );
  function customRSSforMC() {
    add_feed( 'mchimp', 'customRSSforMCFunc' );
  }
  function customRSSforMCFunc() {
    get_template_part( 'rss', 'mchimp' );
  }
/* end Добавляем ленту для рассылки постов через MailChimp */

В строке №7 get_template_part( 'rss', 'mchimp' ); — указывает на то, что шаблон для ленты лежит в корне папки темы и называется rss-zen.php.


После создания файла и добавления функции нужно зайти в админку WordPress, настройки ЧПУ: «Консоль > Настройки > Постоянные ссылки» и нажать кнопку «Сохранить изменения», чтобы WordPress обновил настройки урлов и по заданному /feed/URL в первом параметре строки №4 открывалась новая RSS-лента.


Сделать это нужно один раз при создании ленты.


Смотрите наш пример: https://blog.promopult.ru/feed/mchimp


Что внутри ленты


Внутри самой ленты — обычный цикл постов WordPress: query_posts(). Это позволяет выбирать и фильтровать посты очень гибко: как если бы вы настраивали отдельные категории, страницы с выборками, архивами и всем, что нужно для подборок материалов в WordPress.


Но перед тем как прийти к идеальному решению задачи — было несколько попыток запихнуть важные для письма данные внутрь стандартных конструкций RSS-лент и использовать их в MailChimp.


Например, был такой вариант для счётчика комментов:


<item>
    [...]
  <title><?php the_title_rss(); ?></title>
  <link><?php the_permalink_rss(); ?>?utm_source=newsletter</link>
    
    // если комментариев больше или равно 1, то показать количество
    <?php if (get_comments_number() >= 1) { ?>
      <commentsCounter><?php comments_number('0', '1', '%'); ?></commentsCounter>
    <?php } ?>
  
    [...]
</item>

Такой вариант, конечно, срабатывает в плане данных: всё, что нужно, получается и корректно выводится. Но MailChimp не понимает тега <commentsCounter>, как и любых других нестандартных тегов.


Так же, например, с датами. У MailChimp есть свой тег: *|RSSITEM:DATE:d/m/y|*, и ему можно передавать опции форматирования даты. Но, к сожалению, в письме это выглядит совсем не человечно. Про перевод даты вообще можно не говорить.


Ещё проблема — картинки. Вы страдали и сверстали своё прекрасное письмо. Вам нужно вывести картинку. В шаблоне письма вы делаете так:


<img 
  src="*|RSSITEM:IMAGE|*"
  alt="*|RSSITEM:TITLE|*"
/>

Но парсер MailChimp может приходить и ломать вёрстку, добавляя свои свойства, классы и другой код в тег картинки <img ... />.


Совет. Если вы используете стандартную ленту и теги, то не забудьте включить галочку «Изменение размера изображений RSS-канала в соответствии с шаблоном» в настройках кампании:


Кастомная авторассылка в MailChimp из RSS-ленты

Промежуточные выводы: что-то идёт не так, стандартных вариантов не хватает, письмо страшное и не человечное. Нестандартных данные не вывести.


Делаем финт ушами: все размечаем сами


Если стандартного ничего нельзя сделать в RSS ленте, чтобы парсер сервиса MailChimp это правильно понял, то можно передать готовый размеченный и свёрстанный кусок кода для карточки поста просто в теге <description> отдельного элемента <item> в ленте.

Есть только отдельный минус: все стили для письма должны быть заинлайнены, то есть всё, что описано через .class превращается в стили в атрибуте style=”...”.


<!-- до инлайна так: -->
<style>
  .post-meta {
    Margin: 8px 0;
  }

  .post-category {
    border-radius: 3px;
    border: #adb2b2 1px solid;
    color: #adb2b2 !important;
    border-bottom: #adb2b2 1px solid !important;
    padding: 2px 6px;
    font-size: 13px;
    line-height: 13px;
    Margin: 0 8px 0 0;
  }
</style>

<div class="post-meta">
  <a 
     href="https://blog.promopult.ru/category/seo" 
     target="_blank"
     class="post-category">SEO: поиск и внутренняя оптимизация</a>
</div>

<!-- после инлайна так: -->

<div style="Margin: 8px 0;">
  <a 
     href="https://blog.promopult.ru/category/seo?utm_source=newsletter" 
     target="_blank"
     style="Margin: 0 8px 0 0; border: #adb2b2 1px solid; border-bottom: #adb2b2 1px solid !important; border-radius: 3px; color: #adb2b2 !important; font-size: 13px; line-height: 13px; padding: 2px 6px; text-decoration: none;">SEO: поиск и внутренняя оптимизация</a>
</div>

Для вёрстки писем блога использовался «Печкин» — gulp-сборщик шаблонов писем, который собирает письмо из блоков и сам инлайнит стили. Также можно пользоваться онлайн-инлайнерами стилей, например, Premailer.io.


В шаблоне RSS-ленты доступен цикл постов. Поэтому можно вытащить и сформировать всё как хочется и нужно.


Первый подход к решению был частичным: оставить стандартными теги заголовка, урла, краткого описания, а вот мета-информацию поста: просмотры, лайки, комменты, категорию и дату публикации формировать отдельным куском HTML-кода и вставлять в нужное место разметки.


От этого варианта также пришлось отказаться из-за сломавшейся вёрстки и отсутствия контроля над разметкой и стилями картинки. И позже перенести всю разметку блока карточки поста в тег <description>.


<?php while (have_posts()): the_post(); ?>
  <item>
    <description><![CDATA[
      <div class="post-card">
      <?php if ( get_post_meta($post->ID, 'imga', true) ) { ?>
        <div class="post-card__img">
          <a href="<?php the_permalink(); ?>?utm_source=newsletter" target="_blank">
            <img 
              src="<?php echo $postImg[0]; ?>" 
              alt="<?php the_title(); ?>">
          </a>
        </div>
      <?php } ?>
        <div class="post-card__info">
          <h2>
            <a href="<?php the_permalink(); ?>?utm_source=newsletter"><?php the_title(); ?></a>
          </h2>
          <p>
            <a href="<?php the_permalink(); ?>?utm_source=newsletter">
              <?php if ( !empty( get_post_meta($post->ID, 'intro', true) ) ) {
                echo get_post_meta($post->ID, 'intro', true);
              } else {
                $content = get_the_content(); $trimmed_content = wp_trim_words( $content, 12, '...' ); echo $trimmed_content;
              } ?>
            </a>
          </p>
          <div>
            <p>
              <?php if (get_the_date('Y') == date('Y')) { the_time('j F'); } else { the_time('j F Y'); } ?>,
              <?php
              $categories = get_the_category();
              if( $categories[0] ) {
                echo '<a href="' . get_category_link($categories[0]->term_id ) . '?utm_source=newsletter">'. $categories[0]->name . '</a>';
              }
              ?>
            <?php if(function_exists('the_views')) { ?>
              <span>
                <span>
                  <img 
                    src="icon-views.png" 
                    alt="Просмотры поста">
                </span>
                <span class="item__text"><?php the_views(); ?></span>
              </span>
            <?php } ?>
            <?php if (function_exists('get_simple_likes_counter')) { if (get_simple_likes_counter( get_the_ID() ) >= 1) { ?>
              <span>
                <span class="item__icon">
                  <img 
                    src="icon-like.png"
                    alt="Лайки поста">
                </span>
                <span><?php echo get_simple_likes_counter( get_the_ID() ); ?></span>
              </span>
            <?php } } ?>
            <?php if (get_comments_number() >= 1) { ?>
              <span>
                <span>
                  <img 
                    src="icon-comments.png"
                    alt="Комментарии поста">
                </span>
                <span><?php comments_number('0', '1', '%'); ?></span>
              </span>
            <?php } ?>
            </p>
          </div>
        </div>
      </div>
    ]]></description>
  </item>
<?php endwhile; wp_reset_query(); ?>

В примере кода нет инлайн-стилей, чтобы всё выглядело аккуратно. Боевой же вариант ленты отдаётся с полной разметкой и стилями.


Все адреса для графики в примере также упрощены. В боевом варианте все нужные картинки, иконки, фотографии и всё, что важно для письма, — залиты в админку MailChimp через Content Studio, а уже в шаблонах использованы адреса полного вида для src-атрибутов тегов <img />.


В строках №№20—24 мы выбираем вариант текста-анонса (интро) статьи. Если заполнен кастомный в свойствах поста в произвольных полях записи — get_post_meta(), то показываем его, если его нет, то показываем то, что лежит в get_the_content().


Также выбираем картинку-обложку поста. У нас есть две картинки, связанные со статьей: небольшое превью (отображается в карточке поста на главной странице) и обложка из шапки поста. Берем большую обложку.


Кастомная авторассылка в MailChimp из RSS-ленты

Пример шапки с фоном в посте блога PromoPult


Поскольку всё это происходит в стандартном цикле WordPress, то доступны все способы сортировок. Например, показать самое просматриваемое и залайканные за последние 12 дней, отсортировав от большего к меньшему количеству лайков.


Вывод контента из ленты в шаблоне письма


Поскольку все данные для отдельной карточки поста находятся внутри тега <description>, вложенного в отдельный элемент <item>, то достаточно только его и показать в шаблоне письма:


<h1>Свежие материалы недели в блоге PromoPult</h1>
<p>*|RSSFEED:DESCRIPTION|*</p>
<!-- 
  *|RSSFEED:DESCRIPTION|* покажет: «21 августа — 28 августа», 
  из тега <description> общей ленты 
-->

*|RSSITEMS:|*
  *|RSSITEM:CONTENT|*
*|END:RSSITEMS|*

Данные корректно отображаются, HTML-код вставляется в цикле и автокампания работает.


Отдельной строкой про RSSFEED и FEEDBLOCK


Чем отличается *|RSSFEED|* и *|FEEDBLOCK|*?


В различиях разобраться просто:


  • *|FEEDBLOCK|* можно использовать внутри любых шаблонов писем и кампаний. Например, хотите в периодическом выпуске рассылке рассказать про последние посты — используйте его. Указать можно ссылку на любой RSS-источник.
  • *|RSSFEED|* работает только в автокампаниях и в качестве источника видит то, что указано в настройках кампании.

ИТОГО: Если у вас все стандартно и несложно, юзайте стандартные средства MailChimp и не парьтесь


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


Как — мы рассказали.


Ссылки на тему RSS-лент в MailChimp:


  • Feedblock RSS Merge Tags — документация про использование тегов *|FEEDBLOCK|* в шаблонах писем
  • RSS Merge Tags — документация про тег *|RSSFEED|* в шаблонах писем
  • Email Design Reference > RSS Merge Tags — начало работы с MailChimp и использование блоков RSS-лент в шаблонах писем

Комментарии (3)


  1. ghostinushanka
    11.09.2019 23:31

    А потом выясняем что обезьянки до сих пор не умеют в кастомный «Return-Path» из-за которого не проходят проверки dmarc (SPF alignment) и либо уходим к другому сервису, либо выключаем dmarc на своём домене.


    1. PromoPult Автор
      12.09.2019 13:32

      Кажется, что до наступания на эту штуку нужно как-то дорасти и точно смотреть либо на собственное решение, либо выбирать сервисы по другим параметрам.


      MailChimp — клёвый и всё, что есть в его коробке позволяется быстро создать и управлять рассылками для каких-то маленьких и средних дел: блоги, сайты, магазины, сообщества. Даже в бесплатном тарифе.


      А расскажите, пожалуйста, свою историю, зачем кастомный Return-Path и в какой момент понадобилось и для каких задач?


      1. ghostinushanka
        13.09.2019 21:50

        Чтобы наступить на эту штуку, достаточно поддерживать все стандарты борьбы со спамом
        Про DMARC и как он относится к SPF и DKIM можно почитать вот тут и вот тут. На хабре об этом писало как минимум мейлру в своём блоге пару лет назад.

        Если вкратце, как только вы хотите чтобы от имени вашего домена, например promopult.ru кто-то другой посылал почту, например mailchimp и вы не хотите чтобы она не падала в спам у нормальных провайдеров, вам нужно разрешить на уровне ваших DNS записей это делать. Последнее требование, чтобы домен из «from» соответствовал домену из «return-path». В противном случае это автоматический фейл проверки. А обезьянки настраивать это не позволяют (и год назад походу даже не понимали зачем это надо, вот твит тред)