360 lines
7.9 KiB
Markdown

# Newsletter Integration (Listmonk)
The Newsletter Integration provides automated synchronization between Changemaker Lite and Listmonk newsletter platform. Campaign participants, volunteers, and locations can be automatically synced to Listmonk lists for targeted email campaigns.
## Overview
The Listmonk integration provides:
- **Opt-in Sync** - Controlled by `LISTMONK_SYNC_ENABLED` flag
- **Automatic Subscriber Creation** - Campaign participants → subscribers
- **List Management** - Campaigns → lists, Locations → lists
- **User Role Sync** - User roles → list assignment
- **Bi-directional Updates** - Keep data synchronized
- **Admin Interface** - Manual sync controls and monitoring
## Features
### Subscriber Sync
Automatically sync users to Listmonk:
- **Campaign Participants** - Email senders become subscribers
- **Shift Signups** - Volunteers added to lists
- **Response Submitters** - Response wall participants
- **Manual Users** - User role-based list assignment
### List Management
Auto-create and manage lists:
- **Campaign Lists** - One list per campaign
- **Location Lists** - One list per geographic area
- **Role Lists** - Lists for each user role
- **Custom Lists** - Admin-defined lists
### Sync Triggers
Automatic sync on:
- Campaign email sent
- Shift signup
- Response submission
- User registration
- Manual admin trigger
### Admin Controls
- View sync status
- Manual sync buttons
- Test connection
- List statistics
- Reinitialize lists
## Architecture
### Backend Components
**Listmonk Client:**
- `api/src/services/listmonk.client.ts` - Typed HTTP client (native fetch)
- Basic auth integration
- Full REST API coverage
**Listmonk Sync Service:**
- `api/src/services/listmonk-sync.service.ts` - Sync orchestration
- Participant → subscriber mapping
- List creation and management
- Error handling and logging
**Admin Module:**
- `api/src/modules/listmonk/listmonk.routes.ts` - Admin endpoints
- Status, stats, sync controls
**Database:**
- No new tables (uses existing User, Campaign, Location)
- Listmonk IDs stored in Prisma models (future)
### Frontend Components
**Admin Page:**
- `admin/src/pages/ListmonkPage.tsx` - Newsletter management
- Connection status display
- Sync controls
- List statistics table
## Configuration
### Environment Variables
```bash
# Enable Listmonk sync (opt-in)
LISTMONK_SYNC_ENABLED=true
# Listmonk connection
LISTMONK_API_URL=http://listmonk:9000
LISTMONK_API_USER=api_user
LISTMONK_API_TOKEN=your_api_token
# Web admin credentials (for setup)
LISTMONK_WEB_ADMIN_USER=admin
LISTMONK_WEB_ADMIN_PASSWORD=password
```
### Docker Setup
Listmonk runs as a service in `docker-compose.yml`:
```yaml
listmonk:
image: listmonk/listmonk:latest
ports:
- "9001:9000"
depends_on:
- listmonk-db
environment:
LISTMONK_app__admin_username: ${LISTMONK_WEB_ADMIN_USER}
LISTMONK_app__admin_password: ${LISTMONK_WEB_ADMIN_PASSWORD}
```
### Initialization
Auto-create API user via `listmonk-init` container:
```sql
INSERT INTO users (email, name, password, type, status, created_at, updated_at)
VALUES (
'${LISTMONK_API_USER}',
'API User',
'${LISTMONK_API_TOKEN}', -- Plaintext (Listmonk API tokens)
'api',
'enabled',
NOW(),
NOW()
);
```
## Sync Process
### Campaign Participant Sync
1. **Email Sent** - Campaign email sent via API
2. **Create Subscriber** - POST `/api/subscribers`
- Email, name from user
- Status: `enabled`
3. **Get/Create List** - GET/POST `/api/lists`
- List name: Campaign name
- Type: `public` or `private`
4. **Subscribe to List** - PUT `/api/subscribers/:id/lists`
- Add subscriber to campaign list
### Location Sync
1. **Location Created** - New location added
2. **Get/Create List** - List name: Location name/city
3. **Sync Users** - All users in location → list
### User Role Sync
1. **User Registration** - New user account
2. **Get Role List** - `SUPER_ADMIN`, `INFLUENCE_ADMIN`, etc.
3. **Subscribe User** - Add to role-based list
## API Integration
### Listmonk Client Usage
```typescript
import { listmonkClient } from '../services/listmonk.client';
// Create subscriber
const subscriber = await listmonkClient.createSubscriber({
email: 'user@example.com',
name: 'User Name',
status: 'enabled',
lists: [listId],
});
// Get/Create list
let list = await listmonkClient.getListByName('Campaign Name');
if (!list) {
list = await listmonkClient.createList({
name: 'Campaign Name',
type: 'public',
optin: 'double',
});
}
// Subscribe to list
await listmonkClient.subscribeToList(subscriberId, [listId]);
```
### Sync Service Usage
```typescript
import { listmonkSyncService } from '../services/listmonk-sync.service';
// Sync campaign participant
await listmonkSyncService.syncCampaignParticipant(
campaign.id,
user.email,
user.name
);
// Sync all participants
await listmonkSyncService.syncAllParticipants(campaign.id);
// Sync location members
await listmonkSyncService.syncLocationMembers(location.id);
```
## Admin Interface
### Connection Status
Display:
- Connected/disconnected status
- Listmonk version
- API endpoint
- Last sync time
### Sync Controls
Buttons:
- **Sync All Participants** - Sync all campaign participants
- **Sync All Locations** - Sync all location members
- **Test Connection** - Verify API access
- **Reinitialize** - Reset lists and subscribers
### List Statistics
Table showing:
- List name
- Subscriber count
- Campaign/location association
- Last updated time
## Security
### API Authentication
Listmonk v6+ requires auth on all endpoints:
```typescript
const headers = {
'Authorization': `Basic ${btoa(`${apiUser}:${apiToken}`)}`,
'Content-Type': 'application/json',
};
```
### Token Storage
API tokens stored as plaintext in Listmonk DB:
- Not bcrypt hashed
- Direct upsert possible
- Secure via Redis authentication
### Data Privacy
- Opt-in sync only
- User consent required (future)
- Unsubscribe support
- Data deletion on request
## Error Handling
### Sync Failures
Handled gracefully:
- Network errors logged
- Failed syncs retried
- Admin notifications
- Error statistics
### Rate Limiting
Respect Listmonk limits:
- Batch operations
- Delay between requests
- Queue large syncs
## Listmonk Features
### Campaign Management
Listmonk provides:
- Email campaign creation
- Template management
- Scheduling
- A/B testing
- Analytics
### Subscriber Management
- Import/export subscribers
- List segmentation
- Tags and attributes
- Bounce handling
- Unsubscribe management
### Analytics
- Open rates
- Click rates
- Bounce rates
- Unsubscribe rates
- Campaign reports
## API Endpoints
### Admin Endpoints
```
GET /api/listmonk/status # Connection status
GET /api/listmonk/stats # Sync statistics
POST /api/listmonk/sync-participants # Sync campaign participants
POST /api/listmonk/sync-locations # Sync location members
POST /api/listmonk/test-connection # Test API connection
POST /api/listmonk/reinitialize # Reset and reinitialize
```
## Limitations
### Current Limitations
- Listmonk v6+ only (auth required on all endpoints)
- No webhook support (future)
- Manual sync triggers
- No bi-directional sync (Listmonk → CM Lite)
### Future Enhancements
- Webhook integration
- Real-time sync
- Custom field mapping
- Advanced segmentation
- Campaign stats in CM Lite
## Troubleshooting
### Connection Issues
1. Check `LISTMONK_SYNC_ENABLED=true`
2. Verify `LISTMONK_API_URL` reachable
3. Confirm API user created
4. Test credentials with curl
### Sync Failures
1. Check logs for errors
2. Verify Listmonk database
3. Test API connection
4. Reinitialize if needed
## Related Documentation
- [Listmonk Page](../../frontend/pages/admin/listmonk-page.md)
- [Listmonk Client](../../backend/services/index.md)
- [Campaign Module](../../backend/modules/campaigns.md)
- [Environment Variables](../../deployment/environment-variables.md)
- [Docker Compose](../../deployment/docker-compose.md)