Skip to main content
Contact Lists allow you to organize your contacts into segments for targeted email campaigns, reporting, and automation workflows.

List Structure

Lists are lightweight organizational containers (types.ts:260-266):
export interface ContactList {
  id: string;
  name: string;
  description: string;
  createdAt: string;
  contactCount?: number;
}

Accessing List Management

1

Open CRM

Navigate to Admin → Gestión de Contactos
2

Click Listas / Segmentos

Button in the top toolbar opens the lists panel
3

View All Lists

See all existing lists with contact counts
4

Create or Edit

Add new lists or modify existing ones

Creating a List

1

Click New List

Press ”+ Nueva Lista” in the lists panel
2

Enter Name

Choose a descriptive name (e.g., “Newsletter Subscribers”)
3

Add Description

Describe the list’s purpose and target audience
4

Save

The list is created and available immediately

List Naming Conventions

Good Names:
  • “Newsletter - Bienestar y Meditación”
  • “Retiro Santiago 2024”
  • “Miembros Activos”
  • “Leads - Website Footer”
Poor Names:
  • “Lista 1”
  • “Test”
  • “Contactos”

Common List Types

Newsletter Subscribers

All contacts who signed up for email updates

Event Attendees

Participants in specific events or retreats

Active Members

Current community members with high engagement

Leads

New contacts not yet fully onboarded

Inactive

Contacts with low engagement scores

VIP

High-value contacts (donors, coordinators)

Adding Contacts to Lists

Individual Assignment

1

Open Contact Panel

Click a contact in the CRM table
2

View Lists Section

Scroll to “Listas & Segmentos” in the panel
3

Add to List

Click ”+” button to select lists
4

Save

Contact is immediately added to selected lists

Bulk Assignment

Add multiple contacts at once (AdminViews.tsx:1050-1064):
1

Select Contacts

Check boxes for contacts to add
2

Click Agregar a Lista

Button appears in bulk action toolbar
3

Choose List

Select destination list from dropdown
4

Confirm

All selected contacts are added to the list
// Bulk add to list implementation
handleBulkAddToList = () => {
  if (!bulkListId) return;
  selectedIds.forEach(id => {
    const contact = contacts.find(x => x.id === id);
    if (!contact) return;
    const listIds = Array.from(new Set([...(contact.listIds || []), bulkListId]));
    db.crm.save({ ...contact, listIds });
  });
}

List Management Functions

Programmatic list operations (storage.ts:666-709):

Create List

const newList = db.crm.addList({
  name: "Newsletter - Meditación",
  description: "Suscriptores interesados en contenido de meditación"
});
// Returns: ContactList with generated id and createdAt

Update List

db.crm.updateList({
  id: "list_abc123",
  name: "Newsletter - Meditación y Bienestar",
  description: "Actualizado para incluir bienestar general",
  createdAt: "2024-01-15",
  contactCount: 245
});

Delete List

db.crm.deleteList("list_abc123");
// Removes list and removes list ID from all contacts
Deleting a list removes it from all contacts. This action is permanent and cannot be undone.

Filtering by List

Use list filters to view specific segments:
1

Open CRM Table

View the main contacts table
2

Select List Filter

Choose a list from the “Todas las listas” dropdown
3

View Filtered Contacts

Table shows only contacts in that list
4

Perform Actions

Bulk actions apply only to filtered contacts

Combined Filters

You can combine list filters with:
  • Status filters (Subscribed, Pending, etc.)
  • Tag filters
  • Search queries

List-Based Metrics

View email performance by list (AdminViews.tsx:727-755):
1

Enable Metrics View

Click “Ver Métricas” in the CRM toolbar
2

Select List

Choose a list from the metrics dropdown
3

View Analytics

See open rates, click rates, and engagement for that list

Calculated Metrics

const contactsInList = contacts.filter(c => c.listIds?.includes(listId));
const logsForList = emailLogs.filter(l => 
  contactsInList.some(c => c.id === l.contactId)
);

const openRate = logsForList.length > 0
  ? Math.round((openedCount / logsForList.length) * 100)
  : 0;

Campaign Targeting

Lists are used to target email campaigns (storage.ts:859-906):

Campaign Recipient Options

TypeDescriptionUse Case
AllEvery contact in CRMRare, system announcements only
SubscribedAll subscribed contactsGeneral newsletters
ListSpecific contact listTargeted campaigns
TagContacts with specific tagInterest-based campaigns

Example: Campaign to List

const campaign = {
  name: "Newsletter Julio 2024",
  subject: "Nuevos recursos de meditación",
  recipientType: "list",
  listId: "list_newsletter_meditacion",
  content: "<html>...</html>",
  status: "Draft"
};

db.campaigns.create(campaign);

Automation Triggers

Lists can trigger automation workflows (types.ts:383-400):

Contact Added to List Trigger

const automation = {
  name: "Welcome Series",
  trigger: {
    type: "contact_added_to_list",
    listId: "list_new_subscribers"
  },
  nodes: [
    {
      type: "send_email",
      subject: "Bienvenido a Cafh",
      content: "<p>Gracias por unirte...</p>"
    },
    {
      type: "wait",
      amount: 3,
      unit: "days"
    },
    {
      type: "send_email",
      subject: "Recursos para comenzar",
      content: "<p>Te compartimos...</p>"
    }
  ]
};
Use list-based automation to create onboarding sequences, nurture campaigns, and re-engagement workflows.

List vs. Tags

When to Use Lists

  • Campaigns: Targeting specific email campaigns
  • Automation: Triggering workflows
  • Reporting: Analyzing segment performance
  • Organization: Grouping by acquisition source

When to Use Tags

  • Interests: User interests (“meditación”, “retiros”)
  • Behavior: Actions taken (“downloaded-guide”, “attended-event”)
  • Attributes: Characteristics (“beginner”, “advanced”)
  • Flexible Filtering: Ad-hoc segmentation
A contact can be in multiple lists and have multiple tags. Use both for powerful segmentation.

List Contact Count

Track how many contacts are in each list:
const list = db.crm.getLists().find(l => l.id === listId);
const contactsInList = db.crm.getAll().filter(c => 
  c.listIds?.includes(listId)
).length;

// Update count
list.contactCount = contactsInList;
db.crm.updateList(list);
Contact counts update automatically when contacts are added or removed from lists.

List Hygiene

Maintain clean, effective lists:

Monthly Tasks

  • Search for duplicate emails
  • Merge contact records
  • Keep most complete record
  • Review contacts with ‘Bounced’ status
  • Remove from active lists
  • Move to ‘Inactive’ list
  • Identify completed event lists
  • Archive or delete if no longer needed
  • Document for historical reference
  • Check average engagement scores per list
  • Segment low-engagement contacts
  • Create re-engagement campaigns

GDPR and Compliance

Best Practices

  • Consent: Only add contacts who opted in
  • Unsubscribe: Honor unsubscribe requests immediately
  • Data Retention: Remove inactive contacts after 2 years
  • Transparency: Document list purposes
Never purchase or import lists without explicit consent. This violates GDPR and anti-spam laws.

List Export

Export contacts from a list for external use:
const listId = "list_newsletter";
const contactsInList = db.crm.getAll().filter(c => 
  c.listIds?.includes(listId)
);

// Convert to CSV
const csv = [
  "name,email,status,phone",
  ...contactsInList.map(c => 
    `${c.name},${c.email},${c.status},${c.phone}`
  )
].join("\n");

// Download
const blob = new Blob([csv], { type: "text/csv" });
const url = URL.createObjectURL(blob);

CRM Overview

Complete CRM system documentation

User Roles

Manage admin permissions

Build docs developers (and LLMs) love