Newsletter Platform

Collect email and SMS subscribers, organize them into segments, compose campaigns, and send targeted communications: all from within your Larapen admin panel.

Subscriber Management

Collect subscribers via front-end forms, CSV import, or manual entry. Track status, source, and segment membership.

Double Opt-In

Optional email confirmation flow ensures valid addresses. Subscribers receive a confirmation link before being activated.

Segments

Group subscribers into targeted segments. Public segments let visitors choose which lists to join. Default segments auto-assign.

Email & SMS Campaigns

Compose translatable campaigns, target specific segments, and send via email or SMS (Vonage/Twilio). Track opens and clicks.

Import & Export

Bulk import subscribers from CSV files with automatic column detection. Export active subscribers to CSV at any time.

Welcome Emails

Configurable welcome email with translatable subject and content, sent automatically to newly confirmed subscribers.

Use Cases

Portfolio Site with Updates

You run a portfolio site and want to keep clients informed about new projects and services.

  • Add a subscription form to your footer or a dedicated page section.
  • Create segments like “Clients” and “Prospects” to send targeted updates.
  • Compose campaigns announcing new projects or services and send to all or specific segments.

SaaS Product with Launch List

You are building a product and want to collect early-access signups.

  • Enable double opt-in to ensure valid email addresses.
  • Create a “Beta Waitlist” segment and mark it as default.
  • When ready to launch, compose a campaign targeting the waitlist segment.

Multi-Topic Blog Newsletter

Your blog covers multiple topics and readers want to subscribe only to what interests them.

  • Create public segments for each topic (e.g. “Tech”, “Design”, “Business”).
  • Visitors choose their interests via checkboxes on the subscription form.
  • Send topic-specific campaigns to the relevant segments only.

SMS Alerts for Local Business

You run a local business and want to send SMS promotions to customers.

  • Collect phone numbers through the subscription form (phone field).
  • Create SMS campaigns with plain-text content (HTML is auto-stripped).
  • Send via Vonage or Twilio depending on your configured SMS driver.

Requirements

  • Larapen CMS v1.0.0 or later
  • PHP 8.3+
  • MySQL 8.0+
  • A configured mail driver (for email campaigns and confirmation emails)
  • Optional: Vonage or Twilio account and package (for SMS campaigns)
Note: The add-on works fully with email-only features out of the box. SMS campaign support requires a Vonage or Twilio integration configured in your application.

Installation

Step 1: Place the Add-on

Copy or symlink the newsletter folder into your Larapen "extensions/addons" directory:

Step 2: Activate the Add-on

Go to Admin → Add-ons → Installed Add-ons and activate Newsletter Platform.

Step 3: Run Migrations

This creates 5 tables: newsletter_subscribers, newsletter_segments, newsletter_segment_subscriber, newsletter_campaigns, and newsletter_campaign_logs. It also creates the pivot table newsletter_campaign_segment.

Step 4: Set Permissions

The add-on registers 14 permissions (see Permissions). Assign them to admin roles via Admin → Users → Roles & Permissions.

Step 5: Configure

Navigate to Admin → Newsletter → Settings and configure your sender name, email address, and opt-in preferences. See Configuration.

Configuration

Settings are managed in Admin → Newsletter → Settings (stored in the settings table, group newsletter). Config defaults are defined in config/newsletter.php.

Setting Description Default
newsletter_double_opt_in When enabled, subscribers must confirm their email address via a confirmation link before being added to the list. true
newsletter_from_name The name displayed in the “From” field of newsletter emails. APP_NAME
newsletter_from_email The email address used in the “From” field of newsletter emails. MAIL_FROM_ADDRESS
newsletter_reply_to The email address where replies will be sent. Leave empty to use the From email. (empty)
newsletter_welcome_subject Subject line for the welcome email (translatable, per-locale). Leave empty to disable the welcome email. (empty)
newsletter_welcome_content Body content of the welcome email (translatable, per-locale). Leave empty to disable. (empty)

Environment Variables

Note: Environment variables are used as fallback defaults in config/newsletter.php. Settings saved in the admin panel (stored in the database) override them at boot time via the service provider.

Admin: Settings

