Campaigns

Performance tracking

Every campaign recipient is sent as an individual tracked email, so opens, clicks, bounces, and complaints surface per-contact in the dashboard and via webhooks.

A campaign is not a single send — it fans out into one tracked email per recipient. Each of those emails is logged exactly like a transactional `POST /emails` send, with its own id, status, and event timeline.

That means campaign performance reuses the same delivery, open, and click tracking as the rest of the platform — there is no separate analytics surface to learn.

What is tracked

  • Deliveryemail.sent, email.delivered, and email.delivery_delayed per recipient.
  • Engagementemail.opened and email.clicked, when open/click tracking is enabled on the sending domain.
  • Negative signalsemail.bounced and email.complained, which also add the address to your account suppression list.
  • Unsubscribes — recipients who opt out via the per-campaign unsubscribe link, flipping that contact to unsubscribed in the audience.
Open and click tracking is a per-domain setting. If a campaign shows deliveries but no opens, confirm tracking is enabled on the from-domain under Domains.

Headline metrics

Open a sent campaign in the dashboard to see its performance right away. The headline insights are:

  • Emails delivered — how many copies the receiving servers accepted.
  • Open rate — the share of delivered emails that were opened.
  • Click rate — the share of delivered emails with at least one tracked-link click.
  • Replied, Bounced and Complained — the raw counts behind those signals.
Open rates can be inaccurate. Some inbox providers pre-fetch or proxy the tracking pixel (e.g. Apple Mail Privacy Protection), inflating opens, while others block it entirely, suppressing them. Treat open rate as a directional signal, not an exact count.

Reading results

Each recipient email carries an event log you can read the same way as any other email:

  • In the dashboard, open the campaign to see per-recipient status and aggregate delivery, open, and click counts.
  • Via the API, retrieve an individual recipient email with `GET /emails/:id` to inspect its last_event and status.
  • Via webhooks, subscribe to the email.* events to stream delivery and engagement to your own systems in real time. See Event types.

Aggregate stats endpoint

For a single rolled-up view, call GET /campaigns/:id/stats. It returns the campaign’s aggregate open and click counts (with the underlying delivered/sent totals, plus replies, bounces and complaints) and the top clicked links — the same numbers shown on the dashboard, fetched in one request.

import { Mailblastr } from 'mailblastr';

const mb = new Mailblastr('mb_xxxxxxxxx');

const { data, error } = await mb.campaigns.stats('CAMPAIGN_ID');
console.log({ data, error });

It returns a campaign_stats object. The counts are total (one per recipient copy sent), delivered, opened, clicked, replied, bounced and complainedopened, clicked and replied are unique per recipient, not raw event counts. The rates object carries delivery, open, click, reply, bounce and complaint as percentages: open, click and reply are measured against delivered (falling back to total when no delivery events were recorded), while delivery, bounce and complaint are measured against total. Every rate is a percentage rounded to one decimal place (so 98.1, not 98.06). links lists the top clicked tracked links as { url, clicks }, ordered by clicks descending, and is capped at the 50 most-clicked links.

{
  "object": "campaign_stats",
  "campaign_id": "8f5c2a1e-7b3d-4f9a-9c12-2e6d4a7b8c90",
  "total": 1240,
  "delivered": 1216,
  "opened": 498,
  "clicked": 96,
  "replied": 12,
  "bounced": 18,
  "complained": 1,
  "rates": {
    "delivery": 98.1,
    "open": 41,
    "click": 7.9,
    "reply": 1,
    "bounce": 1.5,
    "complaint": 0.1
  },
  "links": [
    { "url": "https://yourdomain.com/whats-new", "clicks": 74 },
    { "url": "https://yourdomain.com/pricing", "clicks": 22 }
  ]
}

The same fields (without object, campaign_id and links) are returned inline as the statistics field of `GET /campaigns/:id`. Errors: not_found if the campaign does not exist or is not yours.

Because bounces and complaints feed account-wide suppression, contacts that hard-bounce or complain are automatically excluded from subsequent campaigns — keeping your sender reputation healthy without manual list hygiene.