PlunkPlunk
Recipes

Double opt-in

Require a confirmation click before a new signup starts receiving marketing email

Double opt-in adds a confirmation step between "user signs up" and "user starts getting marketing email." It's the standard way to avoid mailing typoed addresses, role accounts, and anyone who didn't actually consent.

The trick is {{subscribeUrl}}: a per-contact link Plunk auto-injects into every send. Clicking it flips subscribed to true and fires a contact.subscribed event.

Setup

Create two templates

  • A Transactional template for the confirmation email, containing {{subscribeUrl}}:

    <p>Hi {{firstName}}, please confirm your email to start receiving updates:</p>
    <p><a href="{{subscribeUrl}}">Confirm my email</a></p>
  • A Marketing template for the welcome email that goes out after they confirm.

The confirmation must be transactional

A marketing template targeted at an unsubscribed contact is silently skipped. Use a transactional template for the confirmation specifically — it bypasses the subscription check.

Trigger the signup from your backend

Two calls with your secret key (sk_*): create the contact unsubscribed, then track the event that fires the confirmation workflow.

curl https://next-api.useplunk.com/contacts \
  -H "Authorization: Bearer sk_your_secret_key" \
  -d '{ "email": "ada@example.com", "subscribed": false, "data": { "firstName": "Ada" } }'

curl https://next-api.useplunk.com/v1/track \
  -H "Authorization: Bearer sk_your_secret_key" \
  -d '{ "event": "signup.pending", "email": "ada@example.com", "subscribed": false }'

Both calls pass subscribed: false. If you skip the first call and rely on /v1/track alone, tracking on an unknown email creates the contact — but defaults it to subscribed, which defeats the point.

Workflow A: send the confirmation

Workflows → New workflow:

  • Trigger: EVENT on signup.pending
  • SEND_EMAIL step → transactional confirmation template

Enable it.

Workflow B: welcome them after confirmation

Workflows → New workflow:

  • Trigger: EVENT on contact.subscribed
  • SEND_EMAIL step → marketing welcome template

Enable it. contact.subscribed fires whenever a contact opts in — including via {{subscribeUrl}}, the preferences page, or the API — so this workflow handles both first-time confirmations and resubscribes.

Reminder if they don't confirm

Extend Workflow A with a WAIT_FOR_EVENT step after the send:

  • Event: contact.subscribed
  • Timeout: 86400 (24 hours)

On timeout, send a single reminder (also transactional). Keep the number of reminders small — repeated confirmation prompts look like spam to mailbox providers as much as to recipients.

What's next