360 lines
7.9 KiB
Markdown
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)
|