- Aug 28
AI Website Change Monitoring: How to Stop the False Alerts and Actually Use the Real Ones
- Mark Fulton
- Automation, AI Systems, AI Agents
- 0 comments
Point a watcher at a page, get an email when something moves. That part works on day one. What decides whether you still have a monitor running a month later is day four, when the thing has emailed you eleven times and every one of those emails was about a rotating testimonial.
I run change monitors across my own products and a short list of pages I care about. The useful ones fire maybe twice a week. Getting there had almost nothing to do with picking a better tool. It came down to accepting two things: a raw page diff is close to useless, and the alert is the cheap half of the system.
The standard write-up on this stops at the detection primitive. Here is the rest of it. What actually changes on a page when nothing changed, what to strip before you compare anything, how often to check and what that cadence costs, the baseline problem nobody warns you about, and what to do with a real change once you finally have one.
Why does a website change monitor fire when nothing changed?
Because the page is not the content. You are diffing a rendered document, and a rendered document carries a lot of moving parts that have nothing to do with whether the company changed its pricing.
Here is what moves on a typical marketing page between two checks, with zero editorial change behind it:
Asset URLs carrying a new build hash after any deploy, including a deploy that changed nothing you can see
Anti-forgery tokens, session identifiers, and nonce attributes, which are supposed to change on every request
A "last updated" stamp, or a relative date that ticks from "2 days ago" to "3 days ago"
Rotating testimonials, logo carousels, "recently viewed", "you might also like", featured post blocks
Live counters: view counts, signup counts, "14 people are looking at this right now"
Consent banner variants, which render differently depending on where the check appears to be coming from
Split-test variants, where you get version A on one check and version B on the next, forever
Advertisement and tracking slots
Lazily loaded sections that arrive or fail to arrive depending on how long the fetch waited
Two different problems are hiding in that list. There is rendering noise, where the meaning is identical and the bytes differ. And there is rotation noise, where the content genuinely differs and means nothing.
A byte diff catches both and calls both a change. A screenshot diff catches both plus font rendering differences between runs. Handing the raw page to a model on every check catches fewer of them, but you pay on every single check, and a model reading two versions of a page will happily tell you something changed because a sentence got rearranged in a carousel.
The order matters more than the technique. Normalize first, then decide whether you need a model at all.
What to normalize before you diff anything
The pipeline that survives contact with real pages is five steps: fetch, extract, normalize, hash, compare.
Extract a region, not a page. Pin a selector to the element that actually holds the thing you care about. The pricing table. The changelog list. The careers listings. Watching a whole page means watching a hundred things you do not care about in order to catch the one you do.
Strip everything that is not content. Remove script and style elements, remove comments, and drop every attribute except href. Class names and generated identifiers are churn.
Collapse whitespace. Rendering pipelines reflow constantly and none of it is meaningful.
Neutralize the volatile tokens. Replace anything date-shaped with a fixed placeholder. Drop query strings from links so a tracking parameter does not read as a new destination. Drop identifiers that look machine-generated.
Sort collections that have no stable order. If a section shuffles its items on render, sort them before comparing, or the shuffle is a permanent change you will never stop seeing.
Then hash the normalized text, and store both the hash and the text.
That pairing is the part people skip. The hash tells you cheaply that something moved. The stored text lets you show exactly what moved without fetching the page a second time and hoping you get the same variant back.
Once a monitor is normalized properly, most of mine run on a plain string comparison and never touch a model on a quiet day. The model earns its cost only on the runs where the hash actually moved, and by then its job is not detection at all. Its job is to say whether the change matters and what should happen next.
The cheapest check is the one where the server does the work
Before you render anything, ask the server whether it is worth rendering. A conditional request sends back the validator you already hold and gets a 304 with no body when nothing changed, which is documented well in the MDN reference for the ETag header. That is close to free compared to a browser render.
The honest caveat: most of the pages worth watching are dynamically rendered marketing pages, and they either send no useful validator or send one that changes on every response. Treat the conditional request as a fast path that sometimes works, never as the strategy. Plenty of the content you want is also rendered client-side, so the raw response never contains it and you need a real browser render regardless.
While you are here, be a polite client. Read the robots exclusion file and honor it, identify your client honestly in the user agent string, keep the request rate low, and back off when you get rate-limited or a server error. The protocol is a real standard, published as RFC 9309, the Robots Exclusion Protocol, and treating it as optional is how a monitor turns into a blocked address.
How often should a change monitor actually run?
Cadence is the cost lever. The model is not.
Run the arithmetic once and it settles most of the design. Checking a page every five minutes is 288 checks a day. Hourly is 24. Twice a day is 2. Same page, same pipeline, and the five-minute schedule costs 144 times what the twice-daily one costs. Multiply that by the number of pages you are watching and the difference stops being theoretical.
So match the cadence to how fast the thing you are watching actually moves:
Pricing and terms pages change a few times a year. Daily is generous.
Documentation and changelogs move weekly. Daily is fine.
Job listings and careers pages move daily. Every few hours at most.
Inventory and ticket availability move in minutes, and if that is your use case you want a purpose-built tool, not a general monitor.
Then tier it. The cheap normalize-and-hash pass runs on the fast cadence. The expensive pass, where a model reads the before and after and decides what it means, runs only when the hash moved. On most days the expensive tier never runs at all, which is exactly the point.
The first run problem, and every version of it after that
Here is the failure that gets skipped in every walkthrough I have read. A monitor needs a baseline, and there are four separate moments when it legitimately does not have one. Each of those moments will fire an alert for every page you watch unless you handle it.
The first run. There is no previous hash, so everything is new. Seed the state, do not alert.
A change to your own normalizer. The moment you add a rule that strips one more thing, every stored hash is stale and every monitor reports a change. Version the normalizer, store that version alongside the hash, and on a version bump re-seed silently instead of alerting.
A site redesign. The selector moves, the whole region reads differently, and one real change becomes a permanent wall of diff. Re-baseline it once, deliberately.
A selector that disappears. This is the dangerous one, and it is the reverse of the others. Extraction returns an empty string, an empty string hashes perfectly stably, and the monitor reports a calm page forever while watching nothing at all.
So the state you keep per monitor is not just a hash. It is the URL, the selector, the normalizer version, the current hash, the last normalized snapshot, the last successful fetch time, the last actual change time, and a consecutive failure count.
Point four has cost me more than the other three combined. A broken monitor and a monitor watching a page that never changes look identical from the outside. Both are silent.
What to do with the change once it fires
This is where most setups quietly die, and it is the reason I stopped thinking of this as a monitoring problem.
Detection is solved arithmetic. The expensive half is that a change arrives at a moment when you cannot act on it. You are asleep, or in the middle of something else, and by the time you open the email the context is gone and the alert becomes one more thing to catch up on. Alert-only monitoring has a shelf life of about two weeks.
The fix is to route the change into work rather than into your inbox. Once the hash has moved, classify what happened, then send it down one of three routes:
Log and ignore. Most changes. Recorded, searchable later, no notification.
Draft something for review. The common one. The change becomes the trigger for work that gets prepared and then waits for a human.
Act unattended. Rare, and deliberately narrow.
The middle route is the whole value. A competitor ships a feature, a vendor changes its terms, a standard gets updated, and what you actually want is the draft that the change should have produced, sitting ready when you next sit down. I already had the fan-out for that built, which is the piece I wrote up in my AI content repurposing workflow, so the monitor never needed to know how to produce anything. It only needed to know how to hand a change to something that did.
Which route a change is allowed to take is a permissions question, not a technical one. Nothing in my setup publishes on its own, and the reasoning behind where I draw that line is in what I gate and what I let run unattended.
That handoff, from a URL changing to a finished bundle of assets waiting for review, is the exact workflow I walked through end to end in the Web Monitor to Content Factory session. It covers the three ingestion paths, a webhook, a cron job, or a scheduled agent task, and what comes out the other side. The full replay of that session is available instantly, along with the workflow and the repo, so you can take the routing layer rather than rebuild it.
If you want the scheduled side of it, the run itself is a non-interactive agent invocation on a cron, which is covered in the guide to running Claude Code programmatically. There is no service to host. There is a schedule, a script, and a state file.
Reliability: what a dead monitor looks like
A monitor is a piece of software that runs when nobody is watching it, which puts it in the category where the interesting failures are the silent ones. I wrote about that category more broadly in what breaks when nobody is watching, and change monitors have three specific versions of it.
The bot wall. The site starts serving a challenge or an interstitial instead of the page. Your monitor sees one dramatic change, then settles into perfect stability, and never sees the real content again. It looks healthy.
The vanished selector. Covered above. Empty extraction, stable hash, permanent silence.
The run that stopped. The schedule failed, the machine slept, the credential expired. You read no alerts as no changes.
All three have the same shape, so they have the same fix: a heartbeat and a sanity check. Every run should assert that the extraction is non-empty, is longer than a floor you set per monitor, and contains at least one token you expect to always be present on that page. A monitor that fails that assertion for more than a couple of runs should alert about itself, loudly, in a way that reads differently from a content alert. The most valuable notification a monitor sends is not "this page changed". It is "I have not been able to read this page since Tuesday".
Should you build this or just buy a watcher?
I would rather say this plainly than pretend building is always the answer.
Buy an off-the-shelf watcher when you are tracking under about ten pages, you want an email, the pages are simple, and nothing downstream needs to happen. Those tools cost very little, set up in minutes, and building your own will not be a good use of a weekend.
Build it when the change has to become work. When the detection is the first step of something that runs inside a system you already own, when you want the classification and the routing and the draft, and when the alert itself is the least interesting output. That is the only reason that has held up for me.
Frequently asked questions
Can AI website change monitoring replace a dedicated change detection tool?
For simple watching, no, and it does not need to. A dedicated watcher will notice that a page moved more cheaply than an agent will. What an agent adds is judgment about whether the change matters and the ability to do something about it. The strongest setup uses both ideas: cheap deterministic detection on a schedule, and a model only on the runs where something actually moved.
How do I monitor a page that requires a login?
Carefully, and usually only on accounts you own. Session cookies expire, and an expired session turns into a login page that your monitor reads as a dramatic content change. If you monitor behind a login, add a sanity check that fails the run when the extraction looks like a sign-in form, and treat that as a monitor failure rather than a content change. Check the terms of the service first. Automated access to an authenticated area is frequently prohibited even when it is technically easy.
Why does my monitor still fire when only an advertisement changed?
Because you are watching the page rather than a region of it. An advertisement slot, a consent banner, and a recommendation widget are all content as far as a diff is concerned. Pin your extraction to the specific element that holds what you care about, then normalize what is left. If a noisy element sits inside the region you genuinely need, strip it explicitly by selector before you hash.
How much does it cost to run an AI change monitor?
Almost all of the answer is cadence, not model choice. A page checked twice a day is 2 runs. The same page every five minutes is 288. If a model reads the page on every single check, that difference lands directly on your bill, which is why the tiered approach matters so much: cheap deterministic checks on the schedule, and the model only on the runs where the hash moved. Done that way, a handful of pages costs very little, because the expensive path runs a few times a week.
Is it legal to monitor a competitor's website?
Reading publicly available pages at a reasonable rate is normal practice and is what search crawlers do all day. That said, honor the robots exclusion file, do not hammer the server, identify your client honestly, read the site's terms, and stay out of anything behind a login you were not given. None of that is legal advice, and if what you are building depends on the answer, ask someone qualified before you scale it up.
If you want the whole system rather than the monitor
A change monitor is one piece of a much larger pattern: agents that run on a schedule, watch something, and hand work to the next stage without a human starting them.
That pattern is what the Agent Ops Club is built around. Membership is $399 a month, billed annually at $4,788 for the year, and it includes eight agent employees you can deploy, the Agent Ops Masterclass at 9 modules and 44 lessons, a software library with a resale license so you can deploy the same builds for clients, monthly one-on-one sessions, and a first-client guarantee: land your first client inside 90 days or I work with you one on one, at no extra cost, until you do.
If you are already building this kind of thing and want the rest of the stack rather than one more tutorial, that is where I would start.
Subscribe Now for More AI Insights
Subscribe for Updates from Reinventing AI
Stay current on the most cutting-edge AI solutions for ambitious entrepreneurs and marketers!