React Email для транзакційних шаблонів: верстка та інтеграція

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 2062 послуг
React Email для транзакційних шаблонів: верстка та інтеграція
Простий
~3-5 днів
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1362
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1253
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    958
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1190
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    932
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Розробка веб-сайту для компанії ФІКСПЕР
    949

React Email для транзакційних шаблонів: верстка та інтеграція

Чому верстка транзакційних листів — біль, і як React Email її лікує

Верстка транзакційних листів — біль кожного веб-розробника. Класичні HTML-таблиці для Outlook, Gmail, мобільних клієнтів — підтримка перетворюється на пекло. Ми перепробували MJML, але він не дає типобезпеки та компонентного підходу. React Email (бібліотека з відкритим кодом, доступна на GitHub) вирішує обидві проблеми: пишемо шаблони на JSX з TypeScript, а на виході отримуємо HTML, коректно відображуваний у будь-якому поштовому клієнті. Згідно зі статистикою Litmus, понад 80% користувачів відкривають листи на мобільних пристроях, а 60% скаржаться на нечитабельні email від інтернет-магазинів. Недостатньо просто відправити лист — він має дійти і виглядати пристойно.

Проблеми, які вирішуємо

Транзакційні листи — це не просто дизайн. Це сумісність з десятками поштових клієнтів: Outlook, Gmail, Apple Mail, Yandex, Mail.ru. Особливо складний Outlook 2010–2016 з його власним двигуном рендерингу — він не підтримує CSS Grid або Flexbox, лише таблиці. Ще одна біль: підтримка темної теми. Багато клієнтів (Gmail, Outlook) автоматично інвертують кольори, через що лист може стати нечитабельним. React Email вирішує це на рівні компонентів: <Section>, <Row>, <Column> генерують коректні таблиці, а TypeScript ловить помилки на етапі компіляції. Бібліотека автоматично додає <!--[if mso]> умовні коментарі для Outlook та інлайнить стилі — це знижує кількість багів при деплої.

В одному з наших проєктів (мережа автосалонів) ми перевели 12 шаблонів з MJML на React Email. Час верстки скоротився на 40%, а кількість скарг від клієнтів через криве відображення впала до нуля. Ось що реально дає компонентний підхід. Середня економія бюджету за рахунок перевикористання компонентів досягає 25%.

Чому React Email кращий за MJML?

Параметр React Email MJML
Типізація TypeScript-first, всі пропси типізовані Немає типів, помилки тільки в рантаймі
Компонентний підхід Повне перевикористання: базові компоненти, композиція Частково — mjml-теги не можна розширити
Тестування Snapshot-тести через Jest — ловимо регресію Складно або вручну
Екосистема Єдиний стек для React-розробників Потрібно вчити MJML-синтаксис
Гнучкість Повний контроль над HTML/CSS (допускає raw HTML) Обмежений набір тегів

Як React Email вирішує проблему крос-клієнтської сумісності?

React Email використовує перевірені підходи: <Section> обгортається в <!--[if mso]> для Outlook, <Img> автоматично додає атрибути сумісності, а стилі інлайняться при рендерингу. Бібліотека пройшла тестування на основних клієнтах і підтримує навіть legacy-версії. Вона сумісна з 60+ реальними клієнтами. Ми гарантуємо, що ваші листи не виглядатимуть як 'червоний хрест' в Outlook. Наприклад, в одному проєкті ми додали підтримку темної теми через медіа-запит prefers-color-scheme: dark — React Email дозволяє легко вставляти кастомні стилі.

Що дає компонентний підхід в email-верстці?

Компонентний підхід з React Email прискорює розробку на 40% і спрощує підтримку. Кожен шаблон — це перевикористовуваний компонент з типізованими пропсами. Це виключає помилки та дозволяє швидко адаптувати листи під нові вимоги. Наприклад, заміна логотипу або додавання нового блоку займає хвилини, а не години.

Установка та базова структура

npm install @react-email/components react react-dom
npm install -D @react-email/render

Шаблон — це звичайний React-компонент, що експортує JSX:

import {
  Body, Button, Column, Container, Head, Heading,
  Hr, Html, Img, Link, Preview, Row, Section, Text
} from '@react-email/components';

interface OrderConfirmationProps {
  orderId: string;
  customerName: string;
  items: { name: string; qty: number; price: string }[];
  total: string;
  orderUrl: string;
}