The settings page (Newsletter → Settings) is organized into sections:

Opt-in Settings

  • Double Opt-In: Toggle switch. When enabled, new subscribers receive a confirmation email and remain in “pending” status until they click the confirmation link.

Email Settings

  • From Name: The sender name for all newsletter emails.
  • From Email: The sender email address.
  • Reply-To Email: Where replies go. Leave empty to use the From email.

Welcome Email

  • Welcome Email Subject: Translatable text input (one per language). Set the subject line of the welcome email sent after subscription confirmation.
  • Welcome Email Content: Translatable textarea. The body of the welcome email. Leave both subject and content empty to disable the welcome email entirely.

Admin: Subscribers

The Subscribers page (Newsletter → Subscribers) is the main subscriber management view.

Statistics Dashboard

A row of stat cards at the top shows:

  • Total Subscribers: all records in the table
  • Confirmed: active, confirmed subscribers
  • Pending: awaiting email confirmation
  • Unsubscribed: opted out
  • New This Month: subscribers created in the current calendar month

Subscribers List

A paginated table (20 per page) with filters:

  • Status filter: dropdown to show All, Pending, Confirmed, or Unsubscribed
  • Segment filter: dropdown to filter by segment membership

Each row shows: email, name, phone, status badge, source badge, segment tags, subscribed date, and a delete action.

Adding a Subscriber

Click Add Subscriber to open the creation form:

  • Email: required, must be unique in the subscribers table
  • Phone: optional, for SMS campaigns
  • Name: optional
  • Status: select: Pending, Confirmed, or Unsubscribed
  • Segments: multi-select of active segments

Manually added subscribers have source = 'manual'. If set to “Confirmed”, their confirmed_at and subscribed_at timestamps are set immediately.

Import & Export

Import from CSV

Click Import to upload a CSV file. Requirements:

  • The first row must be a header row.
  • The importer auto-detects email and name columns from the header.
  • If no header match is found, column 1 is treated as email, column 2 as name.
  • Maximum file size: 5 MB.
  • Accepted formats: .csv, .txt

Imported subscribers are created with status = 'confirmed' and source = 'import'. Duplicate emails are skipped. After import, a summary shows how many were imported vs. skipped.

Export to CSV

Click Export to download a CSV of all active (confirmed) subscribers. The export includes: Email, Name, Status, Subscribed At, and Source columns.

Admin: Segments

Segments (Newsletter → Segments) let you group subscribers into targeted lists.

Segments List

A paginated table showing each segment with:

  • Color swatch: visual identifier
  • Name (translatable)
  • Description (translatable)
  • Active subscribers count
  • Flags: Public, Default, Active badges
  • Position: sort order

Create & Edit

