RFM на 52 донорах: стоила ли игра свеч?


Как вы знаете из этой статьи, мы в LANSOFT активно поддерживаем фонд «Хранители детства», а они, в свою очередь, поддерживают все (ну почти) наши идеи по развитию и автоматизации коммуникаций.
Фонд небольшой: за 2025 год к ребятам пришли с поддержкой всего 52 активных донора и принесли чуть больше 300 000 рублей пожертвований. Все письма благотворителям сотрудники составляли и отправляли сами: спасибо за перевод, ваши деньги были потрачены на то или это, история подопечного или аккуратное напоминание тем, кто давно не проявлял себя. И занимались этим менеджеры, у которых основная работа – подростки, наставники и стажировки, а не рассылки. Каждое письмо – это зайти в выгрузку, глазами найти нужных людей, скопировать текст из шаблона, поправить обращение…
В общем, мы решили автоматизировать такие коммуникации в CDP CleverData Join и настроить их по методу RFM-анализа. Отдельной кнопки «собрать RFM» в CleverData Join нет, и это сознательное решение. Вместо закрытого функционала в некоторых CDP, который считает RFM по своим внутренним правилам, наша платформа дает конструктор – вычисляемые атрибуты профиля и сегменты на DMPQL, из которых RFM собирается под задачу конкретного клиента. Ниже расскажем, как мы это делали и, главное, как выбирали пороги, когда данных мало и взять больше негде.
База про RFM
R – Recency, F – Frequency, M – Monetary, параметры или условные оси, означающие давность последней покупки, частоту покупок и деньги. По каждой оси человеку присваивается балл, обычно от 1 до 3 или от 1 до 5, и дальше комбинация баллов превращается в сегмент: «чемпионы», «спящие», «новички».
Метод старше многих из нас: его придумали в торговле товарами через бумажные каталоги, каждая такая отправка стоила немалых денег и необходимо было решать, кому вообще отправлять каталог. С тех пор метод интегрировался в различные индустрии – в e-commerce, подписочные сервисы, банки, телеком. Причина простая: для анализа нужны три числа, которые есть у любого бизнеса с платежами, никакого ML, LLM и ИИ, результат можно объяснить за минуту, а эффективность доказана десятилетиями.
Почему именно фонд
Донорская база в ряде аспектов ведет себя как клиентская. Человек сначала жертвует часто, потом реже, потом перестает – и ни один менеджер не заметит этого вовремя, если будет смотреть невооруженным глазом. Отличий от ритейла всего два. Первое: главная метрика здесь не выручка, а удержание. Регулярная поддержка в долгосрочной перспективе ценнее разового пожертвования. У фонда 81% всех полученных от жертвователей средств приносят 27 рекуррентных доноров, а годовой вклад одного такого донора – около 9 000 рублей. Второе: апсейл заменяется переводом разового донора в подписку.
И отдельная причина, по которой мы вообще взялись за RFM на такой крохотной базе: сегменты нужны не столько для аналитики, сколько как входные точки для триггерных цепочек. Пока фонд маленький, ценность сегментации в том, что она снимает с людей ручную работу.
Как RFM устроен в платформе CDP CleverData Join
Механика следующая: у профиля в CDP есть вычисляемые атрибуты, и платформа сама считает по событиям суммы и количества за нужный период, а результат хранится прямо в профиле. Поверх этих атрибутов на DMPQL описываются сегменты. На этих двух основах строится RFM-анализ: атрибуты дают значения R, F и M, а сегментация режет их на бины. Одну особенность надо учесть: по умолчанию сегменты не взаимоисключающие, один профиль спокойно попадает в три сразу. Для RFM это критично, каждый профиль должен лежать строго в одном сегменте, иначе донор получит три разных письма в одной ситуации.
Вариантов было два: считать бины снаружи и заливать готовый атрибут в профиль либо собрать сегменты так, чтобы условия физически не пересекались. Выбрали второе, но с подготовкой: сначала завели семь агрегатных атрибутов, которые считают суммы и количества платежей в трех временных окнах.
Атрибут | ID | Что считает |
|---|---|---|
Дата последнего платежа | 50010 | last(attr(10001)) |
Кол-во платежей, 0-60 дней | 50023 | attr_count(attr(30079)) |
Кол-во платежей, 60-180 дней | 50022 | attr_count(attr(30079)) |
Кол-во платежей, >180 дней | 50021 | attr_count(attr(30079)) |
Сумма платежей, 0-60 дней | 50033 | sum(attr(30074)) |
Сумма платежей, 60-180 дней | 50032 | sum(attr(30074)) |
Сумма платежей, >180 дней | 50031 | sum(attr(30074)) |
Фильтр событий везде один – совершённый донорский перевод: CloudPayments[attr(30079) like “Completed”], период вычисления 365 дней, пересчет ежедневный. Без этих атрибутов выражения сегментов превратились бы в простыню из вложенных условий по событиям, которая еще и считается втрое дольше.
Пороги: как не подгонять их под 52 человека
Канонический способ выбрать пороги в RFM-анализе означает нарезать базу на квантили: берем терцили по каждой оси, получаем 3x3x3. Но на 52 донорах это не работает: терцили пляшут от пересчета к пересчету, один крупный платеж сдвигает границу, и сегмент «чемпионы» меняет состав без всякой причины со стороны благотворителей.
Поэтому пороги мы зафиксировали по смыслу платежного цикла, а не по распределению. Вот что было под руками из данных фонда за 2025 год: средний чек рекуррентного платежа 1 711 рублей, разового – 1 678, в среднем 5,3 платежа в год у регулярного донора, retention регулярных 59%.
И получилось следующее:
Recency: 60 и 180 дней. Рекуррент платит раз в месяц. Если был один пропуск, то могла возникнуть техническая ошибка, и списание не прошло. Два пропуска подряд – это уже не случайность, а сломавшаяся подписка или решение уйти. Отсюда 60 дней как граница «активен». 180 – полгода, после которых реактивация почти не срабатывает и человек переходит в разряд «возможно, когда-нибудь он вернется сам».
Frequency: платежи в месяц, а не за год. 5,3 платежа в год – это примерно 0,44 в месяц. Считать частоту за год бессмысленно: донор, пришедший в ноябре, и донор с января получат несравнимые числа. Поэтому F сейчас приводится к месяцу: больше 2 – высокий, от 1 до 2 – средний, меньше 1 – разовый.
Monetary: 500 и 2 000 рублей в месяц. Рекуррент со средним чеком 1 711 при 5,3 платежах дает около 750 рублей в месяц, разовый со своими 1 678 раз в два месяца – около 840. Оба попадают в середину. Чтобы попасть выше 2 000, надо переводить заметно больше среднего, и это уже осмысленный сигнал.
Дальше техническая деталь, из-за которой выражения выглядят немного странно. Окна у нас разной длины: ближнее 2 месяца, среднее 4, дальнее 6. Чтобы сравнивать их с месячными порогами, суммы и количества делятся на 2, 4 и 6 соответственно. Отсюда все эти /2 и /4 в коде.
Сегменты на DMPQL
«Чемпионы» – активные, частые, крупные:
audience from customer_profiles(
attr(50023, -1) not like "None"
and attr(50010, -1) > now - 60 days
and attr(50023, -1) / 2 >= 2
and attr(50033, -1) / 2 > 2000
)
«Риск оттока» – тот самый сегмент, ради которого все затевалось. Средние суммы, последний платеж от 60 до 180 дней назад:
audience from customer_profiles(
attr(50010, -1) <= now - 60 days
and attr(50010, -1) >= now - 180 days
and attr(50032, -1) / 4 >= 500
and attr(50032, -1) / 4 <= 2000
)
«VIP / Меценаты» – единственный сегмент с or: крупные суммы либо при недавней активности с невысокой частотой, либо при давности до 180 дней:
audience from customer_profiles(
(
attr(50023, -1) not like "None"
and attr(50010, -1) > now - 60 days
and attr(50023, -1) / 2 >= 1 and attr(50023, -1) / 2 < 2
and attr(50033, -1) / 2 > 2000
) or (
attr(50010, -1) <= now - 60 days
and attr(50010, -1) >= now - 180 days
and attr(50032, -1) / 4 > 2000
)
)
Всего 27 бинов складываются в 8 сегментов. Проверка корректности элементарная и при этом обязательная: сумма аудиторий всех восьми должна равняться размеру всей донорской базы. Если она не сходится – где-то есть дыра в условиях или, наоборот, перекрытие.
F=3 | F=2 | F=1 | |
|---|---|---|---|
R=3, M=3 | Чемпионы | VIP | Новые |
R=3, M=2 | Лояльные | Лояльные | Новые |
R=3, M=1 | Потенциал | Потенциал | Новые |
R=2, M=3 | VIP | VIP | VIP |
R=2, M=2 | Риск оттока | Риск оттока | Риск оттока |
R=2, M=1 | Потенциал | Потенциал | Потенциал |
R=1, M>=2 | Потерянные | Потерянные | Потерянные |
R=1, M=1 | Холодные | Холодные | Холодные |
Как это выглядит на сегодня, за период с октября 2025 по октябрь 2026: «Потенциал развития» – 59 профилей, «Новые» – 17, «Холодные» – 11, «VIP» – 7, «Чемпионы» – 4, «Лояльные» – 3, «Риск оттока» и «Потерянные» – по 2. Сегменты по два человека – это, конечно, очень мало. Скорее всего, мы склеим восемь сегментов в пять или шесть: «Потерянные» и «Холодные» ведут себя одинаково, «Чемпионам» и «VIP» уходит похожая коммуникация. Но начинать лучше с подробной сетки и укрупнять, чем потом разрезать склеенное.
Цепочки и правила непересечения
На этих сегментах запущены триггерные цепочки. Пример, цепочка «Риск оттока»: вход по попаданию в сегмент, четыре письма за 42 дня (день 0, 14, 28, 42), и перед каждым следующим письмом проверка, не сделал ли человек пожертвование. Сделал – цепочка молча обрывается, потому что просить денег у того, кто только что заплатил, это худшее, что может сделать автоматизация. Отдельно проверяется заполненность email: цепочка стартует не платежом, а попаданием в сегмент, и если адрес брать неоткуда, то на профилях без email сценарий просто не пройдет.
Самое неочевидное оказалось не в цепочках, а между ними. Цепочки друг о друге не знают по умолчанию, может оказаться так, что человек получит письмо из «Риска оттока», а через минуту – из welcome-дополнения. Обе проверяли один и тот же сегмент «получил письмо за 7 дней», который пересчитывается по расписанию три раза в сутки и о свежем письме еще не знали. Лечится это двумя проверками подряд: realtime-сегмент срабатывает мгновенно, но помнит членство только двое суток, а периодический помнит неделю, но отстает на несколько часов. Поодиночке не годится ни один, но вместе они закрывают всю неделю. Поверх этого лежат еще два правила: свежее пожертвование прерывает любую маркетинговую цепочку, а повторный вход в «Welcome» и «Риск оттока» возможен не раньше чем через 90 дней.
Отдельная история – как человек попадает в приветственную цепочку. Вход построен на realtime-сегменте «Успешное НОВОЕ пожертвование», в который человек попадает при любом успешном платеже, разовом или рекуррентном. Разбор, первый он или нет, происходит уже внутри цепочки, фильтром по атрибуту профиля.
Причина в разной природе двух вещей. Платеж – это событие, realtime-сегмент реагирует на него мгновенно. А «первое ли это пожертвование» – вопрос состояния профиля, которое в момент платежа еще не обязано быть пересчитано. Склеите одно с другим в условии входа – цепочка начнет молча пропускать людей на ровном месте. Поэтому событие пускает внутрь всех, а состояние проверяется шагом позже.
Сам факт новизны считает отдельный сегмент по пути клиента: ровно один успешный платеж за последние 30 дней.
audience from customer_journey(
count(CloudPayments[attr(30079) like "Completed"]) = 1
) within 30 days
Что получилось в итоге
Фонд получил автоматические коммуникации там, где раньше были выгрузки и ручной труд. RFM здесь собрался не одной кнопкой, а из штатных инструментов платформы: агрегатные атрибуты плюс аккуратно написанные сегменты. Зато модель получилась своя, под реальные пороги фонда, а не усредненная – и на саму сборку ушло заметно меньше времени, чем на споры о порогах.
Честные ограничения, которые стоит проговорить. Данных у нас был ровно год и 52 донора, поэтому A/B-тесты на такой базе бессмысленны, а пороги придется пересматривать при каждом заметном росте базы или изменении среднего чека. Пороги по M откалиброваны под чек около 1 700 рублей, и если фонд вырастет, они поедут первыми.
Если у вас похожая история – небольшая база, платформа без готового RFM и люди, которые тратят рабочие часы на ручные рассылки, – начинать стоит не с красивой матрицы 5x5, а с вопроса, какие именно письма вы хотите перестать писать руками.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.