Before Send Hook
Use this hook to skip a broadcast for some people, or to change it for each person.
This is a strong hook, so it is a sensitive permission. The admin sees Change emails before they are sent. Add it only if a merge tag cannot do the job.
How it works
Broadcast calls your function once for each batch of up to 100 people, just before it sends to them. It works for broadcasts only, not for sequence emails.
Full example: VIP subject
This plugin skips people who have paused, and it gives VIPs their own subject and a closing line.
manifest.json:
{ "id": "local.vip-subject", "name": "VIP subject", "version": "1.0.0", "requires": { "broadcast": ">=3.0.0 <4.0.0", "pluginApi": "1" }, "permissions": { "subscribers": "read" }, "hooks": { "beforeSend": true } }
dist/main.js:
export default definePlugin({ async beforeSend({ subject, subscribers }) { const changes = {}; for (const person of subscribers) { if (person.custom_data?.paused === true) { changes[person.id] = { skip: true }; } else if (person.custom_data?.vip === true) { changes[person.id] = { subject: `For our VIPs: ${subject}`, append_html: "<p>Thank you for being a VIP.</p>", }; } } return changes; }, });
The subscribers permission is here because the plugin reads custom_data.
What you get and return
You get this:
{ "broadcast_id": 45, "subject": "October news", "subscribers": [ { "id": 12, "email": "ada@example.com", "first_name": "Ada", "last_name": null, "custom_data": { "vip": true } } ] }
You return an object with the subscriber ID as the key. Leave out the people you do not change.
| Field | Effect |
|---|---|
skip: true |
The person does not get this broadcast |
subject |
Replaces the subject, up to 998 characters |
prepend_html |
Adds HTML before the body |
append_html |
Adds HTML after the body |
headers |
Adds email headers, for example { "X-Campaign": "spring" }. Only names that start with X-, up to 10, one line each |
Broadcast ignores everything else. You cannot change who gets the email, who it is from, the unsubscribe link or any header that does not start with X-.
Broadcast cleans your HTML, and each addition can be up to 10,000 characters. The added HTML goes only in the HTML version of the email, not the plain text version.
If two plugins answer for one person, any skip wins, the last subject wins and HTML additions are joined.
Common mistakes
You expect it to fail closed. If your hook fails or takes more than 5 seconds, the email goes out unchanged. So never use this hook as the only guard for something that must not be sent.
You make one call per person. You have 5 seconds for 100 people. Use the data you are given.
You forget subscribers permission. Without it, each person has only id and email, so custom_data is undefined.
You test with a test send. Plugin hooks do not run in test sends. Send to a small segment.