Appearance
Subscription State Diagrams
This document describes the subscription lifecycle, including state transitions, emails/notifications sent, and views rendered.
Subscription Status States
Status Definitions
| Status | Description | Can Receive Emails |
|---|---|---|
Unconfirmed | Signed up but hasn't clicked confirmation link (double opt-in pending) | No |
Active | Confirmed email, receiving emails | Yes |
Unsubscribed | Opted out via unsubscribe link | No |
Bounced | Email delivery failed permanently (invalid address, mailbox doesn't exist) | No |
Junk | Subscriber marked emails as spam | No |
Confirmation Flow
Legacy Controller: ConfirmSubscriptionController
Route: GET /newsletter/confirm (subscriptions.confirmDeprecated)
Signed Controller: ConfirmSubscriptionSignedController
Route: GET /subscriptions/{subscriber:token}/confirm/{list} (subscriptions.confirm)
Confirmation Emails Sent
| Notification | When Sent | Contact List |
|---|---|---|
SubscriberConfirmedEmail | After successful confirmation | PowerfulWeeklyEmail only |
Confirmation Views Rendered
| View | Condition |
|---|---|
pages.subscription.emailConfirmed.free-ebook | FREE_EBOOK_LIST or other lists |
pages.subscription.emailConfirmed.free-ebook-with-newsletter | POWERFUL_WEEKLY_EMAIL_LIST |
pages.subscription.error | Invalid link, not found, or cannot confirm |
Unsubscribe Flow
Legacy Controller: UnsubscribeController
Route: GET /newsletter/unsubscribe (subscription.unsubscribeDeprecated)
Signed Controller: UnsubscribeSignedController
Route: GET /subscriptions/{subscriber:token}/unsubscribe/{list} (subscriptions.unsubscribe)
Unsubscribe Emails Sent
| Notification | When Sent | Condition |
|---|---|---|
SubscriberUnsubscribed | After successful unsubscribe | Only if subscriber had previously confirmed their email (confirmed_at != null) |
Unsubscribe Views Rendered
| View | Data Passed |
|---|---|
pages.subscription.unsubscribe | message, title, email, resubscribe link, highlight_courses, books |
Complete Subscription Lifecycle
All Contact List Notifications
| Notification Class | Purpose | Trigger |
|---|---|---|
ConfirmationNeededForDownloadingFreeEbook | Double opt-in for free ebook | User subscribes for free ebook |
ConfirmationNeededForDownloadingFreeEbookWithWeeklyNewsletterSubscription | Double opt-in for ebook + newsletter | User subscribes for ebook and newsletter together |
ConfirmationNeededForWeeklyNewsletterSubscription | Double opt-in for newsletter | User subscribes to weekly newsletter |
ConfirmationStillNeeded | Reminder for unconfirmed subscription | Scheduled job for pending confirmations |
PromoteNewsletterForFreeEbookDownloader | Upsell newsletter to ebook downloader | After ebook download |
SubscriberConfirmedEmail | Welcome email after confirmation | Successful confirmation (PowerfulWeeklyEmail list only) |
SubscriberUnsubscribed | Goodbye email after unsubscribe | Successful unsubscribe (if was confirmed) |
Error Codes
| Code | Enum Value | Meaning |
|---|---|---|
invalid-book-link | InvalidBookLink | Book download link is invalid |
already-subscribed-confirmation-required | ConfirmationRequired | Already subscribed but needs confirmation |
cannot-confirm | CannotConfirm | Cannot confirm subscription (unsubscribed, invalid link, or not found) |
URL Patterns
Legacy URLs (with secrets in query params)
- Confirm:
/newsletter/confirm?email={email}&list_id={list}&check={secret} - Unsubscribe:
/newsletter/unsubscribe?email={email}&list_id={list}&check={unsubscribe_secret}
Signed URLs (recommended)
- Confirm:
/subscriptions/{token}/confirm/{list}?signature={sig}&expires={ts} - Unsubscribe:
/subscriptions/{token}/unsubscribe/{list}?signature={sig}&expires={ts}
Signed URLs are more secure as they:
- Don't expose secrets in query parameters
- Have built-in expiration
- Are tamper-proof (signature validation)