Skip to content

Birthday & Anniversary Automations in AcelleMail — Date-Triggered Sends

Send a happy-birthday discount on the day, a year-since-signup gift on the anniversary, a renewal reminder 30 days before expiry. AcelleMail's date-relative automation trigger handles all of these — this guide walks the setup with screenshots.

Why date-based automations earn their spot

Birthday and anniversary emails are reliably the highest-converting transactional sends most senders run — 5-10× the click-through rate of standard newsletters. They're personal, they're expected, they coincide with a high-affinity moment.

The setup is a one-time configuration; once it's running, every subscriber whose date matches fires the email automatically. No manual scheduling.

What you need on the list

Before building the automation, the list must have the date field you want to trigger on. Three common patterns:

Use case Field name When you collect it
Birthday birthday (Date type) Signup form, optional field
Year-since-signup anniversary (uses built-in created_at) Automatic
Renewal reminder subscription_expires_at API push from your billing system
Loyalty milestone first_purchase_at API push from ecommerce

For birthday, add a Date field via Audience → [list] → Fields → New field → name birthday, type Date, optional.

To collect the value on signup, edit the signup form (Audience → [list] → Signup forms → [form] → Edit) and add the birthday field with the date picker. Keep it optional — required birthday on signup tanks conversion.

For existing subscribers with no birthday, fill via import or via your account UI — you'll only fire emails for subscribers where the field is non-empty.

Build the birthday automation

Open the visual automation builder

In AcelleMail's left sidebar, click AutomationAutomations. The index lists every automation in this account with its current state:

Automations index

Click New automation in the top-right toolbar. The trigger picker opens:

Trigger picker — pick what starts the automation

For birthday emails:

  1. Trigger: Date relative in the trigger picker
  2. Date field: birthday
  3. Schedule: On the date (offset = 0 days) — fires at midnight in subscriber's timezone if known, or in the campaign's default timezone
  4. Repeat: Yearly — re-fires every year on the same month/day

The trigger picker shows the date-relative option:

Trigger picker — pick "Date relative"

After the trigger, drop in the email step:

  • Subject: Happy birthday, {{ subscriber.first_name | default('friend') }}!
  • Body: a short personal note + a discount code or gift

The configured flow:

Configured flow — date trigger + email step

Save. Going forward, every day at midnight AcelleMail evaluates every subscriber's birthday field; matches fire the email.

Build the anniversary automation

Same pattern, different field:

  1. Trigger: Date relative
  2. Date field: created_at (the built-in signup-date)
  3. Schedule: On the date + Yearly
  4. Email step: thank-you for being-a-subscriber-N-years note
Subject: It's been a year, {{ subscriber.first_name | default('friend') }} — thank you 🎉
Body: One year ago today you joined us. As a thank-you, here's a code for 20% off your next order: ANNIV20.

For "two years since signup", run a second automation with offset = -730 days from created_at + 1095 = checks "exactly 3 years ago". (Or use the created_at Date-relative trigger and a condition WHERE year_diff(created_at, now()) == 2.)

Build the renewal-reminder automation

For subscription / contract renewals, fire 30 days before expiry:

  1. Trigger: Date relative
  2. Date field: subscription_expires_at
  3. Schedule: Before the date, offset = 30 days
  4. Repeat: One-time per subscriber per renewal cycle
  5. Email step: "Your subscription renews in 30 days — confirm payment method"

Then a 7-day reminder:

  1. Trigger: Date relative
  2. Field: subscription_expires_at
  3. Schedule: Before, offset 7 days
  4. Email: "Your subscription renews next week"

And a 1-day final notice:

  1. Trigger: Date relative
  2. Field: subscription_expires_at
  3. Schedule: Before, offset 1 day
  4. Email: "Tomorrow: your subscription renews automatically"

Common UI signals + fixes

Symptom Likely cause UI fix
Birthday emails never fire birthday field empty for most subscribers Confirm field is collected on signup; back-fill via import for existing subscribers
Birthday email fires on the wrong day Timezone mismatch — birthday stored without TZ, sent in app timezone See Advanced: timezone handling
Subscriber gets birthday email twice in the same year Duplicate automation, both with same trigger Open automations index — confirm only one is enabled
Renewal reminder fires AFTER expiry subscription_expires_at was updated late by billing system Move trigger to billing-system-side webhook instead of pulling from AcelleMail's field
Some subscribers get the email at 3am their time Default timezone is server TZ, not subscriber TZ Add per-subscriber timezone field; see Advanced

When to skip the birthday automation

If your industry doesn't fit (B2B SaaS where birthday feels invasive, regulated industries where personalization triggers compliance review), skip it. The "year-since-signup" anniversary is a safer alternative that earns most of the engagement without the personal-data ick factor.

Advanced: timezone-aware date triggers, lookahead jobs, and lead-time logic

The date-relative trigger evaluates dates in a single timezone — by default the AcelleMail server's timezone (typically UTC). For senders with a global audience, you want each subscriber to receive their birthday email at a reasonable local hour.

Per-subscriber timezone field:

Add a timezone field (Type = Text) to the list. Populate it via signup form (geolocate via IP) or via API push from your app's user model.

Automation logic with timezone:

The AcelleMail date-relative trigger handles the matching itself; for per-subscriber timezone offsetting, the cleaner path is to schedule the trigger to evaluate at 09:00 in each subscriber's local time using AcelleMail's per-recipient send-time-optimization feature (if your install supports it).

If not, the workaround: run 24 automations, one per hour, each scoped to subscribers in that hour's timezone:

