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}}
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"
}
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-TimestampX-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)