Skip to main content
The CRM (Customer Relationship Management) system is the central hub for managing contacts, tracking engagement, and orchestrating communication campaigns across the CAFH Platform.

Overview

The CRM module (AdminViews.tsx:622-1279) provides comprehensive contact management with:
  • Contact database with advanced filtering
  • Email campaign orchestration
  • Engagement metrics and scoring
  • List and segment management
  • Mailrelay integration
  • Bulk operations and automation

Contact Structure

Contacts are stored with detailed profile information (types.ts:268-286):
export interface Contact {
  id: string;
  name: string;
  firstName?: string;
  lastName?: string;
  email: string;
  phone: string;
  role: string;
  status: 'Subscribed' | 'Unsubscribed' | 'Bounced' | 'Pending' | 'new';
  lastContact: string;
  tags: string[];
  notes?: string;
  engagementScore?: number; // 0-100
  mailrelayId?: string; // ID in Mailrelay system
  city?: string;
  country?: string;
  createdAt?: string;
  listIds?: string[]; // Arrays of list IDs
}

Accessing the CRM

1

Navigate to CRM

Go to Admin Panel → Gestión de Contactos from the main dashboard
2

View Dashboard

See KPIs including total contacts, email metrics, and engagement rates
3

Browse Contacts

Use the contacts table with pagination (50 contacts per page)
4

Apply Filters

Filter by status, lists, tags, or search by name/email

Dashboard KPIs

The CRM dashboard displays real-time metrics (AdminViews.tsx:83-120):

Total Contactos CRM

Total contacts with breakdown of subscribed count

Emails Enviados

Total emails sent with open rate percentage

Tasa de Apertura

Email open rate as percentage

Tasa de Efectividad

Subscribed contacts / total contacts ratio

KPI Calculations

KPIs are calculated from live data (AdminViews.tsx:41-47):
const totalContacts = contacts.length;
const subscribedContacts = contacts.filter(c => c.status === 'Subscribed').length;
const totalEmailsSent = emailLogs.length;
const openedEmails = emailLogs.filter(l => 
  l.status === 'Opened' || l.status === 'Clicked'
).length;
const openRate = totalEmailsSent > 0 
  ? Math.round((openedEmails / totalEmailsSent) * 100) 
  : 0;

Contact Statuses

StatusDescriptionBadge Color
SubscribedActive, receives emailsGreen
PendingAwaiting confirmationAmber
UnsubscribedOpted out of emailsGray
BouncedEmail address invalid/rejectedRed
newNewly created, not processedBlue

Contact Details Panel

Click any contact to open the detailed off-canvas panel (AdminViews.tsx:284-513):

Information Sections

  • Email: Send individual message
  • Sincronizar: Sync with Mailrelay
  • Métricas: View engagement statistics

Engagement Scoring

Engagement scores help identify active vs. inactive contacts:

Score Calculation

Scores are calculated based on:
  • Email opens: +5 points each
  • Email clicks: +10 points each
  • Recent activity: Weighted by recency
  • Campaign participation: Bonus points

Score Ranges

  • High (70-100): Very engaged, green indicator
  • Medium (40-69): Moderately engaged, amber indicator
  • Low (0-39): Needs re-engagement, red indicator
Use engagement scores to segment your audience for targeted campaigns. Send re-engagement campaigns to contacts with scores below 40.

Search and Filtering

The CRM provides powerful filtering options (AdminViews.tsx:643-672):

Search Query

Search box filters by:
  • Contact name (case-insensitive)
  • Email address
  • Tags

Filter Options

  • All statuses
  • ✅ Subscribed
  • 🕐 Pending
  • 🚫 Unsubscribed
  • ⚠️ Bounced

Clear Filters

Click the Limpiar button to reset all filters to defaults.

Bulk Operations

Select multiple contacts to perform bulk actions (AdminViews.tsx:1023-1082):
1

Select Contacts

Use checkboxes to select individual contacts or “Select All”
2

Choose Action

Actions appear in the toolbar when contacts are selected
3

Execute

Confirm the action to apply to all selected contacts

Available Bulk Actions

ActionDescriptionIcon
Enviar EmailSend mass email to selected✉️
Agregar TagApply tag to all selected#
Agregar a ListaAdd to contact list📋
SuscribirChange status to Subscribed
DesuscribirChange status to Unsubscribed
EliminarPermanently delete contacts🗑️
Bulk delete operations are permanent and cannot be undone. Always confirm you have the right selection before deleting.

Email Metrics Dashboard

When “Ver Métricas” is enabled, view detailed email analytics (AdminViews.tsx:870-969):

Charts and Visualizations

  1. Email Activity Chart: 7-day trend of sent vs. opened emails
  2. Queue Status: Real-time sending queue with throttle limits
  3. Rate Metrics: Open rate, click rate, bounce rate cards

List-Specific Metrics

Filter metrics by contact list to see:
  • Performance of specific segments
  • Engagement by audience type
  • Comparative analysis between lists

Email Queue and Throttling

The platform implements hourly send limits to avoid spam flags (AdminViews.tsx:914-950):
const queueStatus = {
  pending: 45,        // Emails in queue
  sent: 120,          // Total sent
  failed: 3,          // Failed deliveries
  sentCountThisHour: 68,  // Hourly counter
  limit: 80           // cPanel hourly limit
}
The system automatically throttles sending to stay within your hosting provider’s hourly email limit (typically 80 emails/hour for shared hosting).

Mailrelay Integration

Sync contacts with external Mailrelay system (storage.ts:805-812):
1

Open Contact Panel

Click a contact to open their detail view
2

Click Sincronizar

Press the sync button with refresh icon
3

API Call

System calls Mailrelay API to create/update contact
4

Store Mailrelay ID

The returned ID is saved to the contact record

Sync Function

db.mailrelay.syncContact(contact)
// Returns updated contact with mailrelayId

Contact Import

Bulk import contacts from CSV or JSON (storage.ts:650-664):
1

Click Carga Masiva

Open the import modal from the CRM toolbar
2

Choose Format

Select CSV or JSON file format
3

Map Fields

Map your file columns to contact fields
4

Preview

Review the first 5 rows to verify mapping
5

Import

Confirm to add all contacts to the database

CSV Format Example

name,email,phone,city,country,status,tags
Juan Pérez,[email protected],+56912345678,Santiago,Chile,Subscribed,"member,2024"
María González,[email protected],+56987654321,Valparaíso,Chile,Pending,"lead,retreat"
Large imports (>500 contacts) may hit localStorage limits. Consider batch imports of 250-500 contacts at a time.

Contact Editor

Create or edit contacts with the dedicated editor modal (AdminViews.tsx:622):

Editable Fields

  • Name: Full name or display name
  • Email: Primary email address (unique)
  • Phone: Contact phone number
  • City / Country: Location information
  • Status: Subscription status
  • Tags: Comma-separated tags
  • Lists: Assign to one or more lists
  • Notes: Internal notes (not visible to contact)

Validation

  • Email must be valid format
  • Email must be unique in database
  • Name is required
  • Phone format is validated for Chilean numbers

SMTP Configuration

Configure email sending settings (storage.ts:717-726):
export interface SMTPConfig {
  host: string;      // e.g., 'mail.cafh.cl'
  port: string;      // e.g., '465'
  secure: boolean;   // SSL/TLS
  user: string;      // SMTP username
  pass: string;      // SMTP password
  fromEmail: string; // Sender address
  fromName: string;  // Sender name
}
SMTP credentials are stored in localStorage. For production, migrate sensitive config to environment variables.

Data Storage

CRM data is stored in localStorage (storage.ts:10):
KeyContent
cafh_contacts_v1Array of Contact objects
cafh_crm_lists_v1Contact list definitions
cafh_email_logs_v1Email send history
cafh_email_metrics_v1Aggregate email metrics
cafh_smtp_config_v1SMTP server configuration

Storage Limits

  • Contacts: ~2,000-5,000 (depending on field data)
  • Email Logs: Limited to prevent overflow
  • Lists: Unlimited (lightweight objects)

Contact Lists

Manage lists and segmentation

User Roles

Configure admin access permissions

Build docs developers (and LLMs) love