DeckleDocs
Dashboard

Marketing

Campaigns

Broadcast a one-off or scheduled email to your whole list or a segment, with optional A/B subject lines and a full post-send report.

A campaign is a broadcast: a single email you compose once and send to many contacts at once. Unlike a transactional send, a campaign has a target audience, respects the suppression list and one-click unsubscribe, and reports back on how it performed.

What is a campaign#

Campaigns are for the email you send to people, not machines — a newsletter, a product announcement, a promotion. You pick an audience (everyone, or a segment), choose a template and subject, and send it as a one-off or on a schedule.

Every campaign starts life as a draft. Drafts are the only editable state — once a campaign is sent it becomes an immutable record you can report on. Because campaigns are broadcasts to real inboxes, they always go out from a verified domain, include a visible unsubscribe link, and skip any address on your suppression list.

Transactional vs. broadcast

Sending a single receipt or magic link? Use emails.send instead. Campaigns are for reaching a list.

Create a draft#

Create a campaign with campaigns.create. It returns a draft — nothing is sent until you call campaigns.send. Give it a name (for the dashboard), the subject and from identity your recipients will see, the template to render, and a target audience.

import { Deckle } from "@deckle/sdk";

const deckle = new Deckle(process.env.DECKLE_API_KEY!);

const campaign = await deckle.campaigns.create({
  name: "July product update",
  subject: "What's new in Acme this month",
  from_name: "Acme",
  from_email: "hello@acme.com",
  template: "tmpl_newsletter",
  target: "all",
});

console.log(campaign.id); // camp_...

Campaign parameters

namestringRequired
Internal label for the campaign, shown in the dashboard. Not visible to recipients.
subjectstringRequired
The subject line recipients see. Supports {{variable}} personalization.
from_namestringRequired
Display name in the From header, e.g. Acme.
from_emailstringRequired
Sending address. Its domain must be verified — see /docs/domains/overview.
templatestringRequired
The tmpl_... id to render as the email body.
targetstringRequired
Who receives the campaign: "all" or "segment".
segmentstringOptional
The segment id to target. Required when target is "segment".
preview_textstringOptional
The preheader shown after the subject in most inbox previews.
variantsarrayOptional
Alternate subject lines for an A/B test — see below.

Targeting#

A campaign’s target decides who receives it. Send to your entire audience, or narrow to a live segment — a rule-based group that recalculates as contacts change. Either way, unsubscribed and suppressed contacts are excluded automatically.

Send to everyone#

ts
await deckle.campaigns.create({
  name: "Launch announcement",
  subject: "We shipped something big",
  from_name: "Acme",
  from_email: "hello@acme.com",
  template: "tmpl_announcement",
  target: "all",
});

Send to a segment#

Set target to "segment" and pass the segment’s id. Segments have no public write API — build them in the dashboard under Audience → Segments, then reference the id here.

ts
await deckle.campaigns.create({
  name: "Win-back for lapsed users",
  subject: "We miss you",
  from_name: "Acme",
  from_email: "hello@acme.com",
  template: "tmpl_winback",
  target: "segment",
  segment: "seg_lapsed_30d",
});

Membership is live

A segment recalculates as contacts and events change, so the recipient set is resolved at send time — not when you create the draft.

A/B subject lines#

Test which subject line lands better by passing a variants array. The subject you set on the campaign is variant A (the base); each entry in variants is an alternate. You can add up to three alternates — B, C, and D — for four subject lines in total.

ts
await deckle.campaigns.create({
  name: "July product update",
  subject: "What's new in Acme this month", // variant A (base)
  from_name: "Acme",
  from_email: "hello@acme.com",
  template: "tmpl_newsletter",
  target: "all",
  variants: [
    "Your July Acme roundup",   // variant B
    "3 new things in Acme",     // variant C
  ],
});

Only the subject line changes between variants — the from identity, template, and target stay the same. Open and click rates are reported per variant so you can see which subject won.

Send it#

Sending is a separate, deliberate step. Call campaigns.send with the campaign’s id to broadcast the current draft to its target audience.

send-campaign.ts
import { Deckle } from "@deckle/sdk";

const deckle = new Deckle(process.env.DECKLE_API_KEY!);

await deckle.campaigns.send("camp_8f2a1c");

Deckle resolves the audience

The target — all contacts or the segment — is expanded at send time, then filtered against unsubscribes and the suppression list.

Emails are rendered and delivered

Your template is rendered per recipient (with any {{variable}} personalization), an unsubscribe link and one-click headers are added, and each message is delivered through your verified domain.

Results stream into the report

As SES reports delivery, opens, clicks, bounces, and complaints, the campaign report fills in.

Sending requires a LIVE key

Campaign sends only work with a sk_live_ key. With Redis configured, delivery runs asynchronously on the worker so large lists don’t block your request. Without a worker, sends run synchronously and are capped at 200 recipients.

Reports#

Once a campaign is sent, its report tracks how recipients engaged. Fetch it with campaigns.get, or open the campaign in the dashboard. Metrics update as SES and SNS deliver notifications back to Deckle.

MetricWhat it counts
sendsRecipients the campaign was dispatched to after filtering.
deliveredMessages SES confirmed as delivered to the inbox provider.
opensRecipients who opened the email (tracked via the open pixel).
clicksRecipients who clicked a tracked link in the email.
bouncesMessages that hard- or soft-bounced. Hard bounces are auto-suppressed.
complaintsRecipients who marked the email as spam. These are auto-suppressed too.
unsubscribesRecipients who opted out via the unsubscribe link or one-click header.

Keep complaints low

Bounces and complaints suppress the address automatically. Watch your complaint rate — the deliverability guide covers the thresholds bulk senders need to stay under.

Next steps#