Slack Alerts When a Web Page Changes
Create one Rendex Watch, point its webhook at n8n, and get a Slack message — with the before, after, and ringed-diff overlay — the moment a page actually changes. The schedule, the real-Chrome render, the storage, and the diff are all Rendex's job.
Last updated 2026-07-21
The Problem
You want to know when a competitor's pricing page, a supplier's terms, or your own status page changes — and you want it in Slack, not in yet another monitoring dashboard. Rolling your own means a cron to re-fetch the page, a headless browser to render JavaScript-heavy markup, somewhere to store each snapshot, a pixel-diff library to compare them, and a way to suppress the noise from rotating banners and timestamps. That is a small service to build and babysit, and a raw HTTP ping can't even see a visual change.
The Solution
Rendex Watch is that service, managed. Create a watch with a webhookUrl pointing at an n8n Webhook node; Rendex re-renders the page on your schedule in real Chrome, diffs it against the baseline, and — only when the change exceeds your threshold — POSTs an HMAC-signed watch.changed event carrying signed before/after/overlay image URLs. n8n verifies the signature, then formats a Slack message. One watch, one webhook node, zero infrastructure.
How the Workflow Runs
Scheduled check
Rendex Watch re-renders the URL on your interval — daily on Free, as fast as every 30 min on Pro. No cron to run yourself.
Real-Chrome diff
Each check is compared to the stored baseline in real Chrome. A pixel diff above your threshold flips the run to changed.
Signed callback
Rendex POSTs a watch.changed event to your n8n Webhook node with a one-line summary of what changed, the added/removed text lines, a 0..1 diffScore, and signed beforeUrl, afterUrl, diffOverlayUrl, and cropUrl (a tight image of just the change).
Post to Slack
n8n verifies the HMAC signature, then posts the overlay image and diff score to your channel (or a DB, PagerDuty, anywhere).
Input → Rendered Output

Rendered by Rendex
What You Need
- A Rendex API key. Watch runs on Free (1 watch, daily checks, email alerts); the webhook channel used here to reach n8n is a Starter+ feature.
- An n8n instance with a publicly reachable Webhook node URL (Rendex must POST to it from the open internet), set to return the raw body.
- A shared webhook secret stored in n8n credentials, used to verify the x-rendex-signature HMAC on every callback.
- A Slack node (or Slack incoming webhook) connected to the channel you want the alerts in.
What This Recipe Uses
Real-Chrome visual diff
Watch re-renders the full page in real Chrome and pixel-diffs it against the baseline — it catches a layout break or a swapped price an HTTP status check never could.
watch.changed / recovered / error
Three edge-triggered events fire on the same signed channel as job and batch webhooks: a change, a recovery after failures, and a check that errored — so you alert on signal, not noise.
Signed, with diff images attached
Every callback carries x-rendex-signature (HMAC-SHA256) plus beforeUrl, afterUrl, and diffOverlayUrl — short-lived signed links to the exact snapshots, so Slack shows what changed.
Scheduled, one credit per check
You set the interval; Rendex owns the cron, render, storage, and diff. Each scheduled check draws one credit from the same pool as your screenshots, PDFs, and extraction.
Build It
# Create a watch whose change-webhook posts to your n8n Webhook node.
# diffMode "visual" = pixel diff + a highlighted overlay; threshold is the
# 0..1 noise floor the diff must EXCEED to count as a change.
curl -X POST https://api.rendex.dev/v1/watches \
-H "Authorization: Bearer $RENDEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://competitor.com/pricing",
"name": "Competitor pricing",
"intervalMinutes": 1440,
"diffMode": "visual",
"threshold": 0.02,
"webhookUrl": "https://your-n8n.example.com/webhook/rendex-watch"
}'
# => { "success": true, "data": { "id": "<uuid>", "lastStatus": "queued", ... } }
#
# webhookUrl is a Starter+ feature (email alerts work on every plan).
# intervalMinutes floor by plan: Free 1440 (daily), Basic 180, Starter 60, Pro 30, Enterprise 5
# — a faster value returns 403 WATCH_INTERVAL_TOO_FAST. Baseline capture draws 1 credit.// Rendex POSTs this to your webhookUrl when a check exceeds the threshold.
// Headers carry the auth signal (identical scheme to job/batch webhooks):
// x-rendex-event: "watch.changed" | "watch.recovered" | "watch.error"
// x-rendex-signature: HMAC-SHA256 over `${timestamp}.${rawBody}`
// x-rendex-timestamp: unix seconds (matches the value signed above)
// x-rendex-delivery-id: uuid (same across retries — use to dedupe)
{
"event": "watch.changed",
"watchId": "6b1c...-uuid",
"runId": "9af2...-uuid",
"url": "https://competitor.com/pricing",
"diffScore": 0.038,
"diffPixels": 14820,
"summary": "The Pro plan price rose from $19 to $24 per month.",
"textDiff": { "added": ["$24/mo"], "removed": ["$19/mo"] },
"beforeUrl": "https://api.rendex.dev/v1/images/...?sig=...",
"afterUrl": "https://api.rendex.dev/v1/images/...?sig=...",
"diffOverlayUrl": "https://api.rendex.dev/v1/images/...?sig=...",
"cropUrl": "https://api.rendex.dev/v1/images/...?sig=...",
"changedRegion": { "x": 0.1, "y": 0.42, "width": 0.5, "height": 0.12 }
}
// Post {{summary}} straight to Slack for a text-only alert; attach {{cropUrl}} to
// show just what changed. before/after/overlay/crop are short-lived SIGNED URLs
// (same field names the REST run-history endpoint returns). Re-host for a permanent copy.// n8n Code node placed right after the Webhook node (set to "raw body").
// Rejects forged callbacks, then builds a Slack message with the diff overlay.
const crypto = require('crypto');
const SECRET = $env.RENDEX_WEBHOOK_SECRET; // stored in n8n credentials/env
const headers = $input.first().json.headers;
const rawBody = $input.first().json.body; // exact bytes as received
const signature = headers['x-rendex-signature'];
const timestamp = headers['x-rendex-timestamp'];
// Rendex signs `${timestamp}.${rawBody}` with HMAC-SHA256 (hex):
const expected = crypto
.createHmac('sha256', SECRET)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
const ok =
signature &&
signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!ok) throw new Error('Invalid Rendex webhook signature — rejecting.');
// Replay guard (optional): drop callbacks older than ~5 minutes.
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) {
throw new Error('Stale Rendex webhook (>5 min) — rejecting.');
}
const e = JSON.parse(rawBody);
if (e.event !== 'watch.changed') return []; // ignore recovered/error here
// Shape a Slack "chat.postMessage" payload — overlay image as a block.
return [{
json: {
channel: '#market-intel',
text: `Change detected on ${e.url}`,
blocks: [
// The summary is a plain-English sentence — a text-only alert needs nothing else.
{ type: 'section', text: { type: 'mrkdwn',
text: `*${e.url} changed*\n${e.summary ?? (e.diffScore * 100).toFixed(1) + '% visual diff'}` } },
// Attach the crop of JUST the change (falls back to the full overlay).
{ type: 'image', image_url: e.cropUrl ?? e.diffOverlayUrl, alt_text: 'What changed' },
],
},
}];100 free API calls/month — no credit card required. Get your API key and start building.
Reach for this whenever a human needs to see that a page moved — competitor pricing, a vendor's SLA or terms, a regulator's notice board, your own marketing site after a deploy. The reason to wire it through n8n rather than just turning on Watch's email alert is routing and enrichment: once the signed event lands in n8n you can fan it out to a specific Slack channel, open a Linear issue, page on-call, or write a row to a database — each with the overlay image attached so the reviewer sees what changed without opening the site. The signature check is the step people skip and regret; without verifying x-rendex-signature, anyone who learns your webhook URL can forge a watch.changed payload. Watch itself runs on the free tier (one watch, a daily check, email alerts); the webhook channel this recipe routes through is the one Starter-plan feature here, and each scheduled check draws a single credit from the same pool as your screenshots and PDFs.