Learning Goals 5 min
Yesterday a single Discord webhook fired one message. Today you wire two destinations — Discord for chat-style logs, IFTTT to bridge into your phone's native notifications, email, Google Sheets and ~700 other services. By the end of this lesson you will:
- POST to a Discord webhook with a rich embed — title, colour, fields — instead of just plain text.
- POST to IFTTT's Maker Webhooks endpoint with three optional string "values" that become variables in IFTTT recipes.
- Use IFTTT to push a phone notification, a Google Sheets row append, and an email — all from one Arduino trigger.
Warm-Up 10 min
Pull up yesterday's doorbell sketch. We'll fork it to send to two destinations instead of one.
Discord vs IFTTT — pick the right one
| Service | Best for | Trade-offs |
|---|---|---|
| Discord webhooks | Chat-style live log; rich embeds (cards with colour, fields); fast (~200 ms) | Requires a Discord channel; one destination |
| IFTTT Webhooks | Bridges to ~700 services: SMS, email, Google Sheets, Spotify, smart bulbs, IoT platforms | Slower (~5–15 s end-to-end); free tier limited to 5 active recipes |
| Direct service APIs (e.g. Telegram bot, Slack, Pushover) | Targeted, polished, no third party | Each service is its own client implementation |
Discord = great for "live debug stream from my devices". IFTTT = great for "trigger an action somewhere in my digital life". Use both.
Set up IFTTT (free)
- Go to
ifttt.com. Make a free account. - My Applets → New → If "Webhooks: Receive a web request" → event name
doorbell. - Then "Notifications: Send a notification from the IFTTT app" → message
Doorbell pressed at {{Value1}}!. - Connect the "Webhooks" service if asked. Find your key under Webhooks → Documentation. URL format:
https://maker.ifttt.com/trigger/doorbell/with/key/YOUR_KEY_HERE
POST to that URL → IFTTT runs your recipe → phone notification. Optionally include up to 3 string values (value1, value2, value3) as JSON body to fill in template slots.
New Concept · Rich Discord embeds + IFTTT values 25 min
Discord embed format
A plain Discord webhook body has just content. An embed adds a structured card:
{
"embeds": [{
"title": "Doorbell pressed",
"description": "Someone is at the door.",
"color": 5814783,
"fields": [
{ "name": "Time", "value": "19:30:01", "inline": true },
{ "name": "Light", "value": "raw 458 (dim)", "inline": true }
]
}]
}
The color field is a decimal integer (RGB packed: 0x58a4ff = 5808895). Discord renders the embed as a coloured-stripe card — much more legible than a plain message wall.
IFTTT JSON body
{
"value1": "19:30:01",
"value2": "458",
"value3": "dim"
}
Up to 3 values. Inside IFTTT's recipe template, refer to them as {{Value1}}, {{Value2}}, {{Value3}}. The recipe can chain them into the notification message, the email body, the Google Sheets cell, etc.
Wrap both in helpers
bool postDiscord(const String& jsonBody) {
SecureClient client;
client.setInsecure();
HTTPClient http;
http.begin(client, DISCORD_URL);
http.addHeader("Content-Type", "application/json");
int status = http.POST(jsonBody);
http.end();
return status >= 200 && status < 300;
}
bool postIFTTT(const String& v1, const String& v2, const String& v3) {
SecureClient client;
client.setInsecure();
HTTPClient http;
http.begin(client, IFTTT_URL);
http.addHeader("Content-Type", "application/json");
String body = "{\"value1\":\"" + v1 +
"\",\"value2\":\"" + v2 +
"\",\"value3\":\"" + v3 + "\"}";
int status = http.POST(body);
http.end();
return status >= 200 && status < 300;
}Building a Discord embed in code
For more complex JSON, use ArduinoJson — it's much cleaner than string concatenation:
#include <ArduinoJson.h>
String buildDiscordEmbed(const char* timeStr, int rawLight) {
StaticJsonDocument<512> doc;
JsonObject embed = doc["embeds"].createNestedObject();
embed["title"] = "Doorbell pressed";
embed["description"] = "Someone is at the door.";
embed["color"] = 0x58A4FF;
JsonArray fields = embed.createNestedArray("fields");
JsonObject f1 = fields.createNestedObject();
f1["name"] = "Time"; f1["value"] = timeStr; f1["inline"] = true;
JsonObject f2 = fields.createNestedObject();
f2["name"] = "Light"; f2["value"] = String(rawLight) + (rawLight < 300 ? " (dim)" : " (bright)");
f2["inline"] = true;
String out;
serializeJson(doc, out);
return out;
}Worked Example · Doorbell → Discord embed + IFTTT notification 25 min
Step 1 — wire as L03-36 (button on D7)
Step 2 — set up two destinations
Have ready: a Discord webhook URL (from L03-36) and an IFTTT webhook URL with event name doorbell. Both stored as const char* in your sketch (kept private).
Step 3 — the dual-destination sketch
// L03-37 · Dual webhook: Discord embed + IFTTT phone notification
#if defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecureBearSSL.h>
using SecureClient = BearSSL::WiFiClientSecure;
#elif defined(ESP32)
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
using SecureClient = WiFiClientSecure;
#endif
#include <ArduinoJson.h>
#include <time.h>
const char* SSID = "YourNetwork";
const char* PASSWORD = "YourPassword";
const char* DISCORD_URL = "https://discord.com/api/webhooks/REPLACE_ME";
const char* IFTTT_URL = "https://maker.ifttt.com/trigger/doorbell/with/key/REPLACE_ME";
const int BTN_PIN = 13;
const int LDR_PIN = A0;
bool lastBtn = HIGH;
unsigned long lastEdge = 0;
unsigned long lastSentAt = 0;
const unsigned long DEBOUNCE_MS = 50;
const unsigned long COOLDOWN_MS = 10000;
bool postJSON(const char* url, const String& body) {
if (WiFi.status() != WL_CONNECTED) return false;
SecureClient client;
client.setInsecure();
HTTPClient http;
http.begin(client, url);
http.addHeader("Content-Type", "application/json");
int status = http.POST(body);
Serial.print("# POST -> "); Serial.println(status);
http.end();
return status >= 200 && status < 300;
}
void fireDoorbell() {
time_t now = time(nullptr);
struct tm tmNow;
localtime_r(&now, &tmNow);
char timeBuf[20];
strftime(timeBuf, sizeof(timeBuf), "%H:%M:%S", &tmNow);
int rawLight = analogRead(LDR_PIN);
const char* lightLabel = rawLight < 300 ? "dim" : "bright";
// 1. Discord — rich embed
{
StaticJsonDocument<512> doc;
JsonObject embed = doc["embeds"].createNestedObject();
embed["title"] = "Doorbell pressed";
embed["description"] = "Someone is at the door.";
embed["color"] = 0x58A4FF;
JsonArray fields = embed.createNestedArray("fields");
JsonObject f1 = fields.createNestedObject();
f1["name"] = "Time"; f1["value"] = timeBuf; f1["inline"] = true;
JsonObject f2 = fields.createNestedObject();
f2["name"] = "Light"; f2["value"] = String(rawLight) + " (" + lightLabel + ")";
f2["inline"] = true;
String body; serializeJson(doc, body);
postJSON(DISCORD_URL, body);
}
// 2. IFTTT — phone notification with templated values
{
String body = "{\"value1\":\"";
body += timeBuf;
body += "\",\"value2\":\"";
body += rawLight;
body += "\",\"value3\":\"";
body += lightLabel;
body += "\"}";
postJSON(IFTTT_URL, body);
}
}
void checkButton() {
bool b = digitalRead(BTN_PIN);
if (b == lastBtn) return;
if (millis() - lastEdge < DEBOUNCE_MS) return;
lastEdge = millis();
lastBtn = b;
if (b == LOW && millis() - lastSentAt > COOLDOWN_MS) {
lastSentAt = millis();
fireDoorbell();
}
}
void setup() {
Serial.begin(115200);
pinMode(BTN_PIN, INPUT_PULLUP);
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASSWORD);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.println();
configTime(0, 0, "pool.ntp.org");
setenv("TZ", "MYT-8", 1);
tzset();
while (time(nullptr) < 24 * 3600) delay(200);
Serial.println("# Doorbell armed.");
}
void loop() {
checkButton();
}Step 4 — test
Press the button. Within ~1 s your Discord channel shows a coloured embed card with Time and Light fields. Within ~10 s your phone's IFTTT app pushes a native notification.
Step 5 — add a second IFTTT recipe
In IFTTT, create a second applet listening for the same event doorbell. The action: "Google Sheets: Add row to spreadsheet". Configure to write {{OccurredAt}}, {{Value1}}, {{Value2}}, {{Value3}} as four columns. Now every button press also appends a row to your Google Sheet — a free, persistent doorbell log.
Step 6 — third action: dim the smart lamp at night
Another IFTTT recipe: "If Webhooks doorbell + time is between 21:00 and 06:00" → "Philips Hue: turn on the porch light". (Or any other smart-bulb service IFTTT supports.) Same Arduino trigger, three independent automations.
Try It Yourself 15 min
Goal: Change the Discord embed's colour based on time of day — red during the night (22:00–06:00), blue otherwise. Eye-catching for unusual events.
Hint
int colour = (tmNow.tm_hour >= 22 || tmNow.tm_hour < 6) ? 0xEF4444 : 0x58A4FF;
embed["color"] = colour;Goal: Add a username override on the Discord webhook so messages appear as "Front-Door-Bot" rather than "Webhook".
Hint
Add doc["username"] = "Front-Door-Bot"; at the top of the JSON build. Optionally also doc["avatar_url"] = "https://..."; for a profile picture.
Goal: Two-button device. Button A = "doorbell" (fire normal event). Button B = "suspicious" (fire URGENT event with red embed AND a separate IFTTT recipe that sends an SMS).
Hint
Two IFTTT events with different names: doorbell and doorbell_urgent. Two webhook URLs in the sketch. Two button handlers, each calling its own fire function. The IFTTT SMS service is on the Pro tier in 2026; falling back to a Telegram bot or a second Discord channel works on free tier.
Mini-Challenge · Design 3 useful IoT triggers 10 min
Brainstorm three real triggers worth automating with this pattern. For each:
- What sensor / event fires the trigger?
- What Discord embed would you send?
- What IFTTT recipe would catch it on your phone?
Reveal three sensible ideas
- Plant moisture alert: sensor reads < 30% for > 1 hour → Discord embed "Plant thirsty" with current % and last-watered timestamp → IFTTT pushes phone notification "Time to water the plant".
- Fridge door left open: door switch + millis() — if open > 60 s → Discord red embed → IFTTT phone notification "Fridge open".
- Letterbox post arrived: tilt switch in the letterbox flap → Discord blue embed "Mail!" with the time → IFTTT Google Sheet row + push notification.
Tomorrow we ship one of these as Cluster G's capstone: the Doorbell That DMs You.
Recap 5 min
Two destinations from one trigger: Discord for live cards (use embeds array with title / colour / fields), IFTTT for bridging into your phone's native notification system, Google Sheets, email, smart bulbs and ~700 other apps. Free tiers are generous enough for school projects. Latency: Discord ~200 ms, IFTTT ~5–15 s. The pattern: POST JSON to URL → service does something. From here you can wire any sensor event to any digital service. Tomorrow we polish into a portable doorbell — Cluster G's capstone.
- IFTTT (If This Then That)
- A free service that bridges triggers from one app to actions in another. Webhooks integration lets your Arduino fire a trigger.
- Maker Webhooks
- IFTTT's built-in webhook receiver. URL format
https://maker.ifttt.com/trigger/EVENT/with/key/KEY. Accepts an optional JSON body withvalue1,value2,value3. - Discord embed
- A coloured-stripe card sent in a Discord message. JSON shape includes title, description, color, fields. Much more legible than plain text for status updates.
- Webhook URL
- The address a service exposes for incoming triggers. Treat as a secret — anyone with the URL can fire your trigger.
- Recipe / applet
- The trigger + action pairing in IFTTT. One recipe per webhook → notification, or webhook → Google Sheet append.
- Template variable
- Placeholders in IFTTT recipe text like
{{Value1}}that get filled in from the webhook payload. - Fire-and-forget
- Sending a request without waiting for the response. Reduces latency in the trigger loop; loses error visibility.
- Username override
- Discord webhook field that lets each message appear as a custom name / avatar, even though it's coming from a generic webhook.
Homework 5 min
- Set up an IFTTT applet that fires a phone notification when a webhook event arrives.
- Modify yesterday's sketch to fire BOTH Discord and IFTTT. Press the button → Discord embed + phone notification, both within ~10 s.
- Save as
dual-webhook.ino. - Read ahead to ARD-L03-38 (Doorbell That DMs You). Bring a real doorbell-shaped button (or just any button) tomorrow — we'll mount it on cardboard as a finished product.
Bring back next class:
- Working dual-webhook with screenshots of both destinations.
- A button + a piece of cardboard for the doorbell mount.