Email-маркетинг — мапа стека
Єдина сторінка-контекст для роботи з email-каналом (людям і LLM-сесіям). Стан зафіксовано 2026-07-16, оновлено 2026-07-18 (ланцюжок кошика live, SES-only рішення, каденс 2/12); історія рішень — .context/posthog-email-campaigns/report.md у репо хабу (gitignored, робочі нотатки).
Дві системи відправки — хто за що відповідає
Section titled “Дві системи відправки — хто за що відповідає”| Система | Відповідає за | Статус |
|---|---|---|
| PostHog Workflows (проєкт 221580, eu.posthog.com) | Onboarding-лист новим реєстраціям + майбутні event-тригерні листи з веб-подій | 🟢 LIVE з 16.07.2026 |
| Email service / email-octopus (SES + EmailOctopus) | Покинутий кошик симуляції: 2 листи +2 год / +12 год з персональними resume-лінками, №2 з промокодом; broadcast-движок кампаній, welcome-серія, transactional | 🟢 LIVE — бекенд викликає сервіс у prod (179 CHECKOUT#-станів на 18.07, нагадування шлються); історію ввімкнення див. нижче |
| Marketing blueprint | майбутні AI-персоналізовані кампанії — email відкладено на цикл 2027 (ADR-0004) | 📝 план |
| SMTP з api-v2 | старі транзакційні листи (деталі) | 🟢 prod |
Рішення про розподіл (16.07.2026): кошик веде EO-ланцюжок (персональні лінки оплати, 3 торкання, скасування вебхуком), PostHog веде onboarding. PostHog-workflow кошика abandoned_checkout_simulation архівовано — не вмикати, інакше подвійна відправка.
Оновлення 16–17.07 (рішення Б3, варіант c): SES-only. EmailOctopus виведено з розсилок повністю: welcome-автоматизацію EO зупинено 16.07 (замінена SES-серією самого сервісу), кампанії/suppression/сегментація — у власному движку, міграції лістів в EO не буде. EO лишився тільки як legacy contact-upsert. Деталі й стан фаз → картка сервісу.
flowchart LR
subgraph web[abitly.org · frontend]
idfy["posthog.identify<br/>{aid, email, name}"]
bc["simulation_begin_checkout<br/>{order_id, resume_url}"]
end
subgraph ph[PostHog EU · 221580]
wf["Workflow<br/>onboarding_email_on_signup<br/>🟢 active"]
end
subgraph api[api-v2]
cp[createPayment]
wh[Monobank webhook]
end
subgraph eo[Email service · Lambda]
lc["lifecycle<br/>+2h/+12h"]
end
idfy --> ph
bc --> ph
ph --> wf
wf -- "SES акаунт PostHog<br/>from abitly.team@" --> inbox((Inbox))
cp -- "checkoutStarted (resumeUrl)" --> lc
wh -- checkoutCompleted --> lc
lc -- "SES eu-central-1<br/>from abitly.team@" --> inbox
Sender identity та DNS
Section titled “Sender identity та DNS”Відправник обох систем: «Abitly Team» abitly.team@abitly.org. Скринька на Google Workspace (MX root = smtp.google.com) — відповіді на листи реально читаються.
| Шар | Факт |
|---|---|
| PostHog-канал | integration id 71237, MAIL FROM abitly.team.abitly.org, домен Verified 16.07.2026. Шле з SES-акаунта PostHog; свій SMTP не підтримується; click-tracking через спільний awstrack.me |
| Власний SES | eu-central-1, production access, 50k листів/день; DKIM на abitly.org і news.abitly.org; MAIL FROM mail.abitly.org |
| EmailOctopus | identity верифікований (eo._domainkey, eom., eot. → *.eoidentity.com) |
SPF root abitly.org | v=spf1 include:_spf.google.com include:amazonses.com ~all — ⚠️ другий SPF-запис на root додавати не можна (permerror ламає всю пошту); потрібні include-и вже всередині |
| DMARC | _dmarc.abitly.org = p=none (моніторинг, без enforcement) |
| DNS для PostHog-сендера | 6 записів у Cloudflare (16.07): TXT _amazonses, 3 DKIM CNAME *.dkim.amazonses.com, MX+SPF abitly.team.abitly.org |
DNS керується Cloudflare (zone abitly.org); записи PostHog-каналу видно лише в UI діалогу сендера (API їх не віддає).
Тригери (стан 16.07.2026)
Section titled “Тригери (стан 16.07.2026)”| Тригер | Хто шле | Умови | Таймінг | Лист | Статус |
|---|---|---|---|---|---|
Реєстрація (signup) | PostHog workflow onboarding_email_on_signup | person.email is_set · без тест-акаунтів %@abitly.org% · once per person (masking 3 роки) | +30 хв | «З чого почати на Abitly»: 3 інструменти, CTA → /uk/profile/simulation, блок посібників → links.abitly.org/posibnyky/ (+UTM posthog/email/onboarding) | 🟢 active, e2e-тест пройдено |
Покинутий кошик (checkoutStarted з api-v2) | Email service, кампанія payment-reminder | скасування через checkoutCompleted (Monobank webhook), markPaid-guard, suppression | +2 год / +12 год | №1 нагадування з resume-лінком; №2 з промокодом CW8K5QNM −100 ₴ і чесною ціною (promoForAmount; діє до 13.09) | 🟢 live (179 станів, 18.07) |
| Реєстрація → контакт | Email service syncContact | — | одразу | legacy upsert контакту в EO | 🟢 live |
| Реєстрація → welcome-серія | Email service (SES lifecycle, WelcomeService) | EO-автоматизацію зупинено 16.07 | серія через Scheduler (≥100 активних розкладів) | welcome-2026 | 🟢 live · ⚠️ співіснує з PostHog-onboarding (+30 хв) — новий користувач отримує обидва перші листи; узгодити, хто веде перший дотик — TODO: |
Обсяги для планування (30 днів, PostHog): ~98 signup, ~36 simulation_begin_checkout → 14 simulation_purchase (≈20 покинутих кошиків/міс). Всі самостійні доплати стаються ≤32 хв після старту оплати — тому лист №1 на +1h нікого «не обганяє». Monobank-інвойс живе 1 год (validity: 3600), resume-лінк GET /premium/orders/resume/:token (7 днів) перестворює протухлий інвойс і не потребує логіну.
Identity-план (звідки email у PostHog)
Section titled “Identity-план (звідки email у PostHog)”- fe #556/#557 (prod з 16.07):
setAnalyticsUserшле в PostHog person-профіль{aid, email, name}; GA4 і далі без PII. - Подія
simulation_begin_checkoutперенесена вonSuccesscreate-payment і несеorder_id+resume_url(api #594/#595). - Наявна база до 16.07 email у профілях не має — email підтягується при наступному логіні. Тригер onboarding стосується лише нових реєстрацій.
Промокоди в листах
Section titled “Промокоди в листах”Промо-рейка описана в картці промокодів: коди шеровані, лінк ?ref=<КОД> авто-застосовується (localStorage 30 днів, переживає Google-логін), знижка рахується сервер-сайд. Для email:
- Активний код кошика: CW8K5QNM (−100 ₴, campaign
payment-reminder, діє до 13.09.2026) — у нагадуванні №2 (у конфізі є і крок №3, але prod-каденс — 2 кроки). - Мінт нового коду під кампанію: скіл
promo-mintу цьому репо (.claude/skills/promo-mint/) — один шерований код на кампанію, пре-чек проти дублів, ключ з envABITLY_ADMIN_API_KEYабо SSM. - ⚠️ Resume-лінк промо не застосовує (перегенерує стару суму замовлення) — промо-CTA завжди через
?ref=на пейвол. - Контекст: публічний блог-код дає −200 ₴ — email-знижка −100 ₴ слабша за загальнодоступну.
Гочі (перевірені боляче)
Section titled “Гочі (перевірені боляче)”to.emailу PostHog function_email — тільки Liquid{{ person.properties.email }}. Hog-стиль{person.properties.email}не інтерполюється (крок маєtemplating: liquid) — лист «тихо» скіпається для всіх. Виявлено real-send тестом; цей баг досі сидить в архівному workflow кошика.- Активний PostHog-workflow не редагується через MCP — зміни стають draft, який треба
workflows-publish. Крок листа тримає копію шаблону: після правки шаблону в бібліотеці — перевибрати його в кроці (інакше поїде стара версія). - Тест-відправки — тільки на не-
@abitly.orgадреси: фільтр тест-акаунтів проєкту відсікає домен команди. - Telegram-лінки в листах — з
clicktracking="off"+data-ph-no-track, інакше click-tracking-редирект ламає відкриття апки. - Root SPF не дублювати (див. DNS вище).
- CI обох продуктових репо хронічно червоний (усі чеки падають за ~3 с — інфра); гейт релізу — локальні tsc/build/тести. Реліз у main — cherry-pick dual-PR (dev-гілки на 15-18 комітів попереду main).
- Plain-text
.txt.hbsу email-service рендерився з HTML-escape (ламані лінки) — виправлено в PR#17; при нових кампаніях перевіряти text-версію. simulation_purchaseу PostHog занижений (фіксується лише на success-сторінці) — тому в кошикових листах є grace-рядок «якщо оплата вже пройшла — ігноруй».Email-сервіс шле аналітику в чужий PostHog-проєктрозв’язано 17.07: подіїemail_*йдуть у 221580 — дашборди кампаній і bounce-гардcampaign:sendпрацюють по ньому.- У репо
email-octopusнемає гілкиmain— PR-и і деплой ідуть зdev.
Увімкнення EO-ланцюжка кошика
Section titled “Увімкнення EO-ланцюжка кошика”✅ Виконано 16.07. Історичний чекліст закрито: prod-wiring бекенда зроблено 16.07, PostHog-ключ переведено на 221580 (17.07). Живість звірено 18.07 — 179 CHECKOUT#-станів у DynamoDB, нагадування шлються з каденсом +2 год / +12 год (SSM LIFECYCLE_REMINDER_OFFSETS).
Контроль сьогодні: CHECKOUT# у DynamoDB + Scheduler-група abitly-campaigns; редемпшени промо — GET /admin/promo-codes/report?campaign=payment-reminder.
Моніторинг і аналітика каналу
Section titled “Моніторинг і аналітика каналу”- PostHog:
workflows-stats/ invocations воркфлоу; опційно ввімкнути engagement-події (Settings → Workflows → Engagement events) — opens/clicks стають звичайними подіями. - EO-ланцюжок: CloudWatch Lambda + власний PostHog-клієнт сервісу + EmailOctopus dashboard.
- UTM-конвенція листів:
utm_source=posthog|email · utm_medium=email · utm_campaign=<кампанія>; продажі звіряти зpremium_orders(як у paid-ads). - Вартість PostHog-листів: free tier 10k повідомлень/міс (наші обсяги ≈120/міс → $0).
Обмеження та відкриті питання
Section titled “Обмеження та відкриті питання”- Consent-чекбокса на email-маркетинг при реєстрації немає (відомий gap) — обидві системи ставлять unsubscribe-лінк; масові холодні розсилки по базі 84k без re-permission не робити (blueprint D3).
- PostHog шле через спільний tracking-домен
awstrack.me— ок для тригерних обсягів, не для масових. TODO:серверна подіяsimulation_purchaseз Monobank-вебхука в PostHog (закриє недооблік покупок у воронках і фільтрах).