Previews
Check every preview deploy on its own address, before it goes to production, and decide separately whether to be alerted about it.
Updated on 25 September 2026
On this page
- Set it up
- What PostShip checks
- What you see
- What triggers an alert
- Limits and plans
- Troubleshooting
- Why isn't my preview checked?
- Why do all my previews fail on a protected page?
- Why does the Check block the pull request when the page that went down isn't important?
- Performance budget
- What PostShip measures
- Set it up
- What you see
- What triggers an alert
- Limits and plans
- Troubleshooting
- Visual regression
- What PostShip compares
- Set it up
- What you see
- What triggers an alert
- Limits and plans
- Troubleshooting
- Rollback
- By hand
- On its own
- What we return to
- What PostShip sends
- Troubleshooting
The production webhook arrives after the fact: the 500 is already live. A preview, though, is checked before. With preview checks, every Vercel preview, every Netlify deploy-preview or branch-deploy and every Cloudflare Pages preview is checked on its own address, never against your production, and the result is posted on the pull request's commit.
Set it up
On Project → Settings → Monitoring, “What is checked, besides production” section, 2 switches — because they are 2 decisions:
- Check previews. The checks run against the preview URL. The result is visible in Deployments (“Preview” badge) and on the commit's GitHub Check.
- Alert on failing previews, visible only once the first is on. Disabled by default: 6 pull requests in the afternoon would make 6 messages for pages that aren't live, and it's that noise that makes people turn alerts off — production included.
The host's webhook must be connected (Connect your host): it's what announces the preview and its address.
What PostShip checks
Every monitored URL is rewritten onto the preview's host — https://www.acme.fr/pricing becomes https://acme-git-feature-x.vercel.app/pricing — then checked as usual:
| Kind of URL | On a preview |
|---|---|
| HTTP & assets, with the payment pages assertions and the target's private header | Yes |
| Open Graph | Yes |
| Sitemap | Yes |
| Canary form | Yes — a route that moved breaks on the preview first, that's the whole point |
| Payment journey | Yes, each step rewritten onto the preview host |
| SSL certificate | No: it's the host's, renewed by them |
| Indexability | No: a preview is noindex by construction |
| Stripe check | No: the success URL of a real payment doesn't point to a preview |
Then, after the checks, the PageSpeed measurement and the visual comparison of the preview against the last production capture — what the pull request is going to change, before it goes. No budget, no grade and no alert: nothing is live.
How PostShip recognises a preview depends on the host: target other than production at Vercel, context in deploy-preview or branch-deploy at Netlify, environment at preview or a <label>.<project>.pages.dev subdomain at Cloudflare. The checked address must be in *.vercel.app, *.netlify.app or *.pages.dev; otherwise the preview is ignored (skipped: "invalid_preview_url"), never folded onto production.
What you see
- In Deployments: one line per preview, “Preview” badge, with the address and the verdict. No Ship Score, no T+2 / T+8 re-checks.
- On the GitHub commit: a
PostShipCheck that tells the story of the preview —Preview vérifiée · score 94 · checkout OK— with, in its body, the time of the check, the host, a table of pages (✅ / ❌ and the reason), the checkout state and the link to Deployments. The score is the Ship Score applied to what was checked on the preview: it only deducts what was looked at, and claims nothing about the certificate or DNS, which mean nothing on*.vercel.app. The same story is posted as a pull request comment — a single one, updated on every preview — if the GitHub App has the Pull requests: Read and write permission; without it, only the Check is posted. It follows the production setting Require a green deploy / Only block on the payment pages (block a merge): without that, a broken social card on a preview blocked the merge of a team set to only block on money. - On the preview's page: the visual before / after against production.
What triggers an alert
Nothing, as long as Alert on failing previews is off. Once enabled, a URL failing on the preview goes out on your channels like an outage, with the project name prefixed “Preview — Acme”. The same silence rules apply (rules). No incident is opened and nothing is deduplicated from one preview to the next: 2 pushes on the same branch make 2 messages.
Limits and plans
| Discover | Pro | Pro Plus | |
|---|---|---|---|
| Preview checks | Yes | Yes | Yes |
| GitHub Check on the preview | Yes | Yes | Yes |
| Visual diff preview against production | No | Yes | Yes |
A preview counts as a full run on the project; it doesn't consume URL quota. See the plans.
Troubleshooting
Why isn't my preview checked?
In order: preview checks aren't enabled (skipped: "preview_checks_disabled"); the preview's address isn't on a recognised host; or your host sent the event without a usable address. The webhook's response, in the host's logs, carries the reason.
Why do all my previews fail on a protected page?
If the page requires a private header, it's sent on the preview as in production. If the preview itself is protected by a password or a host authentication (Vercel Deployment Protection, for instance), PostShip receives a 401: disable that protection for previews, or add it as a private header on the target.
Why does the Check block the pull request when the page that went down isn't important?
You're in Require a green deploy to merge mode. Switch to Only block on the payment pages: the Check turns green, with the title “Preview: 1 pages failing, outside the payment pages” so the information stays visible, and only a payment page still turns it red.
Performance budget
Available on the Pro and Pro Plus plans.
Measure 3 pages with PageSpeed Insights after every deploy, and make the deploy that slows the site down lose points.
A deploy that doubles the bundle weight breaks nothing: every page answers 200. After every production deploy, PostShip asks PageSpeed Insights to load up to 3 of your pages in a real browser, keeps the Lighthouse score and the metrics, and compares them with the previous deploy. If you set a budget, crossing it costs 15 points on the Ship Score and shows in the GitHub Check.
What PostShip measures
For every production deploy received by webhook, once the checks have run:
- Which pages: the first 3 monitored URLs whose check recorded a
title, in the order of the project's targets (the one they were added in). Atitleproves it's an HTML page — measuring a sitemap would make no sense — and the fixed order allows comparing from one deploy to the next. 3 and not 50: each call runs a Chrome at Google for about 10 seconds. - How: the PageSpeed Insights v5 API, mobile strategy, performance category. Mobile because that's where Google judges, and where a heavy deploy shows; measuring desktop would reassure wrongly.
- What: the performance score (0–100), the LCP, the CLS, the TBT and the FCP. A single missing metric and the whole measurement is ignored — a gap computed on a missing value read as zero would announce a spectacular improvement at every measurement failure.
- As a bonus: the end-of-load screenshot rendered by Lighthouse, which feeds the visual regression.
Why PageSpeed and not Chrome's field data: the latter is windowed over 28 days and requires 1,000 visits a month. A deploy that breaks performance this morning wouldn't appear there before a month, and never on a young site.
Set it up
Project → Deployments → Settings, Performance budget card, 2 independent and optional fields:
| Field | What it requires | Bounds |
|---|---|---|
| Minimum score (0–100) | The Lighthouse score doesn't go below this value | 0 to 100 |
| Maximum LCP (ms) | The Largest Contentful Paint doesn't exceed this duration | 200 to 60,000 |
Leave both empty (“none”) to measure without ever alerting: the figures stay visible on the deploy page. A project can require only an LCP, or only a score. A budget is a threshold you set yourself: crossing it is a fact, not an opinion.
What you see
On the deploy page (deploy diff), one section per measured page: score, LCP, CLS, TBT, and the gap with the previous deploy when it was measured too. “Not measured” when PageSpeed didn't answer — and never an invented zero.
What triggers an alert
The budget doesn't send a message on your channels. What it does when one of the measured pages crosses it:
- The Ship Score loses 15 points, once whatever the number of pages over — the budget is a project decision, not one per URL, and removing it 3 times would drop the grade to zero for a merely slow site. The displayed reason is “performance budget exceeded”.
- The GitHub Check receives this recomputed score: on Pro Plus, a minimum score then turns the commit red.
An isolated overrun on a preview doesn't count: a preview is measured and compared with production, without budget or grade.
Limits and plans
| Discover | Pro | Pro Plus | |
|---|---|---|---|
| PageSpeed measurement after a deploy | No | Yes | Yes |
| Budget (minimum score, maximum LCP) | No | Yes | Yes |
| Pages measured per deploy | — | 3 | 3 |
The card is folded on Discover with a link to the pricing. Deploys detected by fingerprint aren't measured: only webhooks are. See the plans.
Troubleshooting
Why “not measured” on all my pages?
PageSpeed didn't answer within 45 seconds, refused the URL, or its quota is exhausted for the hour. PostShip doesn't retry: the next deploy will measure again. A page protected by a private header isn't measurable either — PageSpeed doesn't send it.
Why does my score vary by 10 points between 2 identical deploys?
Lighthouse loads the page for real, on a shared machine: the variance is known and normal. Set a budget with some margin (a minimum score at 60 rather than 89), and read the trend over several ships rather than an isolated gap.
Why isn't the measured page the one I wanted?
They are the first 3 HTML pages in the order of the project's URLs, that is in practice the order they were added in. There is no reordering: if a decorative page comes before the product page, delete it and add it again so it goes behind.
Why did the budget lower the score without the GitHub Check turning red?
On Discover and Pro, the score is only informative in the Check; only a check failure turns it red. The minimum score is a Pro Plus promise.
Visual regression
Available on the Pro and Pro Plus plans.
Compare pixel by pixel the capture of each measured page with the previous deploy's, and alert beyond the threshold you choose.
The white page, the CSS that didn't ship, the price block that disappeared: all of that answers 200. After every production deploy, PostShip compares the screenshot of each measured page with the previous deploy's, highlights what changed, and — if you set a threshold — tells you like for an outage when a page no longer looks the same.
What PostShip compares
The capture comes from the PageSpeed measurement: Lighthouse renders an end-of-load image, in mobile, for up to 3 pages per deploy. A single call therefore gives the performance budget and the visual before / after.
- The before is the capture of the same page at the previous production deploy that carries one — PostShip goes back up to 10 deploys, so that a failed measurement doesn't lose the comparison.
- The comparison is made pixel by pixel, with a sensitivity that absorbs JPEG noise and discards anti-aliased edges. 2 captures of different sizes are compared on their common area, and each pixel that exists on one side only counts as changed: a page that grows by 300 px changed by 300 px.
- The result is a ratio of changed pixels, a difference image (the change in red on the greyed page, absent when the rendering is identical), and a sentence: “Identical rendering” under 0.5%, otherwise “Rendering changed by 34% (top of page, middle)”, the zones named from most affected to least affected, “whole page” when all 3 thirds are concerned.
A preview is compared with the last production capture: what the pull request is going to change, before it goes. Without grade or alert.
Set it up
Project → Settings → Monitoring, “What compares” section, Visual regression row, a single setting:
| Choice | What it means |
|---|---|
| Show the diff, never alert | The default. The comparison is visible on the deploy page, nobody is woken |
| Alert beyond 1% of the page | A date that changes, a carousel image |
| Alert beyond 5% of the page | A block that moved |
| Alert beyond 20% of the page | A page that no longer looks the same |
| Alert beyond 50% of the page | A white page or a full-width error |
4 values and not a free field: the percentage only makes sense as an order of magnitude. The threshold is inclusive; a strictly identical rendering never exceeds anything.
Ignored zones
A carousel, a clock, a reviews feed: these zones change on every load without the page having changed, and would ring the threshold on every deploy. On a URL's page, Zones ignored by the visual diff card, draw up to 10 rectangles as a percentage of the capture (x, y, width, height), then Add the zone. A rectangle that overflows is brought back to the edge.
The mask is painted grey on both images before the comparison: 2 identical grey zones don't count, and the grey reads on the difference image as “here, we don't look”. Without a zone: “No ignored zone: the whole capture is compared.”
What you see
On the deploy page (deploy diff), for each measured page: the before capture, the after one, the difference image and the sentence. Captures live in a private storage and follow the plan's retention (data).
What triggers an alert
When at least one production page exceeds the chosen threshold:
- A message goes out on your Discord and Slack channels (channels) and by email if your email alerts are active — not on the outbound webhook: “Acme: a page no longer looks the same since the deploy” — or “2 pages no longer look the same” — with one line per page (“https://www.acme.fr/pricing — Rendering changed by 34% (top of page)”) and the See the before / after link.
- The Ship Score loses 15 points, once whatever the number of pages, reason “rendering changed beyond the threshold”. The GitHub Check receives this score.
Without a threshold, nothing goes out, ever. No incident is opened: the page responds.
Limits and plans
| Discover | Pro | Pro Plus | |
|---|---|---|---|
| Visual comparison after a deploy | No | Yes | Yes |
| Alert threshold and ignored zones | No | Yes | Yes |
| Pages compared per deploy | — | 3 | 3 |
See the plans. Deploys detected by fingerprint aren't captured.
Troubleshooting
Why “nothing to compare” on this deploy?
It's the first measured deploy for this page, or none of the 10 previous ones carries a capture (PageSpeed didn't answer). The next deploy will have a before.
Why does it alert on every deploy when nothing changed?
A zone of the page changes on every load: carousel, counter, ad. Open the difference image, spot the red, and draw an ignored zone over it. If the red is everywhere, a consent banner appears on one capture and not on the other.
Why doesn't the capture look like my site?
Lighthouse captures in mobile, after load, without scrolling or clicking. A page that depends on an interaction is captured in its initial state — stable from one deploy to the next, which is all the comparison needs.
Rollback
Put the last deploy verified good back in production — by hand from Deployments, or on its own when a payment page breaks at release.
A deploy just went through, the payment page no longer responds. PostShip saw it and told you; until now, it stopped there, and you went looking in Vercel for which deploy to put back online — the moment when you pick the wrong row. Rollback makes that move from PostShip, towards the last deploy PostShip verified good, not just the previous one in the host's list.
Vercel only for now, through the integration — not through the hand-pasted webhook, which has no token to talk to Vercel.
By hand
Project → Deployments. The Return to the previous deploy button is always there, at the top of the list and on the page of the deploy in production — red when that deploy broke a check, discreet otherwise: a bug the checks don't see can be undone too. A dialog says which deploy you return to and what happens; you confirm.
Vercel then redeploys the chosen deploy to production: it rebuilds the same commit, and it goes live within a few minutes. The team is told on the channels and the owner by email.
It's an ordinary release: your next push takes its place in production as usual. Until then, a banner says so at the top of Deployments, with the Undo the rollback button: it redeploys the removed deploy the same way.
The rollback always starts from the last production deploy and puts back the most recent one verified good before it. Once done, the button waits for the next deploy. You need to be the project's owner or editor.
On its own
Same page, Automatic rollback card. When enabled, it makes the move without asking when, at release (T+0), a payment page — a journey or a page with assertions — goes down. An SEO check turning red, an ordinary page in 500, a DNS drift: PostShip alerts, but doesn't roll back. Neither do the T+2 and T+8 re-checks: 8 minutes later, an outage can come from elsewhere, and an automatic rollback would do more harm than good.
Disabled by default. Putting an old version back in production is a decision you take once, not one you suffer.
What we return to
The most recent Vercel production deploy, before the one that broke, whose PostShip check was good, and whose URL Vercel still has. If there is none — first tracked deploy, or all the previous ones were already red — PostShip says so and does nothing.
Each deploy is rolled back only once, even if 2 people click, even if the automatic and the manual cross.
What PostShip sends
On the project's Discord and Slack channels (channels) and by email to the owner, a message “Rollback on Acme”: which deploy was withdrawn, which one is back, and whether it was a decision of the project or of a person. A line also appears under the deploy, in Deployments.
Troubleshooting
“Vercel refused: the integration doesn't have permission…”
The rollback goes through the PostShip integration's token. If it was installed with read-only access to deployments, Vercel refuses. Reinstall it from Settings → Integrations, Vercel card, granting access to deployments; the deploy's line keeps the reason, and the button stays available to try again.
“No previous deploy verified good”
PostShip only returns to a deploy it saw pass its checks itself. After the first tracked deploy, there isn't one yet: this time, the rollback happens in Vercel.
The rollback happened, but the page is still red
Vercel switches within seconds; PostShip re-checks on the next run and on the T+2 and T+8 re-checks. If the page stays red, the outage didn't come from the deploy — look at the probable cause and the providers.