# Newsletter Campaign System - Architecture Plan

## Overview

A comprehensive newsletter system that separates **design templates** from **campaign content**, allowing efficient email broadcasting to subscribers without rebuilding existing infrastructure.

---

## System Architecture

### 1. **Subscriber Management** ✅ (Already Built)
- **Location**: `Marketing > Newsletter > Subscribers List`
- **Features**:
  - Email collection with validation (format + optional external API)
  - Subscriber metadata (email, user_id, status, subscribed_at, ip_address)
  - Search/filter subscribers
  - Export to CSV
  - Delete subscribers
- **Storage**: WordPress options table (`woonoow_newsletter_subscribers`)

### 2. **Email Design Templates** ✅ (Already Built - Reuse Notification System)
- **Location**: Settings > Notifications > Email Builder
- **Purpose**: Create the **visual design/layout** for newsletters
- **Features**:
  - Visual block editor (drag-and-drop cards, buttons, text)
  - Markdown editor (mobile-friendly)
  - Live preview with branding (logo, colors, social links)
  - Shortcode support: `{campaign_title}`, `{campaign_content}`, `{unsubscribe_url}`, `{subscriber_email}`, `{site_name}`, etc.
- **Storage**: Same as notification templates (`wp_options` or custom table)
- **Events to Create**:
  - `newsletter_campaign` (customer, marketing category) - For broadcast emails

**Template Structure Example**:
```markdown
[card:hero]
# {campaign_title}
[/card]

[card]
{campaign_content}
[/card]

[card:basic]
---
You're receiving this because you subscribed to our newsletter.
[Unsubscribe]({unsubscribe_url})
[/card]
```

### 3. **Campaign Management** 🆕 (New Module)
- **Location**: `Marketing > Newsletter > Campaigns` (new tab)
- **Purpose**: Create campaign **content/message** that uses design templates
- **Features**:
  - Campaign list (draft, scheduled, sent, failed)
  - Create/edit campaign
  - Select design template
  - Write campaign content (rich text editor - text only, no design)
  - Preview (merge template + content)
  - Schedule or send immediately
  - Target audience (all subscribers, filtered by date, user_id, etc.)
  - Track status (pending, sending, sent, failed)

---

## Database Schema

### Table: `wp_woonoow_campaigns`

