Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
493 lines
22 KiB
Markdown
493 lines
22 KiB
Markdown
# Marketing Suite — architecture design (Descrybe v2)
|
||
|
||
**Status:** Design only — no implementation in this doc.
|
||
**Date:** 2026-08-04
|
||
**Repos:** `f:/laragon/www/_MY/descrybe-v2`
|
||
**Inputs:** [PRICING-AND-USER-GROWTH.md](../../descrybe/PRICING-AND-USER-GROWTH.md) (sibling), [process-and-sell-summary.md](process-and-sell-summary.md), [features.md](features.md), existing `internal/billing`, `internal/woocommerce`, `internal/processing`, `internal/mail`, Settings + Nav.
|
||
|
||
---
|
||
|
||
## 0. North star
|
||
|
||
Descrybe’s moat remains **feeds → map → process → export/Woo**. Marketing add-ons sit **on top of a live catalog + Woo connection**, not as a second product that competes with “paste ChatGPT into a plugin.”
|
||
|
||
```
|
||
[ Catalog + Brand kit ]
|
||
│
|
||
├── Product AI copy (existing pipeline) ── credits / BYOK
|
||
│
|
||
└── Marketing Suite
|
||
├── Audience (orders + opt-in)
|
||
├── Campaigns (seasonal / category / product)
|
||
├── Reviews (sync + social proof in copy)
|
||
└── SEO recommendations (catalog-derived)
|
||
```
|
||
|
||
**Principle:** Defaults get a merchant from “Black Friday email for buyers of Category X” in minutes. Advanced (custom prompts, BYOK, segment builders) stays behind optional panels.
|
||
|
||
---
|
||
|
||
## 1. Context from today’s codebase
|
||
|
||
| Area | Today (v2) | Implication for Marketing |
|
||
|------|------------|---------------------------|
|
||
| **Woo** | Company-level `woocommerce_configs`; **outbound product push** only (`internal/woocommerce`); worker claims sync jobs | Must **add inbound** order (+ later review) sync; keep credentials encrypted; reuse same store config |
|
||
| **Credits** | `credit_balances` + `AssertCanStartProcessing` / `ConsumeCredits(..., featureName)` | Extend with feature names: `campaign_copy`, `seo_recommend`, `brand_kit_ai`; same wallet |
|
||
| **Plans** | `plans` / `company_plans` + SKU caps; public Free/Starter/Growth/Business/Enterprise in `pricing-data.ts` | Need **feature flags per plan** (not only meters) for Marketing |
|
||
| **AI** | Worker `Completer` (OpenAI or heuristic); no tenant BYOK yet | Campaign/SEO/Brand AI share Completer + future BYOK seam |
|
||
| **Mail** | Platform SMTP for invites (`internal/mail`); noop if disabled | **Campaign send ≠ platform invite SMTP** — tenant-verified provider required |
|
||
| **Nav / Settings** | Nav: PIM core + WooCommerce extra; Settings tabs: profile / company / api-keys / team | Add **Marketing** nav group; Settings → **Integrations** tab (Woo, Email, Reviews, AI keys) |
|
||
| **Jobs** | DB claim + `NOTIFY` for processing + Woo | Same pattern for `order_sync`, `review_sync`, `campaign_send`, `campaign_generate` |
|
||
|
||
### Pricing doc conflict (resolve explicitly)
|
||
|
||
[PRICING-AND-USER-GROWTH.md](../../descrybe/PRICING-AND-USER-GROWTH.md) currently proposes **Free = 50 AI credits / mo**.
|
||
**This suite design requires Free = ZERO AI credits** and gates campaigns / SEO AI / brand AI.
|
||
|
||
**ASSUMPTION (recommended):** Align product policy as:
|
||
|
||
| Plan | Core product AI | Marketing AI (campaigns / SEO / brand kit AI) |
|
||
|------|-----------------|-----------------------------------------------|
|
||
| **Free** | **0 credits** (map/export/Woo test only; reverse-trial exception below) | **Blocked** |
|
||
| **Starter+** | Included pack per plan | Included; burns same credit wallet (or BYOK) |
|
||
| **Reverse trial (14d Growth)** | Full Growth credits | Full Marketing allowed |
|
||
|
||
Update `pricing-data.ts` + plan seeds when implementing — Free must not advertise “50 AI credits” if policy is zero.
|
||
|
||
---
|
||
|
||
## 2. Product modules
|
||
|
||
### 2.1 Email campaigns
|
||
|
||
**Jobs:** Draft → preview → schedule/send seasonal or catalog-driven emails using Descrybe catalog + Woo audiences.
|
||
|
||
#### Campaign types (MVP → later)
|
||
|
||
| Type | Trigger / audience seed | Copy source |
|
||
|------|-------------------------|-------------|
|
||
| **Seasonal template** | Christmas, Black Friday, New Year, Summer (system templates) | Default prompts + brand kit |
|
||
| **By category** | Products in selected category tree node(s) | Catalog titles/images + formula fields |
|
||
| **By product set** | Explicit SKUs / product IDs / collection | Same |
|
||
| **Purchase-based** | Bought X / not bought Y (needs order sync) | Same + segment filters |
|
||
|
||
#### Prompt model (mirror product formulas)
|
||
|
||
```
|
||
campaign.prompt_mode = "default" | "custom"
|
||
campaign.system_prompt_override? // only if custom + plan allows
|
||
campaign.user_prompt_vars = { season, category_names, product_snippets, brand_voice, cta_url }
|
||
```
|
||
|
||
- **Default:** curated seasonal/category prompts + Brand kit (voice, tone, banned words).
|
||
- **Custom:** editable system/user prompt (Growth+); stored per campaign, versioned.
|
||
- **Preview:** generate N sample emails (1–3) before send; each preview burns credits (or BYOK).
|
||
|
||
#### AI path
|
||
|
||
| Path | When | Billing |
|
||
|------|------|---------|
|
||
| **Managed** | Default | Debit `campaign_copy` (+ token packs via existing `openai_token_k`) |
|
||
| **BYOK** | Growth add-on / Business+ | Completer uses tenant key; **no credit burn for inference**; still need paid plan feature flag |
|
||
|
||
**Never send AI-generated body without human confirm** on first send of a campaign (checkbox “I reviewed the preview”). Resends of an approved version can skip.
|
||
|
||
#### Data model (sketch)
|
||
|
||
```
|
||
marketing_campaigns
|
||
id, company_id, name, type, status (draft|scheduled|sending|sent|cancelled)
|
||
season_key?, category_ids[], product_ids[]
|
||
audience_query jsonb -- segment DSL (see §3)
|
||
prompt_mode, prompts jsonb
|
||
subject, preview_text, body_html, body_text
|
||
schedule_at?, sent_at?
|
||
ai_provider (managed|byok), credit_cost_est
|
||
created_by, created_at, updated_at
|
||
|
||
marketing_campaign_sends
|
||
id, campaign_id, recipient_hash, email_encrypted_or_token
|
||
status (queued|sent|bounced|unsubscribed|failed)
|
||
provider_message_id?, error?, sent_at?
|
||
|
||
marketing_campaign_events -- opens/clicks later (P2)
|
||
```
|
||
|
||
Worker jobs: `campaign_generate`, `campaign_send_batch` (chunked, rate-limited).
|
||
|
||
---
|
||
|
||
### 2.2 Order sync (Woo → audience)
|
||
|
||
**Goal:** Build segments like “purchased product/category X in last 90d AND never purchased Y.”
|
||
|
||
#### Sync design
|
||
|
||
- Extend Woo **Integrations** config (same `woocommerce_configs` row or sibling `integration_woocommerce_orders`):
|
||
- `orders_enabled`, `orders_last_synced_at`, `orders_cursor` (modified_after / page)
|
||
- Worker job `woo_order_sync` (incremental, bounded pages per tick)
|
||
- REST: `GET /wp-json/wc/v3/orders` (+ line items); map to local tables
|
||
|
||
```
|
||
woo_customers
|
||
company_id, woo_customer_id, email_hash, email_enc, name, marketing_opt_in, unsubscribed_at, ...
|
||
|
||
woo_orders
|
||
company_id, woo_order_id, customer_id, status, ordered_at, currency, total, raw_meta jsonb
|
||
|
||
woo_order_items
|
||
company_id, order_id, sku, product_id_local?, woo_product_id, quantity, category_ids_snapshot[]
|
||
```
|
||
|
||
**Privacy:** store emails encrypted at rest; display masked; use `email_hash` for uniqueness. Prefer Woo `marketing_opt_in` / billing consent fields when present.
|
||
|
||
#### Audience DSL (JSON, server-validated)
|
||
|
||
```json
|
||
{
|
||
"op": "and",
|
||
"rules": [
|
||
{ "type": "purchased_sku", "skus": ["ABC-1"], "since_days": 365 },
|
||
{ "type": "not_purchased_sku", "skus": ["ABC-2"], "since_days": 365 },
|
||
{ "type": "purchased_category", "category_ids": ["uuid…"], "since_days": 90 },
|
||
{ "type": "marketing_opt_in", "equals": true }
|
||
]
|
||
}
|
||
```
|
||
|
||
Resolver compiles to SQL with **hard filters**: `unsubscribed_at IS NULL`, `marketing_opt_in = true`, bounce suppression list. Always AND these safety filters server-side (client cannot disable).
|
||
|
||
**ASSUMPTION:** Guests without account email are skipped unless order billing email present and opted-in.
|
||
|
||
---
|
||
|
||
### 2.3 Reviews sync
|
||
|
||
| Provider | Phase | Notes |
|
||
|----------|-------|-------|
|
||
| **WooCommerce product reviews** (`/wp-json/wc/v3/products/reviews`) | **P1** | Same store credentials; incremental sync |
|
||
| **Placeholder providers** (Judge.me, Yotpo, Trustpilot) | **P2** | Interface only: `ReviewProvider` with `ListSince(cursor)`; UI “Coming soon” + webhook stub |
|
||
|
||
```
|
||
product_reviews
|
||
company_id, provider, external_id, product_sku, rating, title, body, author_hash
|
||
reviewed_at, synced_at, usable_in_marketing bool
|
||
```
|
||
|
||
Uses: social proof blocks in campaign templates; optional “mention top reviews” in default prompts; SEO module “products with < N reviews.”
|
||
|
||
---
|
||
|
||
### 2.4 SEO recommendations (from catalog)
|
||
|
||
**Not** a full site crawler in P0. Catalog-first checks that reuse processed products + categories + standard fields:
|
||
|
||
| Check | Signal | Output |
|
||
|-------|--------|--------|
|
||
| Thin title / description | Length, uniqueness | Rewrite suggestion (AI = paid) |
|
||
| Missing attributes | Required attrs empty | Fill via process job CTA |
|
||
| Duplicate titles | Collision count | Merge / differentiate |
|
||
| Weak category paths | Depth / orphan | Taxonomy tip |
|
||
| Image gaps | No primary image | Upload / feed map tip |
|
||
| Keyword coverage | Brand kit primary keywords vs title | Nudge |
|
||
|
||
```
|
||
seo_recommendation_runs
|
||
id, company_id, status, created_at, summary jsonb
|
||
|
||
seo_recommendations
|
||
id, run_id, product_id?, severity, code, message, suggested_action
|
||
ai_draft?, applied_at?
|
||
```
|
||
|
||
- **Free:** show **rule-based** list only (no AI drafts).
|
||
- **Paid:** “Generate rewrite” → `seo_recommend` credits / BYOK → optional apply to product fields via existing product PATCH.
|
||
|
||
---
|
||
|
||
### 2.5 Brand kit
|
||
|
||
Company-scoped creative constraints for **product copy + campaigns**.
|
||
|
||
```
|
||
brand_kits
|
||
company_id PK
|
||
voice_summary text -- short “we sound like…”
|
||
tone_tags text[] -- e.g. friendly, expert, playful
|
||
banned_phrases text[]
|
||
preferred_phrases text[]
|
||
primary_color, secondary_color
|
||
logo_url / logo_file_id
|
||
fonts jsonb? -- optional
|
||
locale_default
|
||
updated_at
|
||
```
|
||
|
||
- **Manual edit:** available Starter+ (or Free read-only empty kit?). **ASSUMPTION:** Free can **view** empty kit + upgrade CTA; edit + AI-assist = paid.
|
||
- **AI assist (“Infer brand from catalog”):** paid; feature `brand_kit_ai`.
|
||
- Injected into processing enhance prompts **and** campaign defaults (single source of truth).
|
||
|
||
UI: Settings → Company **or** Marketing → Brand kit (prefer **Marketing → Brand kit** with deep-link from Integrations).
|
||
|
||
---
|
||
|
||
## 3. Plan gating & Free tier
|
||
|
||
### 3.1 Feature matrix
|
||
|
||
| Capability | Free | Starter | Growth | Business+ |
|
||
|------------|------|---------|--------|-----------|
|
||
| SKU / feed / storage meters | Per pricing ladder | ✓ | ✓ | ✓ |
|
||
| **AI credits** | **0** | Pack | Pack | Pack / BYOK |
|
||
| Product processing AI | ✗ (unless reverse trial) | ✓ | ✓ | ✓ |
|
||
| Marketing nav (read-only teasers) | Teaser + upgrade | ✓ | ✓ | ✓ |
|
||
| Campaigns create/send | ✗ | ✓ (caps) | ✓ | ✓ |
|
||
| Campaign AI generate | ✗ | Credits | Credits/BYOK | ✓ |
|
||
| Order sync | ✗ (or read-only test 1 page?) | ✓ | ✓ | ✓ |
|
||
| Audience “bought X not Y” | ✗ | ✓ | ✓ | ✓ |
|
||
| Reviews sync (Woo) | ✗ | ✓ | ✓ | ✓ |
|
||
| SEO rule-based | ✓ (limited rows) | ✓ | ✓ | ✓ |
|
||
| SEO AI rewrite | ✗ | ✓ | ✓ | ✓ |
|
||
| Brand kit edit | ✗ | ✓ | ✓ | ✓ |
|
||
| Brand kit AI | ✗ | ✓ | ✓ | ✓ |
|
||
| BYOK | ✗ | ✗ | Add-on | Included |
|
||
|
||
**ASSUMPTION:** Starter is the smallest plan that unlocks Marketing Suite send + order sync. Free stays acquisition for **feed aha**, not email ESP.
|
||
|
||
### 3.2 Enforcement seams (reuse billing)
|
||
|
||
Extend `internal/billing`:
|
||
|
||
```go
|
||
// Pseudocode — design only
|
||
AssertFeature(ctx, companyID, "marketing.campaigns")
|
||
AssertFeature(ctx, companyID, "marketing.order_sync")
|
||
AssertCanSpendCredits(ctx, companyID, feature, est)
|
||
```
|
||
|
||
- Plan row gains `features jsonb` (or `plan_entitlements` table).
|
||
- API returns `403` + machine code `feature_gated` / `insufficient_credits` for UI `UpgradeBanner`.
|
||
- Reverse trial: temporary Growth entitlements; day 15 → Free (0 credits, Marketing hard-off). Persist draft campaigns read-only.
|
||
|
||
### 3.3 Caps (Starter starter-limits)
|
||
|
||
| Meter | Starter (example) | Growth |
|
||
|-------|-------------------|--------|
|
||
| Campaigns / mo | 5 | 50 |
|
||
| Recipients / send | 2_000 | 25_000 |
|
||
| Order sync lookback | 180d | 730d |
|
||
| SEO AI rewrites / mo | 50 | 1_000 |
|
||
|
||
Exact numbers tunable; enforce server-side.
|
||
|
||
---
|
||
|
||
## 4. Integration style (UX IA)
|
||
|
||
### 4.1 Settings → Integrations
|
||
|
||
Replace scattered `/woocommerce` as the *only* integration home. Keep `/woocommerce` as redirect → Settings Integrations for one release if needed.
|
||
|
||
**Settings tabs:** `profile` | `company` | `team` | `api-keys` | **`integrations`**
|
||
|
||
Integrations cards:
|
||
|
||
1. **WooCommerce** — store URL, keys, test connection, product sync toggle, **order sync** toggle, **reviews sync** toggle
|
||
2. **Email sending** — provider (Resend / SES / SMTP / Postmark), from-domain, **verification status**, rate limits
|
||
3. **AI keys (BYOK)** — Growth+; encrypted; never logged
|
||
4. **Reviews providers** — Woo (active) + placeholders
|
||
|
||
### 4.2 Marketing nav
|
||
|
||
New top-level group (after Export Feeds / before Billing):
|
||
|
||
```
|
||
Marketing
|
||
├─ Campaigns
|
||
├─ Audiences
|
||
├─ Reviews
|
||
├─ SEO
|
||
└─ Brand kit
|
||
```
|
||
|
||
Free users see routes with locked empty-states + upgrade CTAs (not 404).
|
||
|
||
---
|
||
|
||
## 5. Safety (non-negotiable)
|
||
|
||
| Rule | Implementation |
|
||
|------|----------------|
|
||
| **No send without verified provider** | `email_provider.status == verified` AND DNS/domain checks passed; else Send button disabled + API `412 email_not_verified` |
|
||
| **Opt-out / unsubscribe** | Every email: `List-Unsubscribe` + one-click POST; landing page; set `unsubscribed_at`; suppress forever until re-opt-in via Woo/consent |
|
||
| **Opt-in required** | Audience resolver always requires marketing consent |
|
||
| **Rate limits** | Per-company send RPM/RPH; provider caps; exponential backoff; circuit breaker on bounce rate > threshold |
|
||
| **PII** | No emails in logs; hash + encrypt; admin support tools mask by default |
|
||
| **Double opt-in for imported lists** | If CSV import ever added (P2): require confirmation — Woo-sourced opted-in only in P0/P1 |
|
||
| **Abuse** | Cap Free teasers; paid caps; platform admin kill-switch per company |
|
||
| **Legal copy** | Footer template mandatory (company address, unsubscribe) before schedule |
|
||
|
||
Platform invite SMTP (`internal/mail`) **must not** be used for marketing blasts.
|
||
|
||
---
|
||
|
||
## 6. UX principles
|
||
|
||
1. **Happy path wizard:** Pick template (BF/Christmas) → pick category/products → auto audience suggestion → generate 1 preview → connect email if missing → schedule.
|
||
2. **Advanced accordion:** custom prompts, raw audience DSL, UTM params, send-time optimization (P2).
|
||
3. **Reuse catalog chrome:** product pickers, category tree, UpgradeBanner, processing job progress patterns.
|
||
4. **Empty states teach the core path:** “Connect Woo + sync orders to target buyers of X.”
|
||
5. **Credit honesty:** show estimated credit cost before Generate; BYOK badge when active.
|
||
|
||
---
|
||
|
||
## 7. Interactive tutorial (activation)
|
||
|
||
Extend the pricing doc’s ≤15 min aha into a **guided checklist** (dashboard + optional spotlight tour):
|
||
|
||
| Step | Route / action | Done when |
|
||
|------|----------------|-----------|
|
||
| 1. Add feed | `/feeds` | Feed created with URL/file |
|
||
| 2. Map fields | `/feeds/{id}/mapping` | Required fields mapped (auto-map OK) |
|
||
| 3. Process sample | `/processing` | ≥10 products `completed` (credits: trial/paid) |
|
||
| 4. Export or Woo push | `/export-feeds` or Integrations | Export generated **or** Woo test sync OK |
|
||
| 5. Brand kit (paid) | `/marketing/brand-kit` | Voice saved **or** skipped with “later” |
|
||
| 6. Campaigns (paid) | `/marketing/campaigns` | Draft campaign created (send optional) |
|
||
|
||
- Persist `onboarding_progress` on `company_settings`.
|
||
- Free users complete 1–4; 5–6 show locked steps with value props.
|
||
- Tutorial deep-links must survive refresh; dismissible; “Replay tour” in help.
|
||
|
||
Aligns with [process-and-sell-summary.md](process-and-sell-summary.md) happy path + Marketing as step after export.
|
||
|
||
---
|
||
|
||
## 8. Technical architecture (v2 packages)
|
||
|
||
```
|
||
apps/api/internal/
|
||
marketing/ # campaigns, audiences, brand kit, seo services
|
||
integrations/
|
||
email/ # provider interface: Send, VerifyDomain, Webhooks
|
||
reviews/ # ReviewProvider
|
||
billing/ # + AssertFeature, feature costs
|
||
woocommerce/ # + OrdersClient, ReviewsClient, sync workers
|
||
apps/api/sql/schema/
|
||
01x_marketing.sql # tables above
|
||
01y_integrations_email.sql
|
||
apps/web/src/routes/
|
||
marketing/campaigns/
|
||
marketing/audiences/
|
||
marketing/reviews/
|
||
marketing/seo/
|
||
marketing/brand-kit/
|
||
settings/ # + integrations tab
|
||
unsubscribe/[token]/ # public
|
||
```
|
||
|
||
**Completer sharing:** marketing generation calls the same `processing.Completer` interface; inject company BYOK client when entitlement + key present.
|
||
|
||
**Idempotency:** send batches keyed by `(campaign_id, recipient_hash)`; sync cursors monotonic.
|
||
|
||
---
|
||
|
||
## 9. API sketch (dashboard + future public)
|
||
|
||
| Method | Path | Notes |
|
||
|--------|------|-------|
|
||
| GET/PATCH | `/api/integrations/woocommerce` | Existing + order/review flags |
|
||
| POST | `/api/integrations/woocommerce/sync-orders` | Enqueue |
|
||
| GET/PATCH | `/api/integrations/email` | Provider config |
|
||
| POST | `/api/integrations/email/verify` | Start verification |
|
||
| GET/PATCH | `/api/marketing/brand-kit` | |
|
||
| GET/POST | `/api/marketing/campaigns` | |
|
||
| POST | `/api/marketing/campaigns/{id}/generate` | Credits gate |
|
||
| POST | `/api/marketing/campaigns/{id}/schedule` | Requires verified email |
|
||
| POST | `/api/marketing/audiences/preview` | Count + sample (masked) |
|
||
| POST | `/api/marketing/seo/runs` | |
|
||
| POST | `/api/public/unsubscribe` | Token auth |
|
||
|
||
Public API v1 exposure of Marketing = **Business+ / later**; dashboard session auth first.
|
||
|
||
---
|
||
|
||
## 10. Risks & open decisions
|
||
|
||
| Topic | Risk | Recommendation |
|
||
|-------|------|----------------|
|
||
| Free AI credits vs pricing doc | Conflicting promises | **Ship Free = 0 AI**; update pricing doc + `pricing-data.ts` |
|
||
| Becoming an ESP | Deliverability / spam liability | Verified domain only; start with low caps; consider “export to Klaviyo” P2 |
|
||
| Order PII | GDPR | Encrypt, retention policy, delete-with-company, DPA |
|
||
| Woo permission scopes | Keys may lack orders/reviews | TestConnection checks endpoints; clear UI errors |
|
||
| Custom prompts abuse | Prompt injection / brand damage | Length limits; strip tools; require preview ack |
|
||
|
||
**Open questions (non-blocking for P0 scaffolding):**
|
||
1. First ESP: Resend vs SES vs tenant SMTP only?
|
||
2. Starter recipient cap exact number?
|
||
3. Free SEO rule-based: show all issues or cap at 20?
|
||
|
||
---
|
||
|
||
## 11. Sibling-agent checklist
|
||
|
||
### P0 — foundation (do first; unblocks everything)
|
||
|
||
- [ ] **P0.1** Align Free plan: **0 AI credits**; Marketing feature flags on `plans`; update `pricing-data.ts` + seeds; reverse-trial keeps Growth marketing.
|
||
- [ ] **P0.2** `billing.AssertFeature` + credit feature names (`campaign_copy`, `seo_recommend`, `brand_kit_ai`); wire `UpgradeBanner` codes.
|
||
- [ ] **P0.3** Settings → **Integrations** tab; move Woo config UX there (redirect old `/woocommerce`).
|
||
- [ ] **P0.4** Marketing nav shell + locked empty states for Free.
|
||
- [ ] **P0.5** Brand kit schema + CRUD (manual fields only).
|
||
- [ ] **P0.6** Email provider integration model + **verified-only send gate** (even if provider is stubbed behind interface).
|
||
- [ ] **P0.7** Campaign draft CRUD + default seasonal templates + generate-preview job (no mass send yet).
|
||
- [ ] **P0.8** Unsubscribe token endpoint + suppression list.
|
||
- [ ] **P0.9** Woo **order sync** (incremental) + `woo_orders` / items / customers tables.
|
||
- [ ] **P0.10** Audience preview: purchased X / not purchased Y + opt-in hard filters.
|
||
- [ ] **P0.11** Onboarding tutorial steps 1–4 wired to real completion signals; 5–6 gated.
|
||
- [ ] **P0.12** Safety tests: cannot send if unverified; cannot include unsubscribed; Free cannot generate campaign AI.
|
||
|
||
### P1 — sellable Marketing MVP
|
||
|
||
- [ ] **P1.1** Campaign schedule/send batches via verified provider + rate limits + bounce basic handling.
|
||
- [ ] **P1.2** Custom vs default prompts UI; credit estimate + BYOK seam (if BYOK platform work ready).
|
||
- [ ] **P1.3** Woo product **reviews** sync + Reviews Marketing page.
|
||
- [ ] **P1.4** SEO recommendation runs (rule-based + paid AI rewrite).
|
||
- [ ] **P1.5** Brand kit injection into product enhance + campaign defaults.
|
||
- [ ] **P1.6** Cap enforcement (campaigns/mo, recipients/send).
|
||
- [ ] **P1.7** Tutorial steps 5–6 + “first Black Friday campaign” recipe.
|
||
- [ ] **P1.8** Ops: kill-switch, send metrics on billing overview.
|
||
|
||
### P2 — expand
|
||
|
||
- [ ] **P2.1** Placeholder review providers (Judge.me / Yotpo) + webhooks.
|
||
- [ ] **P2.2** Open/click tracking; A/B subjects.
|
||
- [ ] **P2.3** Export audience / campaign to Klaviyo/Mailchimp.
|
||
- [ ] **P2.4** Site crawl SEO (beyond catalog).
|
||
- [ ] **P2.5** Public API for campaigns.
|
||
- [ ] **P2.6** Multi-language campaign variants from catalog locales.
|
||
- [ ] **P2.7** AI “infer brand kit from best products.”
|
||
|
||
---
|
||
|
||
## 12. Verification expectations (when built)
|
||
|
||
- Unit: audience SQL compiler, feature gate matrix, unsubscribe token.
|
||
- Integration: Woo orders pagination mocked; send blocked without verify.
|
||
- UI: Free user sees locks; Starter can preview generate with credits.
|
||
- No claim-done without `AssertFeature` coverage on every mutating Marketing route.
|
||
|
||
---
|
||
|
||
## 13. Rollback
|
||
|
||
- Feature flags `MARKETING_ENABLED` (platform) + per-plan entitlements.
|
||
- Schema additive only; drop via goose Down if needed.
|
||
- Disabling flag hides nav and 404s APIs without deleting drafts.
|
||
|
||
---
|
||
|
||
## Related docs
|
||
|
||
- Sibling pricing: `f:/laragon/www/_MY/descrybe/PRICING-AND-USER-GROWTH.md`
|
||
- [process-and-sell-summary.md](process-and-sell-summary.md)
|
||
- [features.md](features.md) · [status-and-gaps.md](status-and-gaps.md) · [security-notes.md](security-notes.md)
|