The segment form includes:

  • Name: translatable, required in the default language
  • Description: translatable, optional
  • Color: hex color picker (validated as #RRGGBB)
  • Public: when enabled, the segment appears on front-end subscription forms, allowing visitors to choose which lists to join
  • Default: new subscribers are automatically added to default segments, regardless of their form selection
  • Active: inactive segments are excluded from campaign targeting and front-end forms
  • Position: integer for display ordering
Note: Deleting a segment removes the segment-subscriber associations but does not delete the subscribers themselves.

Admin: Campaigns

Campaigns (Newsletter → Campaigns) are the email or SMS messages you send to subscribers.

Campaigns List

A paginated table (20 per page) with an optional status filter showing:

  • Subject
  • Channel: Email or SMS badge
  • Status badge: Draft, Scheduled, Sending, Sent, or Failed
  • Segments: target segment names, or “All subscribers”
  • Recipients / Opens / Clicks: delivery statistics
  • Author
  • Created date

Composing a Campaign

Click New Campaign to open the compose form:

  • Sending Mode: toggle between Email and SMS
  • Subject: translatable text input (required for email in default locale, optional for SMS)
  • Content: translatable rich text editor (required in default locale). For SMS mode, HTML is automatically stripped when saving.
  • Target Segments: multi-select of active segments. If none are selected, the campaign sends to all active subscribers.
  • Scheduled At: optional datetime field for future scheduling

Campaigns are created in draft status. The active subscriber count is displayed to indicate how many recipients will receive the campaign.

Editing Campaigns

Only campaigns in draft or scheduled status can be edited. Once a campaign enters sending or sent status, it becomes read-only and displays as a detail view with delivery statistics.

Sending a Campaign

When you click Send Now, the following process occurs:

  1. The campaign status changes to sending.
  2. Target subscribers are resolved based on assigned segments (or all active subscribers if no segments).
  3. A newsletter_campaign_logs record is created for each subscriber in a database transaction.
  4. Each log entry is processed: the subscriber receives a Laravel Notification (email via MailMessage or SMS via Vonage/Twilio channel).
  5. Successful deliveries are marked as sent; failures are logged with the error message.
  6. The campaign status updates to sent with the final recipients_count.
Important: Sending is synchronous in the current implementation. For large subscriber lists, consider running the send operation in a queued job or during off-peak hours to avoid request timeouts.

SMS Campaign Mode

When the sending mode is set to SMS:

  • The subject field becomes optional (SMS messages have no subject line).
  • HTML content is automatically stripped from all locale translations when the campaign is saved.
  • Content is truncated to 1600 characters (10 SMS parts) when sent.
  • The notification routes through the Vonage or Twilio channel based on the settings.sms.driver configuration.
  • Only subscribers with a phone number receive SMS campaigns; those without are skipped with an error.

Front-end: Subscribe Form

The subscription form is typically embedded in theme views (footer, sidebar, or a dedicated section). It submits via AJAX and returns a JSON response.

POST /{locale}/newsletter/subscribe
Request Body
email Required (without phone) Valid email address, max 255 characters
phone Required (without email) Phone number for SMS, max 20 characters
name Optional Subscriber name, max 255 characters
segment_ids[] Optional Array of segment IDs (must exist in newsletter_segments)
Response (JSON)
Rate limiting: Subscription attempts are limited to 5 per minute per IP address (configurable via newsletter.rate_limit in the config file).

Front-end: Email Confirmation

When double opt-in is enabled, subscribers receive an email with a confirmation link.

GET /{locale}/newsletter/confirm/{token}
Description

Confirms a subscriber’s email address using their unique 64-character token. On success, the subscriber’s status changes to confirmed and their confirmed_at and subscribed_at timestamps are set. A welcome email is sent if configured.

Renders a themed confirmation page (theme::newsletter.confirm if available, otherwise falls back to newsletter::front.confirm).

Front-end: Unsubscribe

GET /{locale}/newsletter/unsubscribe/{token}
Description

Unsubscribes a subscriber using their unique token. Sets the subscriber’s status to unsubscribed and records the unsubscribed_at timestamp.

Renders a themed unsubscribe page (theme::newsletter.unsubscribe if available, otherwise falls back to newsletter::front.unsubscribe).

Unsubscribe links are included in campaign emails automatically via the campaign email template.

Subscription Flow

With Double Opt-In Enabled (Default)

  1. Visitor submits the subscription form with their email (and optionally name, phone, segments).
  2. A subscriber record is created with status = 'pending'.
  3. A confirmation email is sent with a unique token link.
  4. Visitor clicks the confirmation link.
  5. Subscriber status changes to confirmed.
  6. A welcome email is sent (if subject and content are configured in settings).
  7. The subscriber is now eligible to receive campaigns.

Without Double Opt-In

  1. Visitor submits the subscription form.
  2. A subscriber record is created with status = 'confirmed' immediately.
  3. A welcome email is sent (if configured).
  4. The subscriber is immediately eligible to receive campaigns.

Re-subscription

If a previously unsubscribed email submits the form again:

  1. The existing record is found and its status is reset to pending.
  2. A new token is generated and a confirmation email is sent (if double opt-in is enabled).
  3. The unsubscribed_at timestamp is cleared.

Segment Assignment

When a subscriber is created or re-subscribed:

  • All default segments (segments with is_default = true) are automatically assigned.
  • Any segment IDs submitted via the form are also assigned.
  • Both are merged and applied using syncWithoutDetaching, so existing memberships are preserved.

Confirmation Email

The SubscriptionConfirmationNotification sends a Markdown email using the newsletter::emails.subscription-confirmation template.

  • Subject: “Confirm your subscription to {site_name}” (translatable)
  • From: Uses newsletter.from_email / newsletter.from_name
  • Action button: Links to /newsletter/confirm/{token}

Failures during email sending are caught silently: the subscriber is still created in pending state.

Welcome Email

The WelcomeNotification is sent after a subscriber is confirmed, but only if the admin has configured both a subject and content in the newsletter settings.

  • Subject & Content: Read from database settings, resolved by current locale with fallback to the application’s fallback locale.
  • Unsubscribe link: Included in the email template.
  • From: Uses newsletter.from_email / newsletter.from_name
Disabling: To disable the welcome email, leave the Welcome Email Subject and Content fields empty in the newsletter settings.

Campaign Delivery

The CampaignNotification handles both email and SMS delivery using Laravel’s notification system.

Email Delivery

  • Uses a Markdown template: newsletter::emails.campaign
  • Subject and content are translatable (resolved by the app locale)
  • Reply-To is applied from newsletter.reply_to if configured
  • Unsubscribe link is included in the email footer

SMS Delivery

  • Routes through Vonage (VonageMessage) or Twilio (TwilioSmsMessage) based on settings.sms.driver
  • Content is stripped of HTML tags and truncated to 1600 characters
  • Unicode mode is enabled for Vonage to support international characters

Updating

Step 1: Replace Files

Replace the add-on directory with the new version.

Step 2: Run Migrations

Step 3: Clear Caches

Step 4: Verify

Visit Admin → Newsletter → Settings and confirm your settings are intact. Check the subscribers list to verify data integrity.

Backup first: Always back up your database before running migrations on a production system.

Troubleshooting

Confirmation emails not being sent

  • Ensure your mail driver is correctly configured in .env (MAIL_MAILER, MAIL_HOST, etc.).
  • Check that Double Opt-In is enabled in Newsletter settings.
  • Check the Laravel log file (storage/logs/laravel.log) for mail sending errors.
  • Confirmation email failures are caught silently: the subscriber is still created in pending state, but no email is sent.

Welcome email not being sent

  • Ensure both Welcome Email Subject and Welcome Email Content are filled in for at least one language in the newsletter settings.
  • The welcome email requires content in the current locale or the fallback locale. If neither has content, it is skipped.

Subscribers not receiving campaigns

  • Verify the subscriber’s status is confirmed (pending and unsubscribed subscribers are excluded).
  • If the campaign targets specific segments, ensure the subscriber belongs to at least one of those segments.
  • Check the newsletter_campaign_logs table for error messages on failed deliveries.

SMS campaigns failing

  • Ensure the Vonage or Twilio package is installed and configured.
  • Verify settings.sms.driver is set to either vonage or twilio.
  • Subscribers must have a phone number to receive SMS campaigns. Those without phone numbers will produce a “Subscriber has no phone number” error in the campaign logs.

CSV import shows all subscribers as “skipped”

  • Ensure the CSV file has valid email addresses.
  • Duplicate emails (already in the database) are skipped by design.
  • Invalid email formats (failing FILTER_VALIDATE_EMAIL) are also skipped.
  • Check that the header row has a column labeled email (case-insensitive).

Campaign stuck in “sending” status

If the sending process was interrupted (e.g., request timeout, server crash), the campaign may remain in sending status. To recover:

  1. Check newsletter_campaign_logs for the campaign to see how far delivery progressed.
  2. Manually update the campaign’s status to failed or sent in the database.
  3. For large lists, consider implementing queue-based sending to avoid timeouts.

Subscribers not being assigned to default segments

  • Ensure the segment has is_default = true and is_active = true.
  • Default segments are only assigned at subscription time. Existing subscribers are not retroactively added when a segment is marked as default.

Theme views not overriding add-on views

The front-end confirmation and unsubscribe pages look for theme overrides at:

  • theme::newsletter.confirm
  • theme::newsletter.unsubscribe

Create these views in your active theme’s views/ directory to override the default templates.

Was this article helpful?

Thank you for your feedback!

Still need help? Create a support ticket

Create a Ticket