This phase has one method: crawl staging, crawl production, and diff the two. Checking a few pages by hand finds the failures you thought to look for. A comparison can expose systematic differences you did not anticipate.
Two labels mark evidence boundaries on this page. Documented means the guidance that follows is directly supported by Google's own published documentation, quoted. Recommendation means a threshold, workflow or pass rule that we prescribe and the documentation does not. Statements from Google staff in interviews or podcasts are attributed in the prose rather than tagged - they are first-party, but they are not documentation. Untagged text is ordinary explanation, or a conclusion following from something already labelled.
That distinction matters more here than anywhere else in this cluster. Almost every line below is a pass rule, and a pass rule read as a Google requirement will be defended to an engineering team as though Google had mandated it. Most of them are ours.
Step 1: What Can Actually Reach Your Staging Environment
Staging should be protected - planning called for authentication or IP restriction, and it stays protected until cutover. That decision has a consequence most checklists skip: it puts Google's own testing tools out of reach, and the checks you were counting on may not be runnable.
The two constraints, and the documented way around them
Documented The URL Inspection tool has two requirements that a protected staging host will usually fail. On property scope: The URL must be in the currently opened property.
Google names the way out in the next breath: To test a URL in a property that you don't own, use the appropriate non-owner test, such as the Rich Results test or AMP test.
On reachability: the page must be accessible from the internet without any login requirements.
Google's debug guidance repeats the point plainly: Check that your page isn't protected by robots.txt and doesn't require a login.
Documented Google offers two routes for exactly this situation. Tunnelling: If your URL is behind a firewall, or is hosted on a local computer, you can use a tunnelling solution to expose your page to the testing tool.
Google's debug guidance frames the use case as ours: This can be useful if you want to test a page before making it publicly available on the web, or even as another step in your release process.
And for structured data specifically, the Rich Results Test does not need a URL at all: The code can either be pasted into the tool, or hosted on a live page.
Recommendation Decide which route you are using before the test window opens, because it changes what you can promise the go/no-go meeting:
| Route | What it gets you | Cost |
|---|---|---|
| Your own crawler against protected staging | Everything in the comparison below - status codes, directives, canonicals, metadata, links, structured-data presence, hreflang, assets | None. This is the bulk of the phase. |
| Rich Results Test, code pasted | Validation against Google's requirements for supported rich-result types, without exposing the page | Per-template, manual |
| A tunnel to a staging URL | Google's own rendered output via the Rich Results Test, on any hostname - provided the exposed URL is crawlable. URL Inspection's live test results as well, but only if the exposed URL is inside a property you have verified (see below) | Setup, and a temporarily reachable URL - keep it short-lived and unlinked |
| Defer to post-cutover | Google-rendered checks on the real thing | You launch without them. Legitimate for low-risk templates; state it as an accepted risk rather than an oversight. |
Three requirements, not two, and they do not all apply to both tools
"Use a tunnel" is usually where this advice stops, and it leaves out most of the condition. The requirements are per-tool. Documented:
- Property membership - URL Inspection only.
The URL must be in the currently opened property.
The Rich Results Test does not carry this requirement; Google names it as the non-owner alternative in the sentence quoted above. - Anonymous reachability - both tools. URL Inspection:
the page must be accessible from the internet without any login requirements.
Rich Results Test:Any resources that are behind a firewall or password-protected will not be available to the test.
- Crawlability - Rich Results Test, stated as a bar:
If Google is prevented from crawling the page as part of its regular crawl cycle (for example, is prevented from crawling by a robots.txt rule or noindex directive), the page cannot be tested with this tool.
The third one is the trap in this phase specifically. A tunnelled staging host that keeps its blanket Disallow or its site-wide noindex in place satisfies reachability and still cannot be tested by the Rich Results Test. Google's debug guidance flags the same collision from the other side: some tunneling solutions (not ngrok) automatically protect your temporary public URL with robots.txt, which will prevent you from running Google tests on them.
Recommendation Treat the exposure as a scoped, dated, logged exception rather than a port-forward: a named set of template URLs, crawlable for the test window and returned to the staging default immediately afterwards, unlinked from anywhere, with no indexing requested. If you also want URL Inspection's live test results, put the exposed URL on a controlled hostname inside a property you have verified rather than whatever hostname the tunnelling tool assigns. Record the exception in the same place as the staging-only control inventory, so that the thing you temporarily switched off has a written owner and a written switch-back.
The honest position: a protected staging environment cannot produce Google's rendered output without a tunnel, and cannot produce URL Inspection's live test results without a tunnel and a verified hostname. Neither of those is an indexing verdict - a live test reports what Google finds when it fetches and renders the URL now, not whether the URL will be indexed. If you do neither, the three-artifact comparison described in rendering and indexability runs with two artifacts before launch and completes after it. Say so in the go/no-go rather than implying the check was done.
Step 2: Set Up the Comparison
Recommendation The diff is only as good as its inputs, so make the two crawls comparable before you compare them.
- Crawl production first, while it is still the live site, and keep the export. This is the reference, and it stops existing.
- Crawl staging with the same configuration - same user agent, same rendering mode, same depth and limits, same inclusion rules. A diff between a rendered crawl and an unrendered one is not a diff of the sites.
- Match the URL sets using the redirect map from phase 2, so each staging URL is compared against the production URL it replaces rather than against a similar-looking one. Where URLs are unchanged this is trivial; where they changed, the map is the join key.
- Crawl on the same day where practical, or note the gap. A production crawl from three weeks ago is a comparison against a site that has since changed.
- Authenticate the crawler against protected staging, and confirm it is receiving real pages rather than a login wall - a crawl of 400 identical auth screens will diff cleanly against nothing.
Pass rule: two crawl exports exist, taken with the same configuration, joined on the redirect map, with the date of each recorded.
Step 3: The Comparison, by Class
Each block below is one class of check, with what to compare and the condition for passing. Recommendation The pass rules themselves are ours unless a block says otherwise - set your own thresholds where a percentage appears, and record whichever you choose.
1. Status codes
Compare every mapped URL's staging response against the disposition it was given in phase 2 - mapped, consolidated, retired, unchanged or rule-handled - not against a universal expectation. A retired URL that returns 200 is as much a defect as a mapped URL that returns 404.
Watch specifically for soft 404s. Documented Google's definition: a page that returns a user-friendly 'not found' message but not a 404 HTTP response code.
A staging build that renders a friendly empty state for missing content will produce these in volume, and a crawler reading status codes alone will not see them.
Pass rule: zero unintended non-200 responses across the top URLs by traffic and by referring domains, and zero rows whose observed outcome differs from their recorded disposition.
2. Indexing directives - the highest-consequence check on this page
Work from the staging-only control inventory built during planning: every noindex, X-Robots-Tag header, robots.txt rule, WAF rule and environment flag, each with a removal owner.
Documented Check both forms, because one is invisible in view-source. Google documents the meta tag as <meta name="robots" content="noindex"> and the header form as X-Robots-Tag: noindex in the HTTP response. A header-level block will pass a visual inspection of the HTML and still remove the page.
And a directive interaction worth knowing before you write the launch plan, from the same Google page: For the
noindex rule to be effective, the page or resource must not be blocked by a robots.txt file, and it has to be otherwise accessible to the crawler. If the page is blocked by a robots.txt file or the crawler can't access the page, the crawler will never see the noindex rule, and the page can still appear in search results, for example if other pages link to it.
Pass rule: every staging-only control is present in the inventory with a named owner and a tested removal path. Not "zero noindex tags remaining on staging" - that condition is satisfiable by exposing the environment, which is the opposite of what you want. Removal is verified on production after cutover, in phase 5.
3. Canonicals
Documented Google describes its canonicalization inputs by relative weight - a redirect and a rel="canonical" annotation are each a strong signal
, sitemap inclusion a weak signal
- and warns against contradiction: Don't specify different URLs as canonical for the same page using different canonicalization techniques (for example, don't specify one URL in a sitemap, but a different URL for that same page using rel="canonical").
Compare all applicable signals per mapped URL or template. A migration is a common point at which they diverge, because each is often generated by a different part of the build - but which signals exist depends on the migration. A stable-URL replatform has no legacy redirect target to compare, and an indexable page can legitimately be absent from a sitemap.
Pass rule: the preferred destination is consistent across every signal that applies. Where an old URL redirects, its final target matches the new page's preferred canonical. Where the page appears in a sitemap, the sitemap lists that same preferred canonical. Where the new page emits a rel="canonical", it is self-referential. And where the approved inventory expects a page to declare a canonical - because it is one of a set of alternates or duplicates - that canonical is present, since a page that should declare one and silently does not will otherwise pass every clause above. The absence of a legacy redirect or a sitemap entry is not a failure - a contradiction between signals that do apply is, and so is a missing signal the inventory expected.
4. Content parity
Compare the main content of each template as text, not as layout. The question is whether the new page says the same things, not whether it looks similar.
Illyes, on Google's podcast in February 2023, gave the mechanism for why structural changes matter here: we will try to parse out the main content and understand that that's the centerpiece of the page. And if you change around the structure, you might accidentally change what we parse out as the centerpiece. And eventually, we will relearn it. But momentarily, you might actually messed it up.
Note his hedges - a transitional effect he expects Google to relearn, not a permanent penalty. It is a reason to test parity, not a reason to freeze your HTML.
Pass rule: for each template, the main content present on production is present on staging, and any deliberate difference is recorded as a decision rather than discovered in the diff.
5. Interaction-dependent content
Documented This is a fail condition, not an inspection item. Google: Google won't load content that requires user interactions (for example, swiping, clicking, or typing) to load
, and Don't lazy-load primary content upon user interaction.
Its lazy-loading guidance makes the same point from the other side - the recommended methods don't rely on user actions, such as scrolling or clicking, to load content, which is important as Google Search does not interact with your page
- and viewport-triggered loading is fine: Load content when it's visible in the viewport.
On pagination: Google's crawlers don't "click" buttons and generally don't trigger JavaScript functions that require user actions to update the current page contents
, and When crawling a site to find pages to index, Google generally crawls URLs found in the href attribute of <a> elements.
New tab, accordion and "load more" components are the usual arrivals in a replatform, because they are a design decision rather than a content one.
Pass rule: no critical content and no crawlable link requires a click, swipe or keystroke to enter the rendered HTML. A "load more" control with no underlying <a href> links fails.
6. Titles, descriptions and headings
Compare as a set, not as a sample - template-generated metadata fails by pattern, so one broken rule affects a whole content type at once. Look for empty values, values duplicated across a template, truncation introduced by a new generator, and changes to the heading pattern.
Documented One thing to be careful about when interpreting the results: what you set is not always what appears. Google draws title links from a list of sources including Content in
, the <title> elementsMain visual title shown on the page
, Heading elements, such as
, <h1> elementsContent in
and several others. Snippets work similarly: og:title meta tagsSnippets are primarily created from the page content itself. However, Google sometimes uses the meta description HTML element if it might give users a more accurate description of the page than content taken directly from the page.
So test your source values here, and inspect representative rendered results separately.
Pass rule: across every indexable template, titles, meta descriptions and primary headings are present where expected. Template-wide duplicates, unexpected truncation in the generated source values, and changes to heading count or heading text are reported. Every deliberate change is recorded. Do not use display-pixel or character-length thresholds as a pass rule - record source-value regressions instead.
Recording deliberate title and description changes matters beyond this phase: they are one hypothesis to test if clicks fall while impressions hold after launch, alongside query mix, position, SERP features and Google's own generated title link or snippet. Recording them lets phase 7 test that hypothesis rather than rediscover the change.
7. Structured data
Documented Validity is not the only requirement - the markup has to match the page. Google: Your structured data must be a true representation of the page content.
And on visibility: don't mark up content that is not visible to readers of the page. For example, if the JSON-LD markup describes a performer, the HTML body must describe that same performer.
Failing this has a stated consequence: markup that is not representative of the main content of the page, or is potentially misleading
can keep a page out of rich results, and violations can prevent syntactically correct structured data from being displayed as a rich result in Google Search, or possibly cause it to be marked as spam.
The migration-specific risk is a template that carries its markup across while the content underneath changes - syntactically perfect, and no longer true.
Documented Use the right tool for the right question - Google names two and divides them explicitly. The Rich Results Test is The official Google tool for testing your structured data to see which Google rich results can be generated by the structured data on your page.
The Schema Markup Validator will Validate all Schema.org-based structured data that's embedded in web pages, without Google feature specific warnings.
So: for schema types or properties Google does not report in the Rich Results Test, use the Schema Markup Validator for generic Schema.org validation. Use the Rich Results Test for validation against Google's requirements for supported rich-result types and for feature-specific warnings. "Not reported by the Rich Results Test" is not the same finding as "invalid markup," and treating them alike sends someone to fix what was never broken.
Pass rule: every expected structured-data type is accounted for, and any addition or removal relative to production is recorded as a deliberate change rather than found in the diff. For every retained or added property, confirm it matches content visible on the page. Tool validity alone is not the quality check - no validator can prove the representation requirement above.
8. Hreflang - where locale URLs change
Documented Reciprocity is the requirement that breaks silently: If two pages don't both point to each other, the tags will be ignored.
Each version must also list itself: Each language version must list itself as well as all other language versions.
And x-default covers the remaining case: This value is recommended for specifying the fallback page for users whose language settings don't match any of your site's localized versions.
Google names three delivery methods: HTML, HTTP Headers, Sitemap.
Check which method the new platform uses, because a build that switches method while the old one still emits annotations produces two conflicting sets.
Pass rule: the annotation graph resolves in both directions across the new URLs, every version self-references, and exactly one delivery method is active.
9. Sitemaps
Documented Google: Include the URLs in your sitemap that you want to see in Google's search results.
Limits: All formats limit a single sitemap to 50MB (uncompressed) or 50,000 URLs.
On lastmod: Google uses the <lastmod> value if it's consistently and verifiably (for example by comparing to the last modification of the page) accurate.
Pass rule: generated from the new canonical URLs; no retired URLs, no non-canonical variants, no redirecting URLs; within the size limits; lastmod either accurate or absent.
10. Internal links and navigation
Count the internal links that resolve through a redirect rather than directly. Documented Google's instruction is to Change the internal links on the new site from the old URLs to the new URLs
- redirects are a safety net for external requests, not the mechanism by which your own site should navigate itself.
Search the codebase as well as the crawl: body-copy links, hard-coded CTAs, canonical tags, hreflang annotations, structured-data URL properties, asset paths, email templates and in-app links.
Pass rule: zero internal links to old URLs in navigation and templates; a recorded, accepted count elsewhere.
11. Assets
Documented Assets are on Google's own preparation list: transfer images and downloads (such as PDF documents) that you host. These might already be getting traffic from Google Search or links, and it's useful to tell users and Googlebot about their new location.
Two separate checks: that assets exist at their new paths, and that render-critical CSS and JavaScript are not blocked from crawling. On the second, Google's JavaScript guidance is explicit: Google Search won't render JavaScript from blocked files or on blocked pages.
Pass rule: every asset URL in the production crawl resolves on staging or has a recorded disposition; no render-critical resource is disallowed.
12. Performance - lab, not field
Documented Core Web Vitals thresholds are assessed on real users: RUM data is what Google uses to determine whether a site meets the recommended Core Web Vitals thresholds
, and the field datasets report on their own schedule - PSI and Search Console report the performance observed over the past 28 days, whereas the CrUX dataset and dashboard is broken down by calendar month.
A protected, low-traffic staging host has no representative field data, so there is nothing on staging to compare against a production field baseline. Staging gets lab and synthetic tests, run per template, per device profile, per build - plus load and origin-capacity testing where the move changes hosting.
Pass rule: lab results within an agreed tolerance of the previous build, per template. The production field baseline captured in phase 1 stays untouched and is re-measured after launch. Do not compare a staging lab score with a production field percentile; they are different populations over different windows.
13. Crawler access at the edge
WAF rules, rate limiting and bot management are configured on infrastructure, so they frequently differ between staging and production - which means this check is partly unrunnable on staging and has to repeat at launch.
Documented Cloudflare's own SEO guidance, as one example of a CDN's checklist, asks you to confirm that WAF custom rules, rate limiting rules and bot protection settings are all allowing verified bots.
One consequence worth knowing before launch, because it converts a small problem into a total one - Google's Crawl Stats documentation: Google requests this file frequently, and if the request doesn't return either a valid file (either populated or empty) or a 404 (file does not exist) response, then Google will slow or stop crawling your site until it can get an acceptable robots.txt response.
A robots.txt returning a 500 is worse than a robots.txt that does not exist.
Pass rule: the production edge configuration is reviewed against the CDN's own verified-bot guidance, and robots.txt returns either a valid file or a 404 under fault conditions, never a 5xx.
14. Measurement
Analytics, consent handling and conversion tracking, confirmed working on staging. This is the check that stops a launch-night argument about whether traffic fell or tracking broke.
Documented The declined-consent half of this test has to be written against your consent architecture, because correct behavior differs by mode. In basic consent mode, Google tags are completely blocked from firing
, and when the user doesn't consent, no data is transferred to Google at all, not even the consent status
- so an absence of data is the correct result. In advanced consent mode, Google tags load when a user opens the website or app
, and While consent is denied, the Google tags send cookieless pings.
Do not write this pass rule as "events recorded with consent declined"
That wording fails a correctly-built basic-mode implementation, where no data after refusal is exactly right. Worse, it gives a team under launch pressure a reason to loosen consent controls until the test goes green - turning a QA criterion into a privacy regression. This is the same trap as the staging noindex rule, with higher stakes.
Recommendation Pass rule: with consent accepted - the expected pageview and at least one conversion event are recorded, with the intended identifiers and storage. With consent declined - the observed network, storage and tag behavior matches your configured consent model: basic mode sends no Google measurement data; advanced mode may send consent-state and cookieless pings but must not read or write analytics or advertising cookies. Confirm the default consent state is set before dependent tags run. Test both transitions from equivalent clean browser states, resetting cookies, consent state and relevant browser storage between the accepted and declined runs - one browser state cannot cleanly test both branches once consent has persisted. The expected behavior depends on your consent architecture and the policy that applies to you, so write the specific expectation down before testing rather than deriving it from what you observe.
Step 4: Checks That Apply Only to Some Migrations
Recommendation Run these where the classification from phase 1 calls for them. A framework replatform with stable URLs does not need most of the first group, and forcing it produces acceptance checks that cannot fail.
| Applicable when | Additional checks |
|---|---|
| Public URLs change | Full redirect-map validation against recorded dispositions; internal links updated to final destinations; backlinked URLs manually confirmed; canonical and sitemap regenerated from new URLs |
| Domain or subdomain changes | Verification present on both properties; Change of Address filings prepared for every old-domain variant; both properties readable before cutover |
| Rendering model changes | The three-artifact comparison in phase 3 - with the caveat that its third artifact needs a tunnel or waits until after launch |
| Hosting, CDN or DNS changes | Edge configuration and verified-bot rules; DNS records and TTLs staged; origin capacity tested; old-host shutdown criteria agreed |
| Locale URLs change | Hreflang graph resolution; locale routing tested without cookies and without an Accept-Language header |
Step 5: Go / No-Go
Recommendation The criteria are written during planning and tested here. Two properties make them usable:
- Measurable. "The crawl looks clean" is not a criterion. "Zero unintended non-200 responses across the top 500 URLs by traffic and top 200 by referring domains" is.
- Not satisfiable the wrong way. Before signing off any criterion, ask how a team under deadline pressure could meet the literal wording while making things worse. The staging-
noindexrule in check 2 is the worked example: written carelessly, it rewards exposing the environment.
Record, alongside the decision: which checks were run, which were deferred and why, and which could not run against protected staging. Recommendation A deferred check is an accepted risk with an owner and a date, not an omission - and writing it down is what makes the difference visible if phase 7 ever needs it.
What This Phase Does Not Decide
- The redirect map itself belongs to phase 2; this phase tests it against its recorded dispositions.
- Rendering architecture belongs to phase 3; this phase compares outputs.
- Removing the staging-only controls belongs to phase 5; this phase confirms the inventory is complete and each has a tested removal path.
Sources
Sources:
Google Search Console Help, URL Inspection tool - that the URL must be in the currently opened property and that the non-owner alternative is the Rich Results test or AMP test, the requirement that the page be reachable without a login, and the tunnel option for firewalled pages. Reviewed 28 August 2026; the page carries no publication date.
Google Search Console Help, Rich Results Test - testing a URL or a pasted code snippet; the anonymous-access requirement and the unavailability of firewalled or password-protected resources; and that a page Google is prevented from crawling by a robots.txt rule or noindex directive cannot be tested with the tool. Reviewed 28 August 2026; the page carries no publication date.
Google Search Central, Debug your website pages - the Rich Results Test accepting pasted code or a live page, testing before a page is public, tunnelling for firewalled or local pages, and the login and robots.txt caveat.
Google Search Central, Block Search indexing with noindex - the meta tag and X-Robots-Tag forms, and the requirement that a page be crawlable for the rule to be seen.
Google Search Central, Structured data general guidelines - that markup must be a true representation of page content, the visibility requirement, and the consequences of misleading markup.
Google Search Central, Structured data markup that Google Search supports - the division between the Rich Results Test and the Schema Markup Validator, quoted above.
Google Search Central, How to specify a canonical URL - signal weights and the contradictory-signals warning.
Google Search Central, Build and submit a sitemap - contents, size limits and lastmod.
Google Search Central, Localized versions of your pages - reciprocity, self-reference, x-default and the three delivery methods.
Google Search Central, Mobile-first indexing best practices and Fix lazy-loaded content - content requiring user interaction, and viewport-based loading; Pagination, incremental page loading, and Search - crawlers not clicking buttons, and link discovery through <a href>.
Google Search Central, JavaScript SEO basics - blocked resources not being rendered; Site moves with URL changes - asset transfer and internal-link updating; Page Indexing report - the soft 404 definition.
Google Search Console Help, Crawl Stats report - the consequence of a robots.txt request returning neither a valid file nor a 404. Reviewed 28 August 2026; no publication date shown.
Google Search Central, Influencing your title links in search results - the sources Google draws title links from; and Control your snippets in search results - that snippets are primarily created from page content, with the meta description used sometimes.
web.dev, Getting started with measuring Web Vitals (last updated 9 September 2025) - real-user data as the basis of Core Web Vitals assessment, and the 28-day and calendar-month reporting periods.
Cloudflare, Improve SEO (last updated 20 April 2026) - verified-bot allowances in WAF custom rules, rate limiting rules and bot protection settings.
Google Analytics Help, About consent mode - basic versus advanced behavior when consent is denied. Reviewed 28 August 2026; no publication date shown.
Gary Illyes on main-content parsing - Search Off the Record, episode 56, Google Search Relations, 23 February 2023. A recorded conversation, not documentation.
About the author
Zarko Zivkovic is the founder of CoreAEX, building technical SEO, AEO, and AI-visibility systems for B2B SaaS companies. Connect on LinkedIn.