Pre-launch testing on a Vercel preview
Draft of 21 October 2026, prepared by AnswerShare. Every test runs on a Vercel preview of your site with the rule in place, before anything reaches production. Vercel's own guidance is to test rewrites on preview deployments before going to production.
Set-up
- Two previews from the same branch point. Preview A has the rule. Preview B is the same commit without the rule, as the control. Your team creates both.
- Pages under test. The five side-by-side pages (three English, two Spanish), plus the home page,
/es-US, one equipment page, one location page, one news page and the rental portal sign-up page.Question for HOLT: Please confirm the final list of pages under test, and add any page your team wants covered.
- User agents. The published user agent of every crawler on the rule's list, plus Chrome (desktop), Safari (iPhone) and Firefox for people, and Googlebot (desktop and smartphone), Googlebot-Image, Google-InspectionTool, Bingbot, Applebot, DuckDuckBot, YandexBot, Baiduspider and PetalBot for search. The exact strings ship with the test script.
- Where we test from. Our evidence server, IP 143.244.215.194. Every request and response is saved with its headers, status, timing and a SHA-256 hash of the body, and you get the full results file.
- Access to the preview. Vercel previews are often protected. Either your team runs our test script, or you give us a protection-bypass value on a call (never by email) for the test window. Our question on which you prefer is in the plan.
- Firewall. Vercel's bot protection may challenge a crawler user agent that arrives from our test server rather than from the crawler's own network. If it does, we ask for a temporary allow rule for 143.244.215.194 on the preview only, or your team runs those tests. Real crawlers in production arrive from their own networks.
Question for HOLT: Is Vercel's bot protection or a firewall rule active on the preview or on www, and can your team add the temporary allow rule?
How "unchanged" is checked
Within one deployment, your pages are byte-identical from request to request when they are served from Vercel's cache. So on Preview A we compare the SHA-256 of the body a search crawler or browser receives with the SHA-256 of the body Chrome receives for the same URL at the same time. They must be equal. Between Preview A and Preview B, file names of scripts and styles can differ because the builds differ, so there we compare the parts that matter: status code, title, main heading, meta description, canonical link, language tags, structured data and visible text, each by hash. For any page not served from cache, where bytes can differ between requests, we use the same parts comparison and say so in the results.
Test matrix
| ID | Test | How | Pass when | Runs it |
|---|---|---|---|---|
| T1 | AI crawlers get the AI version | Every AI user agent on the list, against every page under test, on Preview A. | Status 200; the body equals what our service returns for that page; the response carries Cache-Control: private, no-store. Every name on the list routes. | AnswerShare |
| T2 | People get the live page, unchanged | Chrome, Safari (iPhone) and Firefox against every page, on Preview A and Preview B. | On Preview A, body SHA-256 equals Chrome's for the same URL. Between A and B, every part hash matches. No AnswerShare header on any response. | AnswerShare; HOLT spot-checks from its own network |
| T3 | Search crawlers get the live page, unchanged | Every search user agent above against every page, on Preview A. | Body SHA-256 equals Chrome's for the same URL. Status codes equal Chrome's. | AnswerShare; HOLT spot-checks |
| T4 | The search exclusion wins | A made-up user agent containing both "Googlebot" and "GPTBot". | Gets the live page (hash equals Chrome's). | AnswerShare |
| T5 | Unlisted agents and edge cases | No user agent, an empty user agent, an unknown bot, and "GPTBOT" in capitals. | Each gets the live page. (Capitals are not matched; the rule matches each name as published and in lower case.) | AnswerShare |
| T6 | Status codes | For each user agent class: a page that does not exist, /en-US, a trailing-slash address, and a HEAD request. | AI crawlers get the same status code and redirect target as Chrome for the missing page and every redirect. Redirects run before the rule, so they are unchanged. | AnswerShare |
| T7 | Assets and internal paths are never rewritten | AI user agents against /_next/static/ files, /_next/image, an /api/ path, /favicon.ico, /manifest.webmanifest, an image and a /.well-known/ path. | Body SHA-256 equals Chrome's for each. | AnswerShare |
| T8 | robots.txt and the sitemap are untouched | Chrome, Googlebot and GPTBot against /robots.txt and /sitemap.xml, on Preview A and on production today. | All bodies identical across user agents. Compared with production, robots.txt is identical, and the sitemap differs only where your own build changes it (for example, dates). | AnswerShare |
| T9 | The two new files (rule 2, if kept) | Chrome, Googlebot and GPTBot against /llms.txt and /llms-full.txt. | Status 200, plain text, identical body for every user agent. | AnswerShare |
| T10 | No AI copy is ever cached for visitors | For every page: GPTBot, then Chrome straight after, 20 times; repeated after the page is warm in Vercel's cache. | Chrome always gets the live page (hash equals the control). No AI response is served from Vercel's cache. | AnswerShare |
| T11 | In-app navigation and forms work as today | GPTBot user agent with the RSC header, and with the Next-Action header. Your team submits the quote and portal sign-up forms in a browser on Preview A. | Requests with those headers are not rewritten. Form submissions reach your systems exactly as on Preview B. | AnswerShare (headers); HOLT (forms) |
| T12 | English and Spanish with your language routing in place | AI, browser and search user agents against /, /es-US and the Spanish pages under test. | AI crawlers get the AI version in the right language; browsers and search crawlers get the live page. We record the path our service receives for English pages, because your language routing serves / from /en-US internally, and confirm it maps to the right page. | AnswerShare; HOLT confirms routing |
| T13 | Speed | 50 requests per page for Chrome, Googlebot and GPTBot on Preview A and Preview B, from the same place, at the same time. | Chrome and Googlebot: median time to first byte on A within 10% of B. GPTBot: median time to last byte of the AI version no slower than the live page's, and 95th percentile under 1 second [CONFIRM: thresholds]. | AnswerShare |
| T14 | Fall-back and error cases | (a) GPTBot asks for a page that has no AI version. (b) Our service is made to fail for one test page. (c) A third preview points the rule at an address that refuses connections. (d) A test page on our side that answers only after 10 seconds. | (a) and (b): the crawler gets your live page, status 200, hash equal to Chrome's. (c): the crawler gets Vercel's 502, and browsers and search crawlers are unaffected. (d): result recorded against our time budget. [CONFIRM: time budget] | AnswerShare |
| T15 | No loops | GPTBot with our pass-through header; then (a) above while we watch our service's logs. | The pass-through request gets the live page. Our fall-back fetch reaches your site once and never returns to us. | AnswerShare |
| T16 | Nothing from people reaches us | Our service's logs for the whole test window, compared with the requests we sent. | Every request we received carries an AI user agent from the list. None carries a browser or search user agent. | AnswerShare; log extract shared with HOLT |
| T17 | Your firewall and bot protection still work | Your team reviews Vercel's firewall view for the test window. | Your rules and bot protection saw every request, including the AI-crawler ones, before the rule ran. | HOLT |
| T18 | Revert | On Preview A, remove the rule and redeploy; separately, promote the pre-rule deployment. Then repeat T1 for three pages. | AI crawlers get the live page after each revert. Time to revert is recorded. | HOLT; AnswerShare re-tests |
| T19 | Content updates by webhook | Your deploy step sends a signed test event for one page; we refresh it. | Our log shows the event verified; the refreshed AI page matches the changed live page; our refresh fetch was not rewritten by the rule. | HOLT sends; AnswerShare verifies |
Passing the gate to production
- Every test must pass. A failure in T2, T3, T4, T7, T8, T10 or T11 protects your visitors or search, so any one of them stops the launch until it is fixed and the whole matrix is re-run.
- A failure in T1, T6, T12, T13, T14 or T15 is ours to fix; we fix it and re-run the affected tests.
- The day we enable production, we re-run T1, T2, T3, T7, T8 and T10 against www within the first hour.
- You get the full results file for every run: each request, the user agent, the status, the headers, the timing and the body hash.