FastLinkIt

Drip campaigns

Contacts & Mailingmailing4 min read

Available on Starter, Basic, Professional, and Unlimited plans

Multi-step email sequences that fire automatically when a trigger event happens — welcome series when someone signs up, birthday email on the day, post-purchase follow-up after a paid transaction.

Where to manage them

/mailing/sequences — sortable list with name, trigger badge, step count, active enrollment count, status, actions.

Click a row to edit. Click View enrollments to see who's currently in the sequence, what step they're on, and when their next step is due.

Trigger types

Trigger Fires when… Trigger value
Tag added A tag is applied to a contact The tag name (case-insensitive)
Group added A contact is added to a group The group ID
Anniversary Daily sweep at UTC midnight created (sign-up date) or birthday (Contact.Birthday)
After purchase A payment / donation is confirmed Optional product ID; empty = any purchase
After first click Recipient clicks any link in a mailing Optional mailing ID; empty = any mailing

The notifier fires both the unfiltered "any" variant (TriggerValue null) and the value-scoped variant per trigger event, so a generic Welcome series (tag_added, value blank) and a specific VIP welcome (tag_added, value vip) can both fire when a contact is tagged vip.

Creating a sequence

/mailing/sequences/create → fill in:

  1. Pick a prefab (optional) — three one-click templates are at the top:
    • Birthday email — anniversary trigger / Birthday column / one-step "Happy birthday {{FirstName}}"
    • Welcome series — tag_added trigger / 3 steps at 0h / 24h / +6 days
    • Post-purchase thank-you — after_purchase trigger / 2 steps at 0h / +3 days
  2. Name + description + active toggle
  3. Trigger type + trigger value (depending on type)
  4. Steps — flat list, each with:
    • Delay (hours) from the previous step (or from the trigger event for step 1)
    • Subject
    • HTML body
    • Active toggle — pause this step without breaking the chain
  5. Click Save. Existing enrollments continue from where they were; new enrollments use the latest step list.

How the dispatcher works

A background service polls every 5 minutes:

  • Finds active enrollments whose NextStepDueAt <= now
  • Picks the next active step (skips inactive ones automatically — LastStepOrderSent advances past them)
  • Queues a single-recipient Mailing so the regular sender pipeline handles tracking, branding, unsubscribe link, etc.
  • Bumps LastStepOrderSent + LastStepSentAt
  • Computes the new NextStepDueAt from the next active step's DelayHours
  • Marks the enrollment completed when no more active steps remain

For anniversary triggers, a daily UTC-midnight sweep enrolls every contact whose Birthday or CreatedAt matches today's month + day.

Idempotency

  • The trigger notifier checks for an existing Status=active enrollment for the same (MailingSequenceId, ContactId) pair before inserting. Duplicate trigger fires (re-tagging an already-tagged contact) are no-ops.
  • Re-tagging an already-tagged contact doesn't re-enroll — IContactService.AddTagAsync only fires the trigger on the first apply (the join-row check skips re-tags).

Pausing

Three levels:

  • Per-step — toggle a step inactive. The dispatcher advances LastStepOrderSent past it without sending.
  • Per-sequence — toggle the sequence inactive. New triggers don't enroll; existing enrollments stop advancing until the sequence is reactivated.
  • Per-enrollment — set the enrollment's status to cancelled (manual SQL — there's no UI yet).

Worked example — birthday email

Goal: send a friendly note on every contact's birthday.

  1. /mailing/sequences/create → click the Birthday email prefab.
  2. The form pre-fills with anniversary trigger, birthday value, and a one-step "Happy birthday {{FirstName}}" template.
  3. Tweak the subject + body to match your brand voice.
  4. Save. Done.
  5. Every UTC midnight, the daily anniversary sweep enrolls every contact whose Contact.Birthday matches today's month + day. They get the email at 00:00 UTC the same day.

Rejoining the server...

Rejoin failed... trying again in seconds.

Failed to rejoin.
Please retry or reload the page.

The session has been paused by the server.

Failed to resume the session.
Please retry or reload the page.