CMS and deploy webhooks
The loop needs to know when a change went live. Every site gets a hook URL; a publish, a theme deploy or a release posted there is written to the site’s change log, the site audit’s findings it plausibly addresses move to implemented with the CMS as the actor, and the next run confirms or refutes them. A Fix a page or Foundations play passes its acceptance check once a run no longer finds its issue, and its verdict window opens from there. Results reach Slack, Teams, email and the issue in your tracker.
Enable
Section titled “Enable”On the site’s page, Changes from your CMS, press Enable. The panel shows the hook URL (with a per-site token in it), fields for the providers that sign their calls, and two choices:
- Also mark open findings: by default only accepted findings (and refuted ones, for a retry) are marked when their page changes; open ones are left for a person to triage.
- Queue a change run after events go quiet: half an hour after the last event, at most once a day, within the plan’s allowance. A theme deploy is the case that matters: one deploy changes every page of a type.
Rotate issues a new token and invalidates the old URL. Remove hook deletes it.
What a change reaches
Section titled “What a change reaches”| Event | Findings marked |
|---|---|
| a page (a URL, or a list of URLs) | page-scoped findings on exactly those URLs |
| a template (theme deploy, layout change) | template-scoped and site-scoped findings |
| a site (a release, no detail) | template-scoped and site-scoped findings |
A page event never marks a template finding: one edited post is not evidence that a template was fixed. The event and what it marked are visible in the change log and in the audit log.
The generic shape
Section titled “The generic shape”Any deploy step can POST JSON to the hook URL:
curl -X POST "$VERCATUS_HOOK_URL" -H "content-type: application/json" \ -d '{ "kind": "page", "urls": ["/pricing", "https://www.example.com/docs/setup"], "note": "release 2026.09.3" }'kind is page, template or site; urls may be paths or absolute; note and topic are free
text kept with the event; source (or the header X-Vercatus-Source) names the system. Bodies over
512 KB are refused. The URL’s token is the only authentication for this shape, so treat it as a secret.
WordPress
Section titled “WordPress”No plugin from the directory is needed. Either paste the snippet below into a code-snippets plugin or
the theme’s functions.php, or download it as a single-file plugin, zip it and upload it under
Plugins, Add new, Upload:
Set VERCATUS_HOOK_URL in wp-config.php (or at the top of the file) to the site’s hook URL. It
sends a page event when a post, page or product is published or updated, and a template event when
the theme is switched or the customiser is saved. Requests are non-blocking; publishing is not slowed.
Shopify
Section titled “Shopify”In the Shopify admin, Settings, Notifications, Webhooks: create subscriptions for products/update,
collections/update, pages/update, articles/update and themes/publish, format JSON, pointing at
the hook URL. Copy the signing secret shown under the webhooks list into Shopify webhook secret in
Vercatus. Every call is verified against it (X-Shopify-Hmac-Sha256); unsigned or mismatched calls
are refused. Product, collection, page and article events become page events on the storefront’s
URL; a theme publish becomes a template event.
Contentful
Section titled “Contentful”Settings, Webhooks: a webhook on entry publish and unpublish, URL the hook URL, and a custom header
X-Vercatus-Secret set to a value you also paste into Contentful shared secret in Vercatus. The
entry’s slug field (or path / url) becomes the page URL through the URL template
({origin}/{type}/{slug}, with {id} available) or, when no template is set, by finding the sitemap
URL that ends in the slug. An entry without a resolvable URL is recorded as a site event.
Sanity
Section titled “Sanity”Manage, API, Webhooks: a GROQ-powered webhook on create, update and delete, URL the hook URL, with a
secret; paste the same secret into Sanity webhook secret. Calls are verified against the
sanity-webhook-signature header. Include _id, _type and slug in the projection; the URL is
resolved the same way as for Contentful.
Deploys: GitHub, Vercel, Netlify
Section titled “Deploys: GitHub, Vercel, Netlify”A deploy changes every page of a type at once, so it is a template event that names the commit. With Queue a change run on, the check follows ten minutes after the deploy rather than thirty, and its alert, its run page and the runs list say which deploy it checked, how many pages it checked and where AI crawlers are newly refused, or that “the deploy changed nothing the machines see”, which a deploy is always worth one line for. Builds still going and pings are answered and ignored.
- GitHub: repository Settings, Webhooks: payload URL the hook URL, content type JSON, a secret; events
Deployment statuses (a successful deployment is the event; a push is recorded as a site change). Paste
the secret into GitHub webhook secret; calls are verified against
X-Hub-Signature-256. - Vercel: team Settings, Webhooks: URL the hook URL, event Deployment Succeeded, the project. Paste the
secret Vercel shows into Vercel webhook secret; calls are verified against
x-vercel-signature. Preview deployments are ignored; production ones count. - Netlify: site Settings, Notifications, Outgoing webhook on Deploy succeeded, URL the hook URL, with a
JWS secret. Paste it into Netlify JWS secret; calls are verified against
X-Webhook-Signatureand the body hash it carries. Deploys to contexts other than production are ignored.
Tell the search engines too: IndexNow
Section titled “Tell the search engines too: IndexNow”The hook tells Vercatus a change shipped. To tell the search engines that crawl on request, a deploy step can also
send the changed, added and deleted URLs to IndexNow: a submission to one endpoint is
shared with all participating engines, which include Microsoft Bing, Naver, Seznam.cz, Yandex and Yep. Google is not
one of them, so use Search Console for Google. Put a key file at the site root (a text file named after the key, holding
the key) and post the URLs as JSON to https://api.indexnow.org/IndexNow. Bing says IndexNow keeps information fresh
across search and AI experiences, and Copilot answers draw on the Bing index.
Honest limits
Section titled “Honest limits”A publish says “this URL changed”, not “the finding was addressed”. A page republished for a typo marks its accepted findings implemented, and the next run will refute them; the effect estimate reports whether the page’s content actually changed, so those cases read as what they are. Headless systems know entries, not URLs; the template or the sitemap lookup has to be right for page events to match. Template events are broad by design.