```sql
CREATE TABLE wp_woonoow_campaigns (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  subject VARCHAR(255) NOT NULL,
  content LONGTEXT NOT NULL,
  template_id VARCHAR(100) DEFAULT 'newsletter_campaign',
  status ENUM('draft', 'scheduled', 'sending', 'sent', 'failed') DEFAULT 'draft',
  scheduled_at DATETIME NULL,
  sent_at DATETIME NULL,
  total_recipients INT DEFAULT 0,
  sent_count INT DEFAULT 0,
  failed_count INT DEFAULT 0,
  created_by BIGINT UNSIGNED,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  INDEX idx_status (status),
  INDEX idx_scheduled (scheduled_at),
  INDEX idx_created_by (created_by)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

### Table: `wp_woonoow_campaign_logs`

```sql
CREATE TABLE wp_woonoow_campaign_logs (
  id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  campaign_id BIGINT UNSIGNED NOT NULL,
  subscriber_email VARCHAR(255) NOT NULL,
  status ENUM('pending', 'sent', 'failed') DEFAULT 'pending',
  error_message TEXT NULL,
  sent_at DATETIME NULL,
  INDEX idx_campaign (campaign_id),
  INDEX idx_status (status),
  FOREIGN KEY (campaign_id) REFERENCES wp_woonoow_campaigns(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
```

---

## API Endpoints

### Campaign CRUD

```php
// GET /woonoow/v1/newsletter/campaigns
// List all campaigns with pagination
CampaignsController::list_campaigns()

// GET /woonoow/v1/newsletter/campaigns/{id}
// Get single campaign
CampaignsController::get_campaign($id)

// POST /woonoow/v1/newsletter/campaigns
// Create new campaign
CampaignsController::create_campaign($data)

// PUT /woonoow/v1/newsletter/campaigns/{id}
// Update campaign
CampaignsController::update_campaign($id, $data)

// DELETE /woonoow/v1/newsletter/campaigns/{id}
// Delete campaign
CampaignsController::delete_campaign($id)

// POST /woonoow/v1/newsletter/campaigns/{id}/preview
// Preview campaign (merge template + content)
CampaignsController::preview_campaign($id)

// POST /woonoow/v1/newsletter/campaigns/{id}/send
// Send campaign immediately or schedule
CampaignsController::send_campaign($id, $schedule_time)

// GET /woonoow/v1/newsletter/campaigns/{id}/stats
// Get campaign statistics
CampaignsController::get_campaign_stats($id)

// GET /woonoow/v1/newsletter/templates
// List available design templates
CampaignsController::list_templates()
```

---

## UI Components

### 1. Campaign List Page
**Route**: `/marketing/newsletter?tab=campaigns`

**Features**:
- Table with columns: Title, Subject, Status, Recipients, Sent Date, Actions
- Filter by status (draft, scheduled, sent, failed)
- Search by title/subject
- Actions: Edit, Preview, Duplicate, Delete, Send Now
- "Create Campaign" button

### 2. Campaign Editor
**Route**: `/marketing/newsletter/campaigns/new` or `/marketing/newsletter/campaigns/{id}/edit`

**Form Fields**:
```tsx
- Campaign Title (internal name)
- Email Subject (what subscribers see)
- Design Template (dropdown: select from available templates)
- Campaign Content (rich text editor - TipTap or similar)
  - Bold, italic, links, headings, lists
  - NO design elements (cards, buttons) - those are in template
- Preview Button (opens modal with merged template + content)
- Target Audience (future: filters, for now: all subscribers)
- Schedule Options:
  - Send Now
  - Schedule for Later (date/time picker)
- Save as Draft
```

### 3. Preview Modal
**Component**: `CampaignPreview.tsx`

**Features**:
- Fetch design template
- Replace `{campaign_title}` with campaign title
- Replace `{campaign_content}` with campaign content
- Replace `{unsubscribe_url}` with sample URL
- Show full email preview with branding
- "Send Test Email" button (send to admin email)

### 4. Campaign Stats Page
**Route**: `/marketing/newsletter/campaigns/{id}/stats`

**Metrics**:
- Total recipients
- Sent count
- Failed count
- Sent date/time
- Error log (for failed emails)

---

## Sending System

### WP-Cron Job
```php
// Schedule hourly check for pending campaigns
add_action('woonoow_send_scheduled_campaigns', 'WooNooW\Core\CampaignSender::process_scheduled');

// Register cron schedule
if (!wp_next_scheduled('woonoow_send_scheduled_campaigns')) {
    wp_schedule_event(time(), 'hourly', 'woonoow_send_scheduled_campaigns');
}
```

### Batch Processing
```php
class CampaignSender {
    const BATCH_SIZE = 50; // Send 50 emails per batch
    const BATCH_DELAY = 5; // 5 seconds between batches
    
    public static function process_scheduled() {
        // Find campaigns where status='scheduled' and scheduled_at <= now
        $campaigns = self::get_pending_campaigns();
        
        foreach ($campaigns as $campaign) {
            self::send_campaign($campaign->id);
        }
    }
    
    public static function send_campaign($campaign_id) {
        $campaign = self::get_campaign($campaign_id);
        $subscribers = self::get_subscribers();
        
        // Update status to 'sending'
        self::update_campaign_status($campaign_id, 'sending');
        
        // Get design template
        $template = self::get_template($campaign->template_id);
        
        // Process in batches
        $batches = array_chunk($subscribers, self::BATCH_SIZE);
        
        foreach ($batches as $batch) {
            foreach ($batch as $subscriber) {
                self::send_to_subscriber($campaign, $template, $subscriber);
            }
            
            // Delay between batches to avoid rate limits
            sleep(self::BATCH_DELAY);
        }
        
        // Update status to 'sent'
        self::update_campaign_status($campaign_id, 'sent', [
            'sent_at' => current_time('mysql'),
            'sent_count' => count($subscribers),
        ]);
    }
    
    private static function send_to_subscriber($campaign, $template, $subscriber) {
        // Merge template with campaign content
        $email_body = self::merge_template($template, $campaign, $subscriber);
        
        // Send via notification system
        do_action('woonoow/notification/send', [
            'event' => 'newsletter_campaign',
            'channel' => 'email',
            'recipient' => $subscriber['email'],
            'subject' => $campaign->subject,
            'body' => $email_body,
            'data' => [
                'campaign_id' => $campaign->id,
                'subscriber_email' => $subscriber['email'],
            ],
        ]);
        
        // Log send attempt
        self::log_send($campaign->id, $subscriber['email'], 'sent');
    }
    
    private static function merge_template($template, $campaign, $subscriber) {
        $body = $template->body;
        
        // Replace campaign variables
        $body = str_replace('{campaign_title}', $campaign->title, $body);
        $body = str_replace('{campaign_content}', $campaign->content, $body);
        
        // Replace subscriber variables
        $body = str_replace('{subscriber_email}', $subscriber['email'], $body);
        $unsubscribe_url = add_query_arg([
            'action' => 'woonoow_unsubscribe',
            'email' => base64_encode($subscriber['email']),
            'token' => wp_create_nonce('unsubscribe_' . $subscriber['email']),
        ], home_url());
        $body = str_replace('{unsubscribe_url}', $unsubscribe_url, $body);
        
        // Replace site variables
        $body = str_replace('{site_name}', get_bloginfo('name'), $body);
        
        return $body;
    }
}
```

---

## Workflow

### Creating a Campaign

1. **Admin goes to**: Marketing > Newsletter > Campaigns
2. **Clicks**: "Create Campaign"
3. **Fills form**:
   - Title: "Summer Sale 2025"
   - Subject: "🌞 50% Off Summer Collection!"
   - Template: Select "Newsletter Campaign" (design template)
   - Content: Write message in rich text editor
     ```
     Hi there!
     
     We're excited to announce our biggest summer sale yet!
     
     Get 50% off all summer items this week only.
     
     Shop now and save big!
     ```
4. **Clicks**: "Preview" → See full email with design + content merged
5. **Clicks**: "Send Test Email" → Receive test at admin email
6. **Chooses**: "Schedule for Later" → Select date/time
7. **Clicks**: "Save & Schedule"

### Sending Process

1. **WP-Cron runs** every hour
2. **Finds** campaigns where `status='scheduled'` and `scheduled_at <= now`
3. **Processes** each campaign:
   - Updates status to `sending`
   - Gets all subscribers
   - Sends in batches of 50
   - Logs each send attempt
   - Updates status to `sent` when complete
4. **Admin can view** stats: total sent, failed, errors

---

## Minimal Feature Set (MVP)

### Phase 1: Core Campaign System
- ✅ Database tables (campaigns, campaign_logs)
- ✅ API endpoints (CRUD, preview, send)
- ✅ Campaign list UI
- ✅ Campaign editor UI
- ✅ Preview modal
- ✅ Send immediately functionality
- ✅ Basic stats page

### Phase 2: Scheduling & Automation
- ✅ Schedule for later
- ✅ WP-Cron integration
- ✅ Batch processing
- ✅ Error handling & logging

### Phase 3: Enhancements (Future)
- 📧 Open tracking (pixel)
- 🔗 Click tracking (link wrapping)
- 🎯 Audience segmentation (filter by date, user role, etc.)
- 📊 Analytics dashboard
- 📋 Campaign templates library
- 🔄 A/B testing
- 🤖 Automation workflows

---

## Design Template Variables

Templates can use these variables (replaced during send):

### Campaign Variables
- `{campaign_title}` - Campaign title
- `{campaign_content}` - Campaign content (rich text)

### Subscriber Variables
- `{subscriber_email}` - Subscriber's email
- `{unsubscribe_url}` - Unsubscribe link

### Site Variables
- `{site_name}` - Site name
- `{site_url}` - Site URL
- `{current_year}` - Current year

---

## File Structure

```
includes/
├── Api/
│   ├── NewsletterController.php (existing - subscribers)
│   └── CampaignsController.php (new - campaigns CRUD)
├── Core/
│   ├── Validation.php (existing - email/phone validation)
│   ├── CampaignSender.php (new - sending logic)
│   └── Notifications/
│       └── EventRegistry.php (add newsletter_campaign event)

admin-spa/src/routes/Marketing/
├── Newsletter.tsx (existing - subscribers list)
├── Newsletter/
│   ├── Campaigns.tsx (new - campaign list)
│   ├── CampaignEditor.tsx (new - create/edit)
│   ├── CampaignPreview.tsx (new - preview modal)
│   └── CampaignStats.tsx (new - stats page)
```

---

## Key Principles

1. **Separation of Concerns**:
   - Design templates = Visual layout (cards, buttons, colors)
   - Campaign content = Message text (what to say)

2. **Reuse Existing Infrastructure**:
   - Email builder (notification system)
   - Email sending (notification system)
   - Branding settings (email customization)
   - Subscriber management (already built)

3. **Minimal Duplication**:
   - Don't rebuild email builder
   - Don't rebuild email sending
   - Don't rebuild subscriber management

4. **Efficient Workflow**:
   - Create design template once
   - Reuse for multiple campaigns
   - Only write campaign content each time

5. **Scalability**:
   - Batch processing for large lists
   - Queue system for reliability
   - Error logging for debugging

---

## Success Metrics

- ✅ Admin can create campaign in < 2 minutes
- ✅ Preview shows accurate email with branding
- ✅ Emails sent without rate limit issues
- ✅ Failed sends are logged and visible
- ✅ No duplicate code or functionality
- ✅ System handles 10,000+ subscribers efficiently

---

## Next Steps

1. Create database migration for campaign tables
2. Build `CampaignsController.php` with all API endpoints
3. Create `CampaignSender.php` with batch processing logic
4. Add `newsletter_campaign` event to EventRegistry
5. Build Campaign UI components (list, editor, preview, stats)
6. Test with small subscriber list
7. Optimize batch size and delays
8. Document for users
