Make re-engagement email tiers configurable from admin; v1.1.20
Day thresholds and per-tier subject/body/CTA are now editable in the Email Templates panel. Tier keys are position-based (t1/t2/t3) so changing day values never re-sends emails already fired. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+19
-26
@@ -585,36 +585,29 @@ export async function sendStudyReminderEmail(email, displayName, studyTitle, sec
|
||||
}
|
||||
}
|
||||
|
||||
const REENGAGEMENT_COPY = {
|
||||
'7d': {
|
||||
subject: 'Your study is waiting for you',
|
||||
eyebrow: 'Come Back',
|
||||
headline: 'Pick up where you left off',
|
||||
body: "It's been a week — your progress is saved and your next lesson is ready whenever you are.",
|
||||
cta: 'Continue Studying',
|
||||
},
|
||||
'14d': {
|
||||
subject: "Don't lose your momentum",
|
||||
eyebrow: 'Still With You',
|
||||
headline: 'Your spot is still saved',
|
||||
body: 'Two weeks have passed, but every note and completed lesson is still right there. A little each day adds up.',
|
||||
cta: 'Return to Your Study',
|
||||
},
|
||||
'30d': {
|
||||
subject: 'Your progress is still here',
|
||||
eyebrow: 'We Saved Your Spot',
|
||||
headline: "It's been a month — come back anytime",
|
||||
body: 'Your study progress is still intact and waiting. There\'s no deadline — come back whenever you\'re ready.',
|
||||
cta: 'Open Your Study',
|
||||
},
|
||||
const REENGAGEMENT_DEFAULTS = {
|
||||
t1: { subject: 'Your study is waiting for you', body: "It's been a while — your progress is saved and your next lesson is ready whenever you are.", cta: 'Continue Studying' },
|
||||
t2: { subject: "Don't lose your momentum", body: 'Every note and completed lesson is still right there. A little each day adds up — come back and continue.', cta: 'Return to Your Study' },
|
||||
t3: { subject: 'Your progress is still here', body: "Your study progress is still intact and waiting. There's no deadline — come back whenever you're ready.", cta: 'Open Your Study' },
|
||||
}
|
||||
|
||||
function getReengagementCopy(tier) {
|
||||
const cfg = state.cachedSiteContent ?? {}
|
||||
const t = tier === 't1' ? '1' : tier === 't2' ? '2' : tier === 't3' ? '3' : null
|
||||
const def = REENGAGEMENT_DEFAULTS[tier] ?? REENGAGEMENT_DEFAULTS.t1
|
||||
if (!t) return def
|
||||
return {
|
||||
subject: cfg[`studyReengagementT${t}Subject`]?.trim() || def.subject,
|
||||
body: cfg[`studyReengagementT${t}Body`]?.trim() || def.body,
|
||||
cta: cfg[`studyReengagementT${t}Cta`]?.trim() || def.cta,
|
||||
}
|
||||
}
|
||||
|
||||
export async function sendStudyReengagementEmail(email, displayName, studyTitle, studyUrl, tier, unsubUrl) {
|
||||
if (!process.env.RESEND_API_KEY) return
|
||||
const copy = REENGAGEMENT_COPY[tier]
|
||||
if (!copy) return
|
||||
try {
|
||||
const resend = new Resend(process.env.RESEND_API_KEY)
|
||||
const copy = getReengagementCopy(tier)
|
||||
const namePart = typeof displayName === 'string' && displayName.trim() ? displayName.trim() : 'friend'
|
||||
const subject = `${copy.subject}${studyTitle ? ` — ${studyTitle}` : ''}`
|
||||
const bodyHtml = (
|
||||
@@ -629,8 +622,8 @@ export async function sendStudyReengagementEmail(email, displayName, studyTitle,
|
||||
subject,
|
||||
text: `Hi ${namePart},\n\n${copy.body}${studyTitle ? ` Your current study: ${studyTitle}.` : ''}\n\n${studyUrl}\n\nGrace and peace,\nVerse by Verse with Nate${unsubUrl ? `\n\nUnsubscribe: ${unsubUrl}` : ''}`,
|
||||
html: buildBrandedEmailHtml({
|
||||
title: copy.headline,
|
||||
eyebrow: copy.eyebrow,
|
||||
title: copy.subject,
|
||||
eyebrow: 'Study Reminder',
|
||||
bodyHtml,
|
||||
ctaLabel: copy.cta,
|
||||
ctaUrl: studyUrl,
|
||||
|
||||
Reference in New Issue
Block a user