Перейти до вмісту

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

Відправник обох систем: «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
Власний SESeu-central-1, production access, 50k листів/день; DKIM на abitly.org і news.abitly.org; MAIL FROM mail.abitly.org
EmailOctopusidentity верифікований (eo._domainkey, eom., eot.*.eoidentity.com)
SPF root abitly.orgv=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 їх не віддає).

ТригерХто шлеУмовиТаймінгЛистСтатус
Реєстрація (signup)PostHog workflow onboarding_email_on_signupperson.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 перенесена в onSuccess create-payment і несе order_id + resume_url (api #594/#595).
  • Наявна база до 16.07 email у профілях не має — email підтягується при наступному логіні. Тригер onboarding стосується лише нових реєстрацій.

Промо-рейка описана в картці промокодів: коди шеровані, лінк ?ref=<КОД> авто-застосовується (localStorage 30 днів, переживає Google-логін), знижка рахується сервер-сайд. Для email:

  • Активний код кошика: CW8K5QNM (−100 ₴, campaign payment-reminder, діє до 13.09.2026) — у нагадуванні №2 (у конфізі є і крок №3, але prod-каденс — 2 кроки).
  • Мінт нового коду під кампанію: скіл promo-mint у цьому репо (.claude/skills/promo-mint/) — один шерований код на кампанію, пре-чек проти дублів, ключ з env ABITLY_ADMIN_API_KEY або SSM.
  • ⚠️ Resume-лінк промо не застосовує (перегенерує стару суму замовлення) — промо-CTA завжди через ?ref= на пейвол.
  • Контекст: публічний блог-код дає −200 ₴ — email-знижка −100 ₴ слабша за загальнодоступну.

Гочі (перевірені боляче)

Section titled “Гочі (перевірені боляче)”
  1. to.email у PostHog function_email — тільки Liquid {{ person.properties.email }}. Hog-стиль {person.properties.email} не інтерполюється (крок має templating: liquid) — лист «тихо» скіпається для всіх. Виявлено real-send тестом; цей баг досі сидить в архівному workflow кошика.
  2. Активний PostHog-workflow не редагується через MCP — зміни стають draft, який треба workflows-publish. Крок листа тримає копію шаблону: після правки шаблону в бібліотеці — перевибрати його в кроці (інакше поїде стара версія).
  3. Тест-відправки — тільки на не-@abitly.org адреси: фільтр тест-акаунтів проєкту відсікає домен команди.
  4. Telegram-лінки в листах — з clicktracking="off" + data-ph-no-track, інакше click-tracking-редирект ламає відкриття апки.
  5. Root SPF не дублювати (див. DNS вище).
  6. CI обох продуктових репо хронічно червоний (усі чеки падають за ~3 с — інфра); гейт релізу — локальні tsc/build/тести. Реліз у main — cherry-pick dual-PR (dev-гілки на 15-18 комітів попереду main).
  7. Plain-text .txt.hbs у email-service рендерився з HTML-escape (ламані лінки) — виправлено в PR#17; при нових кампаніях перевіряти text-версію.
  8. simulation_purchase у PostHog занижений (фіксується лише на success-сторінці) — тому в кошикових листах є grace-рядок «якщо оплата вже пройшла — ігноруй».
  9. Email-сервіс шле аналітику в чужий PostHog-проєкт розв’язано 17.07: події email_* йдуть у 221580 — дашборди кампаній і bounce-гард campaign:send працюють по ньому.
  10. У репо 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 (закриє недооблік покупок у воронках і фільтрах).