When the page offers to filter or sort a list, at least one filtered view is reachable by URL - a link carrying a filter query parameter, or a GET form around the controls. Warns when controls are served but no filtered view has its own URL. Fails when the page offers filtering and serves no operable control at all. Skips on pages that offer no filtering.
This is the largest published cause of agent failure on real websites. Across 300 tasks on 136 live sites, filter and sorting errors accounted for 57.7% of the strongest agent’s failures, ahead of navigation errors at 19.6%. An agent that can request /shoes?sort=price_asc gets the right list on the first attempt; an agent that has to operate a slider or a custom dropdown, without being able to see the result, stalls and moves on.
- Put the filter and sort state in the query string, so a filtered view has its own address: `/shoes?sort=price_asc&size=10`.
- Make each facet option a real link to that address, or wrap the controls in `<form method="get">` so choosing an option produces one.
- Keep the JavaScript behaviour you already have. This sits underneath it: the page can still update instantly and also have a real address.
- Confirm the address works cold: open it in a private window with no history and check the filtered list renders.
- Avoid POST for filtering and avoid putting state only after a `#`, since neither produces an address the server can act on.
Paste this into Claude Code, Cursor, or any assistant with your repository open. It carries the steps, how to verify them, and the shortcuts to avoid. It is generic, though: run a scan to get one written from what your pages actually do.
Run a scan against your domain to see whether operability.filters_addressable currently passes, warns, or fails. Free, no signup; the score page is permanent and citable.