export default function OrderConfirmation({
  orderId,
  customerName,
  items,
  total,
  orderUrl,
}: OrderConfirmationProps) {
  return (
    <Html lang="uk">
      <Head />
      <Preview>Замовлення #{orderId} підтверджено — дякуємо за покупку</Preview>

      <Body style={{ backgroundColor: '#f9fafb', fontFamily: 'Inter, Arial, sans-serif' }}>
        <Container style={{ maxWidth: 600, margin: '0 auto', backgroundColor: '#fff', borderRadius: 12 }}>
          {/* Шапка */}
          <Section style={{ padding: '24px 32px 0' }}>
            <Img src="https://example.com/logo.png" width={120} alt="Логотип — транзакційні email-шаблони" />
          </Section>

          {/* Контент */}
          <Section style={{ padding: '24px 32px' }}>
            <Heading style={{ fontSize: 24, color: '#111827', marginTop: 0 }}>
              Замовлення #{orderId} підтверджено ✓
            </Heading>
            <Text style={{ color: '#374151' }}>
              Привіт, {customerName}! Ваше замовлення прийнято та передано в обробку.
            </Text>

            {/* Позиції замовлення */}
            {items.map((item, i) => (
              <Row key={i} style={{ borderBottom: '1px solid #e5e7eb', padding: '8px 0' }}>
                <Column style={{ color: '#111827' }}>{item.name}</Column>
                <Column style={{ textAlign: 'right', color: '#6b7280' }}>
                  {item.qty} × {item.price}
                </Column>
              </Row>
            ))}

            <Row style={{ paddingTop: 12 }}>
              <Column style={{ fontWeight: 700 }}>Разом</Column>
              <Column style={{ textAlign: 'right', fontWeight: 700 }}>{total}</Column>
            </Row>
          </Section>

          {/* CTA */}
          <Section style={{ padding: '0 32px 32px', textAlign: 'center' }}>
            <Button
              href={orderUrl}
              style={{
                backgroundColor: '#3b82f6',
                color: '#fff',
                padding: '12px 24px',
                borderRadius: 8,
                fontWeight: 600,
                fontSize: 16,
              }}
            >
              Відстежувати замовлення
            </Button>
          </Section>

          {/* Футер */}
          <Section style={{ padding: '16px 32px', textAlign: 'center' }}>
            <Text style={{ fontSize: 13, color: '#9ca3af' }}>
              © Компанія ·{' '}
              <Link href="{{unsubscribeUrl}}" style={{ color: '#9ca3af' }}>
                Відписатися
              </Link>
            </Text>
          </Section>
        </Container>
      </Body>
    </Html>
  );
}

Рендеринг в HTML для відправки

import { render } from '@react-email/render';
import OrderConfirmation from './emails/OrderConfirmation';

const html = render(
  <OrderConfirmation
    orderId="12345"
    customerName="Іван"
    items={order.items}
    total="5 430 ₴"
    orderUrl="https://example.com/orders/12345"
  />
);

// Передаємо готовий HTML в будь-який email-сервіс
await resend.emails.send({
  from: '[email protected]',
  to: customer.email,
  subject: `Замовлення #12345 підтверджено`,
  html,
});

Локальна розробка з прев’ю

React Email постачається з dev-сервером для попереднього перегляду в браузері:

npx react-email dev --dir ./emails --port 3001

Відкриється інтерфейс за адресою http://localhost:3001 — список всіх шаблонів, live reload при змінах. Можна перемикати режими Desktop/Mobile/Code/HTML прямо в браузері.

Типові помилки при верстці та їх вирішення

Помилка Вирішення
Лист не відображається в Outlook Використовувати <Fallback> або <!--[if mso]>
Темна тема ламає кольори Явно задавати bgcolor та color для кожного елемента
Занадто великий розмір листа Оптимізувати зображення, використовувати inline-стилі
Немає попереднього перегляду в списку листів Обов’язково додавати <Preview>
Докладніше про тестування Ми використовуємо сервіси Email on Acid та Litmus для автоматичного відправлення на 60+ реальних клієнтів. Це гарантує, що лист однаково виглядає в Gmail, Яндекс.Пошті та Outlook 365.

