Deploy check
The question right after shipping is “did that break anything?” Mark a deploy, and PageHum compares the hours after it with the same hours on the week before: client errors, failing requests, broken links, rage clicks, the funnel, and speed. It says what got worse, where, and by how much, with a prompt to fix it.
Plans
| Free | Starter | Pro | Ultra | |
|---|---|---|---|---|
| Windows judged after each deploy | — | First 3 hours | First hour, 3 hours, and day | First hour, 3 hours, and day |
Each deploy is checked from when it’s marked; nothing extra runs on your site.
Marking a deploy
A deploy marker is the line on the board’s charts for a deploy. Any of these starts its check:
- The site’s deploy hook, from Changes on the board: one URL to call from Vercel, Netlify, GitHub, or any CI, no key needed. It answers with the marker’s
id. - The API:
POST /sites/{key}/markerswith a write key. Put the commit in the text, likea1b2c3d New checkout, and the prompt starts from it. - Changes on the board, with the kind set to Deploy.
A deploy marked more than a day after it happened isn’t checked: the hours after it are already behind other changes.
How it's judged
| Window | Is | Judged |
|---|---|---|
| First hour | The hour the deploy landed in (if in its first 10 minutes), else the next | 5 minutes after it ends |
| First 3 hours | That hour and the next two | 5 minutes after they end |
| First day | 24 hours from there | 5 minutes after they end |
Each window is compared with the same hours on each of the 7 days before. PageHum keeps each hour’s counts for 8 days for this; until a site has 3 days of them, it compares with the 7 whole days before instead.
| Reading | Worse when | Needs |
|---|---|---|
| Client errors per pageview | Up at least 1 point and by half | 100 pageviews |
| Failing requests per pageview | Up at least half a point and by half | 100 pageviews |
| Broken link hits per pageview | Up at least half a point and by half | 100 pageviews |
| Rage clicks per pageview | Up at least half a point and by half | 100 pageviews |
| Visits reaching the goal | Down at least 5 points | 50 visits |
| LCP, p75 | Up at least 500 ms, and past 2.5 s | 30 readings |
| INP, p75 | Up at least 100 ms, and past 200 ms | 30 readings |
| TTFB, p75 | Up at least 300 ms, and past 800 ms | 30 readings |
- Worse: the change is also past three times how much that reading usually moves from day to day, and for a rate, how much it moves by chance in a window that size. A site whose errors swing a lot needs a bigger jump.
- Watch: past twice that, and half the size. A new error seen 10 times or more also makes a fine deploy one to watch.
- Looks fine: everything within its usual range.
- Too quiet to tell: no reading had enough traffic in the window, and at least 3 of the 7 days before with half that. A quiet site never gets a false Worse.
A checked page or flow that started failing after the deploy makes it worse whatever the counts say. Errors and failing endpoints that none of the 7 days before had are listed by page, at 3 or more.
Where it shows
- Since the last deploy, near the top of the board for a day after each deploy: each window, what moved with its numbers before and after, and Copy prompt to fix it when it’s worse or one to watch.
- A lamp on the deploy’s marker in every chart: green, amber, or red. Hover the marker for the verdict.
- When it’s worse, once per deploy: a notification, browser push, and your Slack, Discord, Teams, Telegram, or webhook channels (the webhook event is
deploy.worse; see payloads).
In CI
GET /sites/{key}/deploys/{id} answers for a deploy marker’s id, or latest, with a read key. A pipeline can wait for the window it cares about and fail on regressed. Or ask your assistant: the MCP tool is get_deploy_check.
The answer
{
"ok": true,
"data": {
"marker": { "id": "m_8f2k1c", "at": 1791986700000, "text": "a1b2c3d New checkout", "source": "api" },
"verdict": "worse",
"regressed": true,
"settled": false,
"nextAt": 1791994500000,
"windows": [
{
"key": "1h", "label": "First hour", "ready": true, "verdict": "worse", "pageviews": 412, "baseline": "hours",
"findings": [
{ "metric": "errors", "label": "Client errors per pageview", "kind": "rate", "before": 0.011, "after": 0.136, "verdict": "worse" }
]
},
{ "key": "3h", "label": "First 3 hours", "ready": false, "verdict": null, "pageviews": 780, "findings": [] },
{ "key": "24h", "label": "First day", "ready": false, "verdict": null, "pageviews": 780, "findings": [] }
],
"newErrors": [{ "path": "/cart", "message": "TypeError: cart.items is undefined", "count": 57 }],
"newRequests": [],
"failing": [],
"prompt": "My website \"Lumen\" got worse after a deploy…"
}
}This GitHub Actions workflow marks each deploy, then waits for the first hour’s verdict and fails the run if it’s worse, with the prompt in the run’s summary. Add PAGEHUM_KEY (a key with write access, from your account page) to the repository’s secrets.
.github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
env:
PAGEHUM_SITE: s_your_site_key
jobs:
deploy:
runs-on: ubuntu-latest
outputs:
marker: ${{ steps.mark.outputs.id }}
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh # your deploy
- id: mark
name: Mark the deploy on PageHum
run: |
id=$(curl -fsS -X POST "https://api.pagehum.com/v1/sites/$PAGEHUM_SITE/markers" \
-H "Authorization: Bearer ${{ secrets.PAGEHUM_KEY }}" -H "Content-Type: application/json" \
-d "$(jq -n --arg text "$(git log -1 --pretty='%h %s')" '{text: $text}')" | jq -r .data.id)
echo "id=$id" >> "$GITHUB_OUTPUT"
deploy-check:
needs: deploy
runs-on: ubuntu-latest
timeout-minutes: 150
steps:
- name: Fail if the first hour after the deploy got worse
run: |
url="https://api.pagehum.com/v1/sites/$PAGEHUM_SITE/deploys/${{ needs.deploy.outputs.marker }}"
while :; do
check=$(curl -fsS "$url" -H "Authorization: Bearer ${{ secrets.PAGEHUM_KEY }}")
[ "$(jq '.data.windows[0].ready' <<< "$check")" = "true" ] && break
sleep 300
done
echo "Deploy check: $(jq -r '.data.verdict' <<< "$check")"
if [ "$(jq '.data.regressed' <<< "$check")" = "true" ]; then
jq -r '.data.prompt' <<< "$check" >> "$GITHUB_STEP_SUMMARY"
exit 1
fi