Automation 1: trigger 09:00 server time; condition timezone = 'America/Los_Angeles'
Automation 2: trigger 10:00 server time; condition timezone = 'America/Denver'
Automation 3: trigger 11:00 server time; condition timezone = 'America/Chicago'
Automation 4: trigger 12:00 server time; condition timezone = 'America/New_York'
Automation 5: trigger 13:00 server time; condition timezone = 'America/Halifax'
...

Tedious to set up; runs forever. Most senders simplify to 4 buckets (Americas / EMEA / APAC / IST) and accept the imprecision.

Lookahead via API for high-precision renewals:

For subscription renewals where the field source is your billing system (Stripe, Chargebee), the cleanest pattern is to fire the email from the billing system's webhook rather than from AcelleMail's date trigger:

Stripe webhook 'invoice.upcoming' fires 30 days before renewal
→ your backend receives the webhook
→ calls AcelleMail API: trigger a "renewal_reminder_30d" custom event
→ AcelleMail automation triggered by event = renewal_reminder_30d sends the email

Advantage: Stripe's invoice.upcoming is authoritative; AcelleMail's stale subscription_expires_at might not have been updated yet if your billing-to-AcelleMail sync runs nightly.

Bulk back-fill birthdays from an existing system:

If you're migrating from a system that already has birthdays stored, push them in via the API:

# CSV file: email,birthday (YYYY-MM-DD)
while IFS=, read email bday; do
  curl -X PATCH "https://acellemail.com/api/v1/subscribers" \
    -H "Authorization: Bearer $ACELLE_TOKEN" \
    -d "{
      \"email\": \"$email\",
      \"list_uid\": \"$ACELLE_LIST_UID\",
      \"fields\": {\"birthday\": \"$bday\"}
    }"
done < birthdays.csv

Lead-time math for renewal cycles:

If subscription_expires_at = 2026-12-31 and your trigger says "30 days before", that fires on 2026-12-01 at the timezone the trigger runs in. For annual renewals, set the automation to One-time per subscriber per year (or whatever your cycle is) — AcelleMail tracks the per-subscriber last-run timestamp so it won't double-fire within the cycle window.

If you change the subscription_expires_at mid-cycle (e.g. customer upgrades and the date resets), the automation re-evaluates and may fire the reminder again from the new date. Test this carefully if your billing flow updates the field frequently.

Multi-step birthday flow (day-of + 3-day follow-up if no purchase):

Date relative on birthday → email "Happy birthday, here's 20% off"
  Wait 3 days
  Condition: did NOT use discount code
    → email "Your birthday discount expires in 24h"

The Wait step + condition step are standard automation primitives. Many senders see the highest birthday ROI on the expiry reminder, not the day-of email.

Related articles

11 comments

7 comments

  1. Ahmed
    Always test the END of the sequence first, not the start. Most testing focuses on email 1 but the longest-tenure subscribers are at the end and that's where bugs surface.
  2. Marcus
    We do almost exactly this but with one tweak — we use the 'goal' node to exit subscribers from the sequence early when they complete a target action. Saves us sending to people who already did the thing.
  3. Minh
    Solid walkthrough. The conditional-branching example especially — most automation guides skip that and you end up rebuilding from scratch.
    1. Admin
      The branching bit is in there because we kept hitting it ourselves. A birthday flow without a condition sends the same coupon to someone who bought last week and someone who has been cold for a year, and the unsubscribe rate tells you about it fast. One thing the article doesn't stress enough: the condition is evaluated at the moment the subscriber enters that step, not when the automation was triggered. So if you have a long wait before the branch, the field you're checking may have changed since the birthday fired. Usually that's what you want, but it surprises people who expect a snapshot. I'll add a note about it.
  4. Quân
    The visual flow diagram is exactly what I needed. Our welcome series has been a mess of forgotten branches — going to redo it tonight using this as the template.
  5. Olufemi
    What's the max number of steps in a sequence before performance becomes a concern? Asking because we have a 14-step nurture and I'm wondering if it's overkill.
    1. Admin
      14 steps is fine. There's no hard cap in the automation engine, and step count isn't really the axis that hurts. What costs you is how many subscribers are sitting in the sequence at once, since each active step gets evaluated on the trigger tick. A 14-step nurture over a few thousand contacts is nothing. For date-triggered flows like birthdays specifically, the thing to watch is a wide Wait window colliding with the annual re-trigger, so someone can be mid-sequence when next year's birthday fires. Keep the total sequence duration well under 365 days and that never comes up. If you do see the tick getting slow, tell me the subscriber count and the shape of the sequence and I'll look at it. Perf complaints on automations have almost always been list size or a missing index, not step depth.
  6. James
    Built a 9-email welcome series last quarter using this pattern. Took 4 days end-to-end. Open rate on email 1 is 62%, drops to 28% by email 9 — which is actually higher engagement than our broadcast list. Highly recommend the format
    1. Admin
      28% on email 9 is good. A tail that high usually means the series is paced right rather than dumped over three days, so the list never gets a chance to tune it out. Worth saying that a welcome series and a birthday automation behave differently even though the builder is the same. Welcome fires off a known signup timestamp, so your 9 steps land in a predictable order. Date triggers depend on the subscriber having a real date field, and anyone with a blank or junk date silently never enters. That's the one number I'd watch if you port this pattern over. Four days end-to-end is roughly what I'd expect once the copy is written. If you're up for it, I'd take the step timing you landed on as a note in the article, we don't have a concrete pacing example in there right now.
  7. Linh
    how do you handle subscriers who join mid-sequence (e.g. via API)? Do they start at step 1 or pick up at a current point?
    1. Admin
      Everyone starts at step 1, API-created included. There's no catch-up logic, and no way to skip earlier steps.

More in Automation