Рассылки по сегментам на основе MailChimp

    Привет, Хабр! Сегодня я расскажу о том, как можно интегрировать сервис почтовых рассылок mailchimp на своем сайте.
    Сервис дает множество возможностей:
    — расширенный трекинг;
    — выборки пользователей;
    — красивые шаблоны писем;
    — интеграция с социальными сетями;
    — интеграция с Google Analytics;
    — экономия времени на разработку своего проекта.
    На основе этого сервиса мы сделали автоматическую рассылку спецпредложений по целевым срезам — определенным вендорам и категориям продуктов. Попробуем вкратце рассказать о некоторых особенностях реализации.


    Создание списка пользователей.
    Рассылки в mailchimp строятся на основе списка пользователей, поэтому первым делом, в личном кабинете mailchimp.com, создадим такой список: Lists — Create List. Мой список называется «спецпредложения», в нем находятся пользователи, подписавшиеся на новости и акции нашего интернет-магазина. После создания списка необходимо узнать его уникальный номер: Lists — спецпредложения — Settings — List Settings and Unique ID, чтобы работать с этим списком через API.



    Создадим группы пользователей в списке, в моем случае это вендоры и категории: Lists — спецпредложения — Groups — View Groups

    Вот, например, секция вендоров:


    При создании групп нужно учесть, что кроме названия никаких дополнительных параметров больше нет, а это усложняет создание связи между
    группой и вашей базой данных. Мы остановились на составном названии группы, первая часть — число — код вендора/категории в нашей бд, вторая — отображаемое имя вендора/категории.

    Кстати, самих групп нельзя создать больше 60, и эта важная информация хранится в виде комментария к одному из методов API.

    Импорт пользователей в список рассылки.
    Обычно пользователи попадают в список рассылки через форму подписки, но можно их загрузить целой пачкой через механизм импорта. (Lists — спецпредложения — import.) Возможности «откуда» довольно большие, имеется импорт из файлов, гугл контактов, документов и т. д. Импортировать можно сразу в определенные группы.



    Обратите внимание, что в бесплатной версии есть ограничение на 2000 подписчиков, поэтому если вы загрузите туда большее число e-mail адресов, появится сообщение «You've hit your sending limit. Your Forever Free plan can only send while your total subscriber count (all lists combined) is at or under 2000. upgrade to re-enable» и запускать рассылки уже не получится, даже если в рассылке участвуют не все подписчики, а лишь небольшой сегмент.

    Также после импорта вы, скорее всего, увидите сообщение «Our review team recently emailed you some questions. Before we can approve your account for sending email campaigns, we need your reply». В нём просят рассказать о вашей компании, указать откуда вы берете списки пользователей – в общем, пройти своеобразную верификацию. Вот объяснение, для чего нужна такая проверка: kb.mailchimp.com/article/why-is-my-account-under-review

    API MailChimp
    После того как создан список пользователей можно приступить к созданию первой рассылки. Создание и запуск рассылок через панель управления mailchimp нас не интересует, так как нам нужна автоматическая система. Поэтому идем сразу изучать API MailChimp.
    На текущий момент API имеет версию 1.3 и находится тут: apidocs.mailchimp.com/api/1.3

    Практически всё, что можно делать через панель управления, реализовано в методах API и есть набор готовых классов-оберток для различных языков. Вот для php: apidocs.mailchimp.com/api/downloads/#php

    Для работы с API необходим ключ, который можно создать в личном кабинете:



    Пример работы с API:
    <?php 
    require_once('MCAPI.class.php');
    
    //ключ API
    $apiKey = 'd43a8xxxxxxxxxxxxxxxxxc6867cbd-us4';
    
    //ID списка пользователей
    $listId = '8e2xxxxx44';
    
    $mailchimpAPI = new MCAPI($apiKey);
    
    //получаем список групп у списка пользователей
    $groups = $mailchimpAPI->listInterestGroupings($listId);
    
    print_r($groups);
    
    

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


    На скриншоте видна выборка пользователей по 3 разным сегментам: группы, язык, местоположение. Вообще выборки могут быть довольно сложными и для создания таких выборок сделали даже отдельный инструмент — HairBall, подробнее тут: blog.mailchimp.com/introducing-hairball-an-air-app-for-really-complicated-mailchimp-lists

    В нашем проекте мы используем только сегменты по группам (вендоры/категории). Вот пример создания рассылки на основе групп:

    $opts= array(
    	'list_id'	=> $listId,
    	'from_email'	=> 'почта отправителя',
    	'from_name'	=> 'название отправителя',
    	'tracking'	=> array('opens' => true, 'html_clicks' => true, 'text_clicks' => false),
    	'authenticate'	=> true,
    	'analytics'	=> array('google'=>'UA-XXXXXX-2'),
    	'subject'	=> 'Тема письма',
    	'title'		=> 'Заголовок рассылки',
    );		
    		
    $content = array(
    	'html' => 'html тело письма',
    	'text' => 'plain text тело письма',
    );
    		
    $segmentGroups = array(
    	'match' => 'any', 
    	'conditions' => array(
    		array('field' => 'interests-5555', 'op' => 'all', 'value' => '17#ABBYY, 19#Adobe Systems, 20#McAfee Inc'),
    	array('field' => 'interests-4444', 'op' => 'all', 'value' => '88#Антивирусы. Безопасность, 99#Офисные программы, 77#Операционные системы'),
    	)
    );
    
    //создание рассылки
     
    $campaignId = $mailchimpAPI->campaignCreate('regular', $opts, $content, $segmentGroups);
    //запуск рассылки
    if ($campaignId) {
    	$mailchimpAPI->campaignSendNow($campaignId);
    }
    

    В массиве $opts задаются настройки рассылки, в массиве $content — содержимое письма, html и plain text.

    В параметре $segmentGroups, должен быть специально сформированный массив с сегментами пользователей из списка.

    Если сегментом является группа (наш случай), то имя сегмента должно состоять из префикса 'interests-' + ID корневой группы (называется вообще groupings — группировка), а значением — перечисленные через запятую названия групп.

    Как видно 5555 и 4444 — это id корневых групп, в нашем случае вендоров и категорий.

    Узнать id корневых групп и всю информацию по группам можно через метод listInterestGroupings

    $groups = $mailchimpAPI->listInterestGroupings($listId);
    print_r($groups);
    

    apidocs.mailchimp.com/api/1.3/listinterestgroupings.func.php

    Видно, что API поддерживает выборку по нескольким сегментам. В моём случае это 2 группы, а также поддерживает различные условия, как между сегментами — ключ match = «any» (ИЛИ), match = «all» (И), так и внутри сегментов — ключ op = «all» (полное совпадение со списком в value), op = «one» (одно из совпадений со списком в value).
    apidocs.mailchimp.com/api/1.3/campaigncreate.func.php

    Вернемся к массиву $content — откуда брать текст письма?
    Тут есть несколько ситуаций – например, менеджер в админке mailchimp может выбрать симпатичный шаблон письма, а их там много, отредактировать текст на нужный, сохранить в «мои шаблоны». Далее через метод templates(), (http://apidocs.mailchimp.com/api/1.3/templates.func.php) мы получаем ID нужного шаблона и создаем рассылку на основе него (в массиве $opts метода campaignCreate() нужно указать ключ template_id).

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

    Метод campaignCreate() создаст кампанию и вернет ее ID, саму кампанию можно будет наблюдать в списке кампаний в панели управления mailchimp, а после выполнения campaignSendNow() произойдет запуск рассылки, начнут отправляться письма.



    По отправленным рассылкам можно смотреть отчеты. Вот, например, отчет по рассылке некой тестовой группе:


    В итоге мы написали скрипт, который:

    1. выбирает новые спецпредложения из нашей бд
    2. ищет группы пользователей в mailchimp на основе выборки спецпредложений (спецпредложения привязаны к вендору/категории)
    3. генерирует текст письма на основе макета с прикрученными тегами Twig, с блоками топовых, дополнительных спецпредложений, блоком менеджера, баннерами и т.д.
    4. запускает рассылку и отмечает время последнего запуска
    5. переходит к п.1 на следующий день :)

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



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

    Воспользуемся API.
    Подписка пользователя представлена 2 методами: listSubscribe — создание подписки для нового пользователя и listUpdateMember — обновление подписки пользователя:
    apidocs.mailchimp.com/api/1.3/listsubscribe.func.php
    apidocs.mailchimp.com/api/1.3/listupdatemember.func.php

    Методы практически одинаковые, например указание ключа update_existing = true превращает listSubscribe() в listUpdateMember()

    Будем рассматривать только метод listSubscribe, так как он более полный:
    $mailchimpAPI->listSubscribe($listId, $email, $mergeVars, $emailType, $doubleOptin, $updateExisting, $replaceGroups, $sendWelcome);
    

    Важные параметры:
    • $listId — ID списка пользователей
    • $email — почтовый адрес пользователя, подписку которого надо создать или обновить
    • $mergeVars — массив с изменяемыми данными, например группы
    • $updateExisting — обновлять подписку, если она уже есть
    • $replaceGroups — заменить группы, если они есть в $mergeVars или объединить с существующими

    Для обновления групп пользователя нам нужен параметр $mergeVars, где ключ id — это id корневых групп (вендоры и категории), а ключ groups — перечисленные через запятую названия групп:

    $mergeVars = array('GROUPINGS' => array(
    	array(
    		'id' => '4444', 
    		'groups' =>  '99#Офисные программы, 77#Операционные системы'
    	),
    ));
    

    Также выставляем $replaceGroups = false для объединения уже существующих групп с новыми в $mergeVars.

    Для полной замены групп на новые нужно во-первых выставить $replaceGroups = true, а во-вторых в $mergeVars передавать весь массив корневых групп с пустыми значениями самих групп.
    $mergeVars = array('GROUPINGS' => array(
    	//останутся только эти группы
    	array(
    		'id' => '4444', 
    		'groups' =>  '99#Офисные программы, 77#Операционные системы'
    	),
    	//удаляем группы
    	array(
    		'id' => '5555', 
    		'groups' => ''
    	),
    	//удаляем группы
    	array(
    		'id' => '7777', 
    		'groups' => ''
    	),
    ));
    

    То есть параметр $replaceGroups=true работает в пределах одной корневой группы, а не всех.

    Используя этот метод мы сделали 2 варианта формы:
    1. Для всех пользователей – обычная форма с полем email и скрытыми полями для групп рассылок в зависимости от текущей страницы.
    2. Форма в личном кабинете, где отображается список чекбоксов из групп на которые можно подписаться/отписаться.

    Особенности метода listSubscribe:
    1. Если подписка новая, то вся ее обработка переходит на сервис mailchimp, высылается письмо с подтверждением подписки, после подтверждения дается ссылка на профиль подписчика, где он может редактировать свои данные, профиль опять же находится на сайте mailchimp.
    2. Если email пользователя уже есть в списке рассылки, то метод выдаст ошибку и предложит вручную отредактировать личные данные и группы подписчика, ссылка на профиль придет в тексте ошибки $mailchimpAPI->errorMessage. Надо указывать $updateExisting=true — чтобы сделать обновление подписки, но этим ключом можно перезаписать и чужую подписку, поэтому это не подходит для неавторизованного пользователя.

    В итоге у нас 2 проблемы:
    1. Вся обработка нового подписчика происходит не у нас, мы не можем на ее повлиять, например, выставить группу рассылки.
    2. Непонятно как обновлять подписку неавторизованному пользователю, так как мы не можем быть уверены, что указанный email принадлежит ему.

    Поэтому мы отключили у listSubscribe отправку писем с подтверждением подписки — параметры $doubleOptin = false, $sendWelcome = false и написали механизм, который:

    1 — при отправке формы подписки на нашем сайте высылает письмо с уникальной ссылкой-подтверждением.
    2 — обработчик ссылки который жестко создает или обновляет подписку, используя $doubleOptin = false, $sendWelcome = false, $updateExisting = true. Теперь мы уверены что указанный email действительно принадлежит неавторизованному пользователю, так как он перешел по ссылке в своем письме.

    Надо понимать, что с параметром $doubleOptin = false мы подписываем/обновляем подписку любого пользователя без его подтверждения, поэтому такой подход стоит использовать только там, где вы точно уверены что данная подписка принадлежит текущему пользователю, например в личном кабинете или при переходе по уникальной ссылке.

    В итоге:
    На основе рассылок mailchimp вполне реально сделать систему автоматических рассылок по определенным сегментам — группам вендоров и категориям продуктов, сделать формы подписки и отписки на определенные сегменты, кастомизировать шаблоны писем. Всю логику подписки/отписки можно перенести на свой сайт и реализовать ее по своему усмотрению, оставив за самим сервисом отправку писем и сбор статистики.

    Автор: Андрей Рябин — разработчик Softline
    Softline
    Компания

    Похожие публикации

    Комментарии 12

      0
      Как нынче с готовыми шаблонами? Наблюдал много косяков отображения на российских почтовых веб-мордах.
        0
        Что касается шаблонов, то можно использовать следующие:
        mailchimp.com/resources/html-email-templates/
        mailchimp.com/features/designer-templates/
        Но в любом случае придется часть дорабатывать и грамотный верстальщик очень пригодится.

          0
          Ключевой момент «придется дорабатывать». Печаль. Мне же проще самому сверстать — быстрее будет. Могу предложить почитать мои первые топики. Избавит от многих экспериментов.
            0
            Спасибо. Отмечу, лишь то, что данные в шаблон подставляются динамичеси, заранее не известно сколько будет спецпредложений в рассылке, поэтому подставлять теги шаблонизатора вместо контента все равно придется.
        0
        Отличное описание, большое вам спасибо, про mailchimp всё ещё не много толковых инструкций на русском языке, что создаёт барьер для людей с трудностями восприятия инструкций на английском.
          0
          Пользуясь случаем хочу спросить — а существует ли какое-нибудь готовое open source решение по рассылке почты по своей базе адресов, но не phplist (на его код смотреть страшно). Понятно что надо будет писать некий код по интеграции, но хотелось бы чтобы кто-то взял на себя функцию правильной рассылки почты.
            +1
            Про open source решение сказать сложно, но лично у нас на проектах используется
            marketion.ru
            mailchimp.com
            и наше самостоятельно решение. Также можно посмотреть
            sendgrid.com
            aws.amazon.com/ses
            www.unisender.com/ru/
              0
              marketion.ru — чистые спамеры, соответствуют всем критериям
              по году от них валится спам одинаковый, всё идёт на…

              abuse@slicehost.net (for slicehost.net)
              abuse@rackspace.com (for slicehost.net)
              abuse@slicehost.com (for slicehost.net)

              ну и quick.spam.spamcop.net, spam@uce.gov, webcomplaints@ora.fda.gov, anonymous@submit.spam.acma.gov.au, knujon@coldrain.net заодно
            0
            С простой рассылкой справляются почти все, в том числе российские Унисендер, Маркетион. Но если вам нужны посложнее рассылки, транзакционные письма, формирование писем в зависимости от действий посетителя на сайте, с сегментацией, то тут лучше подумать навырост. Это уже решения типа Mailchimp и постарше.
              0
              Скажите, правильно ли я понял, что вам удалось отключить совсем штатный механизм подтверждения подписки, используя $doubleOptin = false, $sendWelcome = false? Какой версией API вы пользовались?
                0
                да, подтверждение подписки происходит полностью на нашей стороне, версия API 1.3
                  0
                  C отпиской другая ситуция, если нужна ссылка на моментальную отписку в каждом письме, то такую ссылку может дать только сам сервис, можно конечно давать ссылку на профиль пользователя на вашем сайте, в котором он может авторизовавшись отписаться, но это не очень хорошее решение

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

                  Самое читаемое