Resend Integration: Hybrid Approach
Why Not Just Use Resend’s Built-in Unsubscribe?
Short Answer: We need granular control that Resend doesn’t provide.Resend’s Limitations:
- All-or-nothing suppression - If user unsubscribes, they’re blocked from ALL emails (or all emails in a list)
- No category distinction - Can’t differentiate between marketing, operational, and transactional emails
- External dependency - Would need to call Resend API before every email send
- Generic experience - Their unsubscribe page is basic and can’t explain “you’ll still get daily snapshots”
Our Requirements:
✅ User unsubscribes from marketing → Still gets daily snapshots and alerts✅ Database-first permission checks (fast, no external API calls)
✅ Custom unsubscribe page with clear messaging
✅ Granular preference management (2 marketing types, 4+ operational types)
✅ Settings UI for users to manage individual email types
✅ Both marketing types can be toggled independently in settings
Our Hybrid Solution: Best of Both Worlds
We built a custom database-backed system but enhanced it with Resend features:What We Built Custom:
-
Database schema (2 tables)
email_preferences- Marketing preferences (feature_announcements, marketing_general)all_users- Operational preferences (email_daily_summary, email_spending_spikes, etc.)- Fast permission checks without API calls
-
Permission system (
EmailSubscriptionManager)- Checks if user allows specific email types
- Handles unsubscribe logic (marketing vs operational)
- Generates secure unsubscribe tokens (90-day expiry)
-
Custom unsubscribe page (
/app/unsubscribe/page.tsx)- Shows clear messaging about what continues
- Links to settings for granular control
- No chat widget to prevent distractions
-
Settings UI (
/app/settings/page.tsx → Email Notifications)- Individual toggles for each email type
- Marketing emails with blue “Marketing” badges
- Real-time updates with toast notifications
- Separate sections for operational vs marketing emails
-
API Endpoints
/api/unsubscribe- Token-based unsubscribe processing/api/marketing-preferences- CRUD for marketing preferences- Works without authentication (token proves identity)
What We Use from Resend:
-
List-Unsubscribe Headers ⭐
Result: Gmail/Outlook show native “Unsubscribe” button next to email
-
Email Tags 📊
Result: Track performance in Resend dashboard
How It Works
Sending a Marketing Email (Complete Example):
When User Clicks Unsubscribe:
Option A: Email Client Button (Gmail/Outlook)Benefits of This Approach
✅ Advantages:
-
Email Client Integration
- Gmail/Outlook users see native “Unsubscribe” button
- One-click unsubscribe (no page visit required for some clients)
- Improves email deliverability (ISPs like seeing proper unsubscribe headers)
-
Granular Control
- Marketing unsubscribe doesn’t affect operational emails
- Database-first permission checks (fast, no external dependency)
- Custom business logic (e.g., “unsubscribe from ALL marketing at once”)
-
User Experience
- Custom unsubscribe page with clear messaging
- Users understand they’ll still get important emails
- Settings UI with individual toggles for each email type:
- Feature Announcements (Marketing)
- Marketing & Promotions (Marketing)
- Portfolio Summary (Operational)
- Spending Alerts (Operational)
- Stock Price Alerts (Operational)
- Financial Statements (Operational)
- Real-time updates with toast notifications
- Blue badges distinguish marketing from operational emails
-
Analytics
- Track email performance by category and campaign in Resend
- Monitor unsubscribe rates per email type
- A/B test different email approaches
-
Independence
- Not locked into Resend’s suppression system
- Can switch email providers without losing preference data
- Full control over permission logic
⚠️ Trade-offs:
- Maintenance - We maintain our own permission system
- Complexity - More code than using Resend alone (but necessary for our requirements)
- No auto-sync - We don’t sync suppression back to Resend audiences (could add if needed)
Helper Methods & Hooks
For Sending Marketing Emails:
For Settings UI (Frontend):
Optional: Sync to Resend Audiences
If you want extra safety, you can also suppress in Resend:Key Files
Backend
/lib/email-subscription-manager.ts- Core permission system and token generation/app/api/unsubscribe/route.ts- Token processing endpoint/app/api/marketing-preferences/route.ts- Marketing preferences CRUD/sql-queries/email-preferences-schema.sql- Database schema
Frontend
/app/settings/page.tsx- Settings UI with email toggles/app/unsubscribe/page.tsx- Unsubscribe confirmation page/hooks/queries/use-marketing-preferences.ts- Marketing preferences hook/hooks/queries/use-email-preferences.ts- Operational email preferences hook
Email Templates
/emails/feature-announcement-email.tsx- Feature announcements/emails/daily-email.tsx- Daily portfolio summaries
Summary
We chose the hybrid approach because it gives us:
- ✅ Granular control users want (turn off marketing, keep operational)
- ✅ Native email client integration for better deliverability
- ✅ Settings UI for managing all preferences in one place
- ✅ Full control over unsubscribe logic and messaging
- ✅ Analytics via Resend tags for email performance tracking