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)
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
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
emailandnamecolumns 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
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:
- The campaign status changes to
sending. - Target subscribers are resolved based on assigned segments (or all active subscribers if no segments).
- A
newsletter_campaign_logsrecord is created for each subscriber in a database transaction. - Each log entry is processed: the subscriber receives a Laravel Notification
(email via
MailMessageor SMS via Vonage/Twilio channel). - Successful deliveries are marked as
sent; failures are logged with the error message. - The campaign status updates to
sentwith the finalrecipients_count.
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.driverconfiguration. - 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.
/{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)
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.
/{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
/{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)
- Visitor submits the subscription form with their email (and optionally name, phone, segments).
- A subscriber record is created with
status = 'pending'. - A confirmation email is sent with a unique token link.
- Visitor clicks the confirmation link.
- Subscriber status changes to
confirmed. - A welcome email is sent (if subject and content are configured in settings).
- The subscriber is now eligible to receive campaigns.
Without Double Opt-In
- Visitor submits the subscription form.
- A subscriber record is created with
status = 'confirmed'immediately. - A welcome email is sent (if configured).
- The subscriber is immediately eligible to receive campaigns.
Re-subscription
If a previously unsubscribed email submits the form again:
- The existing record is found and its status is reset to
pending. - A new token is generated and a confirmation email is sent (if double opt-in is enabled).
- The
unsubscribed_attimestamp 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
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_toif configured - Unsubscribe link is included in the email footer
SMS Delivery
- Routes through Vonage (
VonageMessage) or Twilio (TwilioSmsMessage) based onsettings.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.
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_logstable for error messages on failed deliveries.
SMS campaigns failing
- Ensure the Vonage or Twilio package is installed and configured.
- Verify
settings.sms.driveris set to eithervonageortwilio. - 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:
- Check
newsletter_campaign_logsfor the campaign to see how far delivery progressed. - Manually update the campaign’s
statustofailedorsentin the database. - For large lists, consider implementing queue-based sending to avoid timeouts.
Subscribers not being assigned to default segments
- Ensure the segment has
is_default = trueandis_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.confirmtheme::newsletter.unsubscribe
Create these views in your active theme’s views/ directory to override the default templates.