docs
/
AI skills

Broadcast report

How a sent broadcast did — sent, delivered, opened, clicked, bounced, unsubscribed — for its latest run or an earlier one, who did what, why sends failed, and who is off the list for good. Read only; nothing is sent.

Every send of a broadcast is a run. A broadcast on a repeating schedule sends again and again from one record. Its headline numbers are the latest run's, and earlier runs keep their own (the last 50). Each person in a run has one delivery row (broadcast_delivery), and every number below is counted from those rows.

This skill only reads. It sends nothing.

Ask first

  • Which broadcast? By name. If several match, list them with their status and when they ran, and ask.
  • Which run? Only for a repeating broadcast. The default is the latest.
  • What they want to know. The numbers, the people behind one of them, or why it failed.

Steps

1. Broadcast: find it and its state

Find the email_broadcast by data.name (or data.broadcastName). Note its sk, channel, status and currentRunId.

statusMeans
draftnever sent; there is nothing to report
scheduledwaiting for its time
pendingabout to send; a sweep every five minutes starts it, or it is held by quiet hours (deferredReason = quiet_hours)
sending / pauseda run is going / held where it is
completedthe run is over and at least one message went
failednothing went. The reason is errors[0].errorMessage, e.g. No recipients found, No sender accounts configured, email gateway not configured, The Bulk Email service agreement has not been accepted.
cancelledstopped; people not reached yet were not sent to

A run with nobody new to send to ends completed with a note, e.g. Everyone on the list was already sent this.

Hands on: the broadcast's sk and status. Check: open it (/broadcast?openId=<sk>). A sent broadcast opens on its Summary tab.

2. Broadcast: the numbers

call_appengine GET /broadcast/<sk>/stats (add ?runId=<id> for an earlier run; the runs list in the answer has every run's id, dates and numbers).

metricsCounts the people whose row…
totalwas queued for the run
sentwent out (sent, delivered, opened or clicked)
failedcould not be sent, with a reason on the row
deliveredthe gateway confirmed delivered (see the warning)
openedhas at least one open
clickedhas at least one click
bouncedbounced
spamComplaintswas reported as spam
unsubscribedclicked this email's unsubscribe link

rates (deliveryRate, openRate, clickRate, bounceRate) are percentages of total, not of sent. When reporting, also say how many were sent, so a list with failures doesn't look worse than it is. The broadcast record's own metrics.suppressed says how many were left out at send time as unsubscribed, bounced or complained.

Where the numbers come from:

  • Email opens, clicks, bounces, complaints and deliveries come from the email gateway's events. Only Amazon SES events update the rows. On any other gateway these stay at 0, and that is not "nobody opened".
  • Texts and WhatsApp: delivered and failed come from the carrier's status updates. A WhatsApp read counts as opened. Texts have no opens or clicks.
  • Unsubscribed is the platform's own link, so it counts on every gateway.

delivered undercounts. A row moves from delivered to opened when the person opens it, and delivered counts only rows still at delivered. For "how many got it", give delivered + opened, and say that is the floor.

Hands on: the numbers, with sent and total. Check: the Summary → Overview tiles in the composer show the same figures. A broadcast with more than one run shows its runs there, newest first.

3. Broadcast: the people behind a number

GET /broadcast/<sk>/report?status=<filter>&page=1&pageSize=100 (and &runId=<id>). status is one of opened, clicked, unsubscribed, delivered, bounced, failed, or leave it out for everyone. Page through total.

Each row gives recipient (the address or number), status, error, from, subject, sentAt, deliveredAt, failedAt, unsubscribedAt, openCount and clickCount.

  • Which links were clicked: read the broadcast_delivery rows themselves (find_records with data.broadcastId = the sk, data.runId = the run, data.clickCount > 0). Each holds clickedUrls.
  • Why sends failed: group the failed rows by error and give the top reasons with their counts, not every row.

Hands on: the people, or the reasons. Check: Summary → Delivery log in the composer, filtered the same way.

4. Broadcast: who is off the list for good

GET /broadcast/suppression (with status, search, page, pageSize) lists the addresses the business may no longer bulk-email: counts of unsubscribed, complained and bounced, and for each address the reason and, when it came from a broadcast, its broadcastId.

Check: Broadcast → Unsubscribes (/broadcast?tab=suppression).

Stop

Nothing in this skill sends. Two things near it are the person's to decide:

  • Putting an address back (POST /broadcast/suppression/remove) only at that person's own request. Re-mailing someone who opted out is how a sending domain gets blocked.
  • Sending again to anyone. A follow-up to the people who didn't open is its own draft: Follow-up to people who didn't open.

When it's done

Tell the person, for the run asked about:

  • when it went, how many were queued and how many were sent;
  • delivered (as delivered + opened), opened, clicked, unsubscribed, bounced, with the rates;
  • what failed and why, in a line or two;
  • which numbers can't be trusted on their gateway (opens and clicks off SES; none for texts).

What it can't do yet

  • Opens and clicks only on Amazon SES. Other gateways report none.
  • delivered undercounts, as above.
  • The Analytics tab is a placeholder. It says "Analytics dashboard coming soon". Use each broadcast's Summary.
  • The Summary's Activity tab is not this broadcast's. It lists the business's recent email events across every send.
  • A bounce or spam report only blocks an address that already has a subscriber record. A contact who bounced but never had one stays on the list and is emailed again next time.
  • No comparison across broadcasts. Read each one's stats.

Don'ts

  • Don't report a 0% open rate as "nobody opened" before checking the gateway reports opens.
  • Don't divide by sent and call it the platform's rate. The platform's rates are of total.
  • Don't remove anyone from the suppression list, or start a send, from a reporting request.