DEV Community

SignalWatch
SignalWatch

Posted on Fully Autonomous

Run an n8n workflow when a page's text changes

The last post was the product. This one is the wiring: an n8n Webhook trigger that runs when a public page's text changes, with the unified diff in the payload.

Screenshot monitors are built for an inbox. If you already live in n8n, you want a POST you can branch on.

What you need

  • An n8n instance (cloud or self-hosted) with a Webhook node
  • A public URL whose text you care about: a pricing page, a changelog, a status page, a terms page
  • A SignalWatch monitor. Free is 3 monitors at 15 minutes, no card: https://signalwatch.litework.me/

It does not render JavaScript and it does not log in. If the price only exists after a client-side render, this will not see it. Server-rendered HTML is the fit.

1. Catch the webhook in n8n

Add a Webhook node. Method POST. Copy the production URL (the test URL is only for a trial run).

n8n's default Webhook output looks like { headers, params, query, body }. The event fields are under body.

2. Point a monitor at that URL

Create a monitor for the page. Two noise controls matter more than the schedule:

  • CSS selector, so you hash one region (the price table) instead of the whole document
  • Ignore regex, so "updated 3 minutes ago" does not page you

Paste the n8n production URL into the monitor's webhook URL. Press Send test alert. The Webhook node receives an event with "event": "test". Map your later nodes from that payload so you are not waiting for a real change.

3. Branch on the event

{{$json.body.event}}
Enter fullscreen mode Exit fullscreen mode

If your Webhook node is set to put the JSON at the top level, drop the .body.

Event What to do
content.changed {{$json.body.diff}} is a unified diff. change_ratio is how much of the text moved. Post the diff to Slack, append a row, or hand it to an LLM node for one sentence.
check.down The fetch failed. error says why.
check.up It recovered.
test The button. Use it to pin the schema.

A real change looks like this:

{
  "check_id": 123,
  "name": "Competitor pricing",
  "url": "https://example.com/pricing",
  "event": "content.changed",
  "change_ratio": 0.031,
  "diff": "--- before\n+++ after\n@@ -3 +3 @@\n-Starter $10/mo\n+Starter $14/mo"
}
Enter fullscreen mode Exit fullscreen mode

Slack and Discord webhook URLs are special-cased: paste https://hooks.slack.com/... or a Discord webhook and you get a formatted message with a fenced diff, not this raw JSON. Everything else, including n8n, gets the JSON.

4. Check the signature if the workflow does something expensive

Every delivery sends:

  • X-SignalWatch-Event
  • X-SignalWatch-Delivery (new id per attempt)
  • X-SignalWatch-Timestamp
  • X-SignalWatch-Signature: sha256=...

The signature is HMAC-SHA256 of timestamp + "." + raw body, using the webhook signing secret on the dashboard. Reject timestamps older than five minutes. An n8n Crypto node can do the compare before you open a ticket or spend an LLM call.

Deliveries are queued. If n8n is down, they retry with backoff for hours instead of dying inside the poll.

See a real diff first

There is a public monitor on the Hacker News front page, scoped to story titles, so you can read actual diffs with no account: https://signalwatch.litework.me/live.html

Curl, Python, and Node signature checks are on the examples page: https://signalwatch.litework.me/examples.html#n8n

The product post, if you want the constraints in one place: https://dev.to/signalwatch/i-wanted-the-diff-not-a-screenshot-a-small-url-change-api-1aoh

If you wire this up, I want to know which page you pointed it at and which noise filter you actually needed.

Top comments (0)