Send rich notifications to Discord
Push Northwind deploy alerts and KPI updates to a Discord channel — embeds, not plain text.
Published Oct 15, 2025
Northwind runs its day-to-day operations in Discord — one channel for the engineering team, another for the wider company. When a deploy goes out or a KPI crosses a threshold, the team wants to hear about it there, not buried in an inbox nobody checks until lunchtime.
A plain-text webhook message works, but it scrolls past unnoticed. A Discord embed — a titled card with a coloured spine down the left edge — stands out in a busy channel and tells you the outcome at a glance: green for a clean deploy, red for a failed one. This script wraps that pattern in a small helper so any of your other scripts can post a proper notification in one line.
What you’ll need
- A Discord channel you can post to, and permission to manage its integrations.
- A webhook URL for that channel. In Discord, open Channel settings → Integrations → Webhooks → New Webhook, then copy the URL.
- That URL saved as
DISCORD_WEBHOOKin Script Properties — see Store API keys and secrets securely. A webhook URL is a secret: anyone who has it can post to your channel.
The script
// Brand colours for embed spines, as integers (Discord wants a decimal int,
// not a "#rrggbb" string — hex literals like 0x10b981 are the same thing).
const COLOUR_INFO = 0x2563eb; // blue — neutral updates
const COLOUR_SUCCESS = 0x10b981; // green — something worked
const COLOUR_FAILURE = 0xef4444; // red — something broke
/**
* Posts a single embed to the Northwind Discord channel.
*
* @param {string} title The bold heading on the embed card.
* @param {string} description The body text under the title.
* @param {number} colour The spine colour, as a decimal integer.
*/
function discordSend(title, description, colour = COLOUR_INFO) {
// The webhook URL is a secret — read it from Script Properties, never
// hard-code it into the script.
const hook = PropertiesService.getScriptProperties()
.getProperty('DISCORD_WEBHOOK');
if (!hook) {
Logger.log('No DISCORD_WEBHOOK set — skipping notification.');
return;
}
// An embed is just a JSON object inside an "embeds" array. Discord
// renders the title in bold and draws the colour down the left edge.
const response = UrlFetchApp.fetch(hook, {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify({
embeds: [{ title, description, color: colour }],
}),
muteHttpExceptions: true,
});
// A successful webhook post returns 204 No Content. Anything else
// (a 404 for a deleted webhook, a 429 for rate limiting) is worth logging.
const code = response.getResponseCode();
if (code !== 204) {
Logger.log('Discord webhook returned ' + code + ': ' + response.getContentText());
}
}
/**
* Posts a deploy result to Discord — green for success, red for failure.
*
* @param {string} version The release version, e.g. "v2.4.0".
* @param {boolean} success Whether the deploy succeeded.
*/
function deployAlert(version, success) {
discordSend(
success ? 'Deploy succeeded' : 'Deploy failed',
'Northwind ' + version,
success ? COLOUR_SUCCESS : COLOUR_FAILURE
);
}
How it works
- Three named constants hold the embed colours as decimal integers. Discord’s
webhook API expects a number for
color, not a CSS-style#rrggbbstring — the0x10b981hex literals are just a readable way to write those numbers. discordSendreads the webhook URL from Script Properties. If it is missing, the script logs a note and stops rather than throwing — a missing secret should never crash the caller.- It builds the payload: a single object inside an
embedsarray, carrying the title, description, and colour. Discord renders that as a card. - It posts the payload with
UrlFetchApp.fetch. A successful webhook call returns HTTP204 No Content; any other code is logged so a deleted webhook or a rate-limit error does not pass silently. deployAlertis a thin wrapper that picks the title and colour from a boolean, so the rest of your code can announce a release in one line.
Example run
Calling the helpers from another script:
deployAlert('v2.4.0', true);
discordSend('Weekly MRR', 'Northwind MRR is £48,200 — up 3.1% on last week.');
The channel shows two embeds. The first is a green-spined card titled Deploy succeeded with the body Northwind v2.4.0. The second is a blue-spined card titled Weekly MRR showing the figure. Both are scannable at a glance — colour alone tells the team whether to relax or react.
Run it
discordSend is a building block, not a standalone job — call it from your
existing scripts at the point where something noteworthy happens:
- After a deploy step, call
deployAlert(version, success). - After a metrics calculation, call
discordSend('Weekly MRR', summary).
To test it in isolation, add a throwaway function and run it from the editor:
function testDiscord() {
discordSend('Test', 'If you can read this in Discord, the webhook works.');
}
Watch out for
- The webhook URL is a credential. Anyone who has it can post to your channel as the webhook. Keep it in Script Properties, and rotate it in Discord if it ever leaks.
- A successful post returns
204, with an empty body — do not try to parse the response as JSON. The script checks the status code instead. - Discord rate-limits webhooks (roughly 30 messages per minute per channel). A
burst of alerts can return
429; if you expect bursts, batch updates into one embed rather than firing one message per event. - Embed text has limits — a title caps at 256 characters and a description at 4,096. Long KPI dumps will be truncated, so summarise before you send.
- A webhook can only post to the one channel it was created for. To notify several channels, create one webhook per channel and store each under its own property key.
Related
Build a two-factor SMS verification step
Add phone verification to a Northwind workflow — code via Twilio, validated by web app.
Updated Dec 18, 2025
Bridge Sheets to Zapier or Make
Trigger external automations from Northwind Sheets via webhooks — no Apps Script logic needed downstream.
Updated Nov 8, 2025
Build a payment-webhook receiver
Catch Stripe payment events into a Northwind sheet — paid invoices flip status instantly.
Updated Oct 11, 2025
Build a WhatsApp notification sender
Push Northwind updates via the WhatsApp Business API — for client billing milestones.
Updated Jul 23, 2025
Send SMS notifications with Twilio
Text Northwind alerts straight from your scripts — for production outages or VIP events.
Updated Jul 19, 2025