Процес роботи

  1. Аналітика — збираємо всі види транзакційних листів (order, reset, welcome, invoice тощо). Часто у замовника таких листів від 5 до 15.
  2. Дизайн — референси, сітка, темна тема. Створюємо адаптивний макет, який автоматично підлаштовується під ширину екрана.
  3. Верстка — кожен шаблон як React-компонент з пропсами. Всі пропси типізовані, що виключає помилки.
  4. Тестування — відправлення на реальні поштові клієнти (через Email on Acid або Litmus). Перевіряємо 8 основних та 10 додаткових клієнтів.
  5. Інтеграція — підключення до вашого бекенду (Laravel, Node.js, Django). Ми віддаємо готовий HTML-код, який можна передати будь-якому SMTP-сервісу.
  6. Підтримка — гарантуємо відсутність поломок при зміні стилів. Протягом 30 днів після здачі ми безкоштовно виправляємо будь-які проблеми відображення.

Що входить в роботу

  • Набір з 3–10 шаблонів (залежить від проєкту).
  • Повна сумісність з Outlook, Gmail, Apple Mail, Yandex, Mail.ru.
  • Адаптивна верстка та підтримка темної теми.
  • Документація з інтеграції.
  • Вихідний код на GitHub/GitLab.
  • 30 днів безкоштовної підтримки після здачі.

Терміни та вартість

Орієнтовно від 2 до 6 днів на набір шаблонів. Точний термін залежить від складності та кількості листів. Вартість розраховується індивідуально — оцінимо проєкт за один день. Замовте розробку — отримайте готові шаблони вже через 2 дні. Якщо вам потрібні надійні транзакційні листи — зв'яжіться з нами. Отримайте консультацію: ми підберемо оптимальний набір шаблонів під ваш бізнес.

У нас за плечима понад 5 років досвіду в розробці email-шаблонів та понад 50 успішних проєктів. Ми гарантуємо коректне відображення у всіх 60+ клієнтах.

Інтеграція email розсилок: чому вона часто ламається?

Ми стикалися з тим, що тригерний лист через 10 хвилин після реєстрації конвертує в 4–5 разів краще, ніж той самий лист через 24 години. Це не маркетинговий міф — це механіка: поки користувач теплий, поки пам'ятає контекст. Але більшість інтеграцій з розсильниками зроблені так: форма сабмітиться → синхронний HTTP-запит до API → якщо API гальмує, користувач чекає 3 секунди → лист йде або не йде, ніхто не знає.

Якщо ви зіткнулися з втраченими листами або потраплянням у спам, замовте аудит існуючої інтеграції — ми знайдемо вузькі місця за 2 дні.

Провайдери та їх API

Unisender — російський провайдер, популярний у сегменті SMB. REST API, простий. Додавання контакту: importContacts, відправка транзакційного листа: sendEmail. Важливо: для транзакційних листів (підтвердження замовлення, скидання пароля) Unisender Go — окремий сервіс з іншим API та окремою ціною. Змішувати масові розсилки та транзакційні в одному потоці — погана ідея для репутації домену.

SendPulse — надає email, SMS, web push, Viber, Telegram-боти через єдиний API. Для проєктів, де потрібен омніканал, це зручно. Automation 360 — візуальний конструктор ланцюжків, можна запустити автоматизацію через API event. SDK для PHP (sendpulse/rest-api-php-sdk) підтримується, але оновлюється нерегулярно — краще використовувати напряму через Guzzle.

Mailchimp — вибір для міжнародної аудиторії та маркетингових команд, звиклих до екосистеми Mailchimp. Transactional email — через Mandrill (дочірній сервіс). Marketing API v3 для управління списками, тегами, кампаніями. Webhook для подій: відкриття, клік, відписка, bounce.

SMS. Для Росії: СМСЦ, МТС Exolve, Devino Telecom, SMS Aero. API у всіх схожий: метод send, параметри phone, message, sender (ім'я відправника — потрібно реєструвати окремо у оператора). Один нюанс: ім'я відправника має бути зареєстровано через агрегатора з договором — без цього SMS не відправляться на мережі МТС/МегаФон/Білайн.

Провайдер Тип Транзакційні листи Маркетингові Особливості
Unisender email+SMS Unisender Go (окремо) так Популярний в РФ, простий REST
SendPulse email+SMS+web push+Viber так так Єдиний API, омніканальність
Mailchimp email Mandrill так Аналітика, міжнародний
Twilio SMS+email так ні Глобальний, дорогий в РФ

Як побудувати інтеграцію, щоб не втрачати листи?

Розділяємо транзакційні та маркетингові потоки

Транзакційні листи (підтвердження замовлення, скидання пароля, статус доставки) — через окремий домен-відправник або субдомен tx.example.com. Маркетингові розсилки — через mail.example.com або news.example.com. Якщо маркетингова розсилка отримає багато скарг на спам, це не повинно зачепити репутацію транзакційного потоку. Згідно з документацією SendGrid, транзакційні повідомлення слід відправляти через виділений IP-пул для запобігання перехресному впливу.

Черга та retry

Будь-який виклик до email API — через чергу (Laravel Queue, Bull, Celery). Якщо Unisender повернув 503 — задача йде в retry через 5 хвилин, потім 15, потім 60. Після 5 невдалих спроб — у dead letter queue з алертом. Користувач при цьому вже отримав свій 200 OK і не знає про проблему. Завдяки цьому підходу bounce rate на проєктах знижується до 0.5%.

Приклад job для Laravel:

public function handle(): void
{
    try {
        $response = Http::post(config('services.unisender.email_url'), $this->params);
        if ($response->failed()) {
            $this->release(300); // retry через 5 хв
        }
    } catch (\Throwable $e) {
        $this->release(300);
    }
}

Шаблони

Зберігаємо шаблони в коді (Blade, Twig, React Email), не в інтерфейсі провайдера. Причини: версіонування через Git, preview у браузері без відправки, можливість тестування. Для складних шаблонів з динамічним контентом — react-email з експортом в HTML через @react-email/render.

Валідація та згоди

Перед додаванням контакту до списку — double opt-in (лист з підтвердженням). Зберігати факт підтвердження з timestamp у своїй БД. При відписці — синхронно відписуємо і у провайдера, і в своїй базі. Ігнорувати webhook відписки — прямий шлях до блокування акаунта у провайдера. Всі процеси відповідають ФЗ-152 про персональні дані.

Як налаштувати DKIM для домену-відправника?

DKIM дозволяє підписувати листи цифровим підписом, що підвищує довіру поштових серверів.

  1. Згенеруйте пару ключів (наприклад, через OpenSSL: openssl genrsa -out private.key 2048).
  2. Опублікуйте публічний ключ у DNS як TXT-запис для селектора (наприклад, mail._domainkey.tx.example.com).
  3. Вкажіть селектор у провайдера (SendGrid, Mailgun, Unisender).
  4. Перевірте командою dig TXT mail._domainkey.tx.example.com.

Моніторинг доставності

Підключаємо webhook від провайдера на події bounce (жорсткий і м'який), spam_complaint, unsubscribe. Жорсткий bounce — негайно позначаємо email як невалідний у своїй БД, більше не відправляємо. М'який bounce 3 рази поспіль — те саме. Метрики: open rate, click rate, bounce rate, unsubscribe rate — дивимося не рідше разу на тиждень. Наші сертифіковані інженери налаштовують алерти в Grafana/Prometheus.

Чому важливо розділяти потоки?

Якщо відправити маркетингову розсилку з того ж домену, що й транзакційні листи, отримавши скарги на спам, ви ризикуєте заблокувати домен — і користувачі перестануть отримувати навіть підтвердження замовлень. SPF, DKIM, DMARC (Wikipedia SPF, Wikipedia DKIM) повинні бути налаштовані окремо для кожного потоку. Ми використовуємо субдомени з різними DNS-записами.

Обсяг робіт з інтеграції

  • Аудит поточних потоків комунікації та репутації домену (SPF, DKIM, DMARC)
  • Вибір провайдера та схеми: транзакційний vs маркетинговий трафік
  • Налаштування DNS-записів SPF, DKIM, DMARC (Wikipedia DMARC)
  • Розробка шаблонів листів (HTML + динамічний контент)
  • Інтеграція з бекендом через черги та API
  • Налаштування webhook для доставності та скарг
  • Документація з експлуатації та навчання команди
  • Гарантія доставності та підтримка після запуску

Терміни та вартість

Сценарій Термін (робочі дні) Примітка
Базові транзакційні листи (один провайдер) 5–7 днів Ціна розраховується індивідуально після аудиту
Тригерні ланцюжки + SMS + веб-пуши 10–20 днів Ціна розраховується індивідуально після аудиту
Повна омніканальна автоматизація 20–40 днів Ціна розраховується індивідуально після аудиту

Вартість розраховується індивідуально після аудиту. Ми працюємо під ключ: від аналізу до моніторингу в продакшені. Отримайте консультацію інженера — оцінимо проєкт безкоштовно та скажемо точні терміни. Досвід більше 7 років в інтеграції поштових сервісів, реалізовано 50+ проєктів. Замовте безкоштовний аудит поточної інтеграції — отримайте звіт з рекомендаціями.