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
namestringRequiredsubjectstringRequired{{variable}} personalization.from_namestringRequiredFrom header, e.g. Acme.from_emailstringRequired/docs/domains/overview.templatestringRequiredtmpl_... id to render as the email body.targetstringRequired"all" or "segment".segmentstringOptionalsegment id to target. Required when target is "segment".preview_textstringOptionalvariantsarrayOptionalTargeting#
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#
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.
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.
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.
import { Deckle } from "@deckle/sdk";
const deckle = new Deckle(process.env.DECKLE_API_KEY!);
await deckle.campaigns.send("camp_8f2a1c");Deckle resolves the audience
Emails are rendered and delivered
{{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
Sending requires a LIVE key
Campaign sends only work with ask_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.
| Metric | What it counts |
|---|---|
sends | Recipients the campaign was dispatched to after filtering. |
delivered | Messages SES confirmed as delivered to the inbox provider. |
opens | Recipients who opened the email (tracked via the open pixel). |
clicks | Recipients who clicked a tracked link in the email. |
bounces | Messages that hard- or soft-bounced. Hard bounces are auto-suppressed. |
complaints | Recipients who marked the email as spam. These are auto-suppressed too. |
unsubscribes | Recipients 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.