Rendex
Recipe

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

Left: a single POST that creates a Rendex Watch on a pricing page. Right: an n8n Webhook node receiving a signed watch.changed event that resolves into a Slack message with the before/after/overlay diff.

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-watch.sh
# 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.
watch-changed.json
// 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.
verify-and-alert.js
// 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.

Frequently Asked Questions

Related Resources