Skip to main content

Subscriber Management

Newsletter

Import, export, segment, and manage your newsletter subscribers.

Import/Export

CSV, JSON support

Segmentation

Target by attributes

Double Opt-In

GDPR compliance

Engagement Tracking

Activity & health

Add Subscribers

Add subscribers programmatically:

Single subscriber
import { platform } from '@/lib/platform'

// Subscribe with verification email (double opt-in)
const subscriber = await platform.newsletter.subscribe({
  email: 'user@example.com',
  preferences: ['product_updates', 'weekly_digest'],
  source: 'signup_form',
  metadata: {
    name: 'John Doe',
    company: 'Acme Inc',
    plan: 'pro',
  },
})

// subscriber.status = 'pending' until verified
Bulk subscribe
// Import multiple subscribers at once
const result = await platform.newsletter.bulkSubscribe({
  subscribers: [
    { email: 'alice@example.com', preferences: ['all'] },
    { email: 'bob@example.com', preferences: ['product_updates'] },
    { email: 'carol@example.com', preferences: ['promotions'] },
  ],
  source: 'import',
  sendVerification: true, // Send double opt-in emails
})

// result.added = 3
// result.duplicates = 0
// result.invalid = 0

Double Opt-In Flow

The recommended subscription flow for GDPR compliance:

1

User Submits Email

User enters email in your signup form. Call newsletter.subscribe().

2

Verification Email Sent

Subscriber receives email with verification link. Status is pending.

3

User Clicks Link

Clicking the link verifies their email. Status becomes verified.

4

Ready to Receive

Subscriber can now receive campaigns. Webhook newsletter.verified fires.

Skip verification (not recommended)
// Only use for trusted sources (admin import, migrating lists)
await platform.newsletter.subscribe({
  email: 'user@example.com',
  preferences: ['all'],
  doubleOptIn: false, // Skip verification
  source: 'admin_import',
})

Legal Compliance

Skipping double opt-in may violate GDPR and CAN-SPAM regulations. Only skip for subscribers who have already verified consent elsewhere.

Import Subscribers

Import existing subscribers from CSV or JSON:

CSV Import
// Import from CSV file
const result = await platform.newsletter.import({
  format: 'csv',
  data: csvFileContent,
  mapping: {
    email: 'Email Address', // CSV column name
    name: 'Full Name',
    preferences: 'Topics', // Comma-separated in CSV
  },
  options: {
    sendVerification: true,
    skipDuplicates: true,
    source: 'mailchimp_migration',
  },
})

// {
//   total: 5000,
//   added: 4850,
//   duplicates: 120,
//   invalid: 30,
//   errors: [...]
// }
JSON Import
// Import from JSON array
await platform.newsletter.import({
  format: 'json',
  data: [
    {
      email: 'user1@example.com',
      preferences: ['product_updates'],
      metadata: { source: 'website' },
    },
    {
      email: 'user2@example.com',
      preferences: ['all'],
      metadata: { source: 'api' },
    },
  ],
})

Export Subscribers

Export your subscriber list:

// Export all subscribers
const { data, count } = await platform.newsletter.export({
  format: 'csv', // or 'json'
  fields: ['email', 'preferences', 'subscribedAt', 'status'],
})

// Export specific segment
const { data } = await platform.newsletter.export({
  format: 'json',
  segment: {
    status: 'verified',
    preferences: { includes: 'product_updates' },
  },
  fields: ['email', 'metadata.name', 'metadata.company'],
})

Segmentation

Create segments to target specific subscribers:

// Get subscribers by preference
const productUsers = await platform.newsletter.getSubscribers({
  segment: {
    preferences: { includes: 'product_updates' },
  },
})

// Multiple conditions
const targetedSegment = await platform.newsletter.getSubscribers({
  segment: {
    status: 'verified',
    preferences: { includes: 'promotions' },
    metadata: {
      plan: { in: ['pro', 'enterprise'] },
      country: 'US',
    },
    subscribedAfter: '2024-01-01',
    lastEngaged: { within: '30d' }, // Active in last 30 days
  },
  limit: 1000,
})

// Count segment size
const count = await platform.newsletter.countSubscribers({
  segment: { preferences: { includes: 'weekly_digest' } },
})

Segment Operators

PropertyTypeDescription
includesstringArray contains value (for preferences)
eqanyEquals exact value
inarrayValue is in array
gt / gtenumber | DateGreater than (or equal)
lt / ltenumber | DateLess than (or equal)
withinstringWithin time period (e.g., "30d")
existsbooleanField exists / not null

Subscriber Status

Track subscriber status throughout lifecycle:

pending

Awaiting email verification

verified

Can receive campaigns

unsubscribed

Opted out of all emails

bounced

Email delivery failed

complained

Marked as spam

// Get subscriber details
const subscriber = await platform.newsletter.getSubscriber({
  email: 'user@example.com',
})

// {
//   email: 'user@example.com',
//   status: 'verified',
//   preferences: ['product_updates', 'weekly_digest'],
//   metadata: { name: 'John', plan: 'pro' },
//   subscribedAt: '2024-01-15T10:00:00Z',
//   verifiedAt: '2024-01-15T10:05:00Z',
//   lastEngaged: '2024-01-20T14:30:00Z',
//   engagement: {
//     opens: 12,
//     clicks: 5,
//     campaigns: 8,
//   }
// }

Update & Unsubscribe

Manage subscriber preferences and status:

// Update preferences
await platform.newsletter.updateSubscriber({
  email: 'user@example.com',
  preferences: {
    product_updates: true,
    promotions: false,
    weekly_digest: true,
  },
  metadata: {
    plan: 'enterprise', // Update metadata
  },
})

// Unsubscribe
await platform.newsletter.unsubscribe({
  email: 'user@example.com',
  reason: 'Too many emails', // Optional feedback
})

// Resubscribe (sends new verification)
await platform.newsletter.resubscribe({
  email: 'user@example.com',
})

List Health

Monitor your subscriber list health:

const health = await platform.newsletter.getListHealth()

// {
//   total: 10000,
//   verified: 8500,
//   pending: 500,
//   unsubscribed: 800,
//   bounced: 150,
//   complained: 50,
//   activeRate: 75.2, // Engaged in last 90 days
//   bounceRate: 1.5,
//   unsubscribeRate: 0.8,
//   growthRate: 5.2, // Month over month
// }

Clean Your List

Regularly remove bounced and complained subscribers to maintain deliverability. High bounce rates can affect your sender reputation.