ShipworkSite inspection
Checks

Crawlability

PaginationAre paginated pages set up right?Internal searchIs site search eating crawl budget?URL parametersAre parameters creating duplicates?Log analyserWhat does Googlebot actually crawl?Robots builderNeed a robots.txt file?Soft 404sAre pages “not found” but returning 200?JavaScriptCan crawlers see it without running JS?FreshnessIs my site quietly going stale?Robots.txtDoes robots.txt say what I think?

Indexing

Sitemap lastmodAre my sitemap dates valid?SitemapIs my sitemap actually fetchable?IndexingIs Google allowed to index my pages?CanonicalsIs Google indexing the wrong URL?Index signalsDo sitemap and index signals agree?Sitemap generatorNeed a sitemap.xml for my site?Bulk URL statusWhere does each of these URLs really land?Redirect builderNeed the redirect rules?RedirectsAre my URLs answering directly, over HTTPS?

On-page

Keyword ideasWhat are people searching for?SERP previewHow does my page look in Google?Content qualityAre your pages too thin or too alike?Image weightAre images slowing the page?CannibalizationAre pages competing with each other?On-page checkDoes the page use its target phrase?ImagesAre my images accessible and loading?Meta tag builderWhat should my title and share tags say?DuplicatesDo my pages compete for one query?

Links

Orphan pagesWhich pages can no link reach?Link graphHow deep do your pages sit?Anchor textDo links say what they point at?Outbound linksAre external links still alive?Broken linksAre internal links sending visitors nowhere?

Structured data

Rich resultsIs my markup eligible for a rich result?Structured dataIs my product schema valid?Schema coverageDo my key pages carry structured data?Social previewHow does my page look when shared?Schema vs pageDoes markup match the page price?Schema builderNeed valid JSON-LD?

International

Hreflang sitemapDo page and sitemap hreflang agree?HreflangDo my language versions link back?Hreflang builderNeed the hreflang tags?Page DoctorWhy is this page not doing well?Redirect planMy site has dead links — what redirects do I write?Sitemap diffIs anything missing from my sitemap?Robots simulatorWhat does my robots.txt actually block?Can Googlebot?Can Googlebot fetch this URL?
Every error, explainedGuides
Pricing Learn Error guides Run free audit

+1 free check

Welcome to Shipwork

Sign in free and your next check this month is on us.

Continue with GoogleContinue with email

We email you a 6-digit code. No password.

No card needed. Reports and watches follow you to any device.

Nginx 301 redirect examples for pages and URL sections

For one permanently moved path, put an exact-match location in the active server block and return a 301 to the final URL. For a whole section, use a rule that replaces the old prefix while preserving the rest of the path. The examples below cover query strings, rule placement, validation and the common loops that make a small config change disruptive.

Published

Redirect one exact path permanently

Use an exact location when one page has a known replacement. Replace the example host and destination with your real canonical URL. Add the location inside the matching HTTPS server block, not at the top level of the configuration file. These are location fragments for an already configured virtual host, including its existing TLS settings:

location = /old-guide {
    return 301 https://shop.example.test/guides/new-guide;
}

The Nginx location documentation defines the matching rules. The = makes this location an exact path match, so /old-guide is handled without catching paths such as /old-guide/extra. The query string is not part of the path match: a request like /old-guide?ref=mail still matches. If a replacement is permanent, a server-side 301 is a suitable response; if you are testing a temporary change or may restore the old URL, use a temporary redirect until the decision is final. Google treats permanent and temporary redirects differently when selecting a URL for search results. See Google’s redirect guidance.

Absolute destinations make the intended host clear when a request may arrive on several domains. A relative target such as /guides/new-guide is resolved on the current host and scheme; that can be useful for path-only moves, but it will not consolidate a second hostname by itself. Handle HTTP-to-HTTPS or www-to-apex consolidation in a deliberate server block, and check which block actually receives the request.

A redirect rule should describe the desired destination, not merely make the old address stop returning 404. If the replacement is unrelated, keep the removal outcome separate and choose an appropriate 404 or 410 response instead of sending every retired URL to the homepage.

Move a URL prefix and keep the remaining path

For a section migration, replace the leading path segment and carry the suffix into the new section. This hypothetical rule maps /old-catalog/blue-cup to /catalog/blue-cup:

location ^~ /old-catalog/ {
    rewrite ^/old-catalog/(.*)$ /catalog/$1 permanent;
}

The rewrite expression captures everything after /old-catalog/, including nested path segments. Because the replacement does not add a new query string, Nginx carries the original request arguments forward. See the Nginx rewrite module documentation for rewrite and return behavior. The prefix location includes a trailing slash so the rule does not accidentally catch a sibling such as /old-catalogue/. This example also leaves the bare /old-catalog path outside that location. Add a separate exact rule for that address if it should move too.

Keep the destination outside the old prefix. If the replacement path is still matched by a rule that sends it back to the old prefix, clients can bounce between URLs. A redirect chain can also appear when the new path already has a second rule to a third URL. Map each old path directly to the final address; the redirect-chain guide explains how to identify and flatten existing hops.

For many hand-reviewed pairs, prefer exact rules that make each destination visible. A broad pattern is easier to maintain only when the old and new path structures truly match. If a few exceptions exist, place specific rules so their intended match is clear and test each exception along with a normal path from the section.

Decide whether to preserve query strings

Query strings may carry campaign attribution, internal search state, variant selection or no useful information at all. Decide per route family instead of preserving every parameter by reflex. For an exact redirect where you want the original query passed to the destination, make that choice explicit in the return URL:

location = /old-guide {
    return 301 https://shop.example.test/guides/new-guide$is_args$args;
}

$is_args expands to ? when arguments exist, and $args contains those arguments. With no query string, the suffix adds nothing. If the destination should always be clean, omit both variables:

location = /campaign-landing {
    return 301 https://shop.example.test/collections/summer;
}

Do not copy arbitrary user-provided query values into a newly constructed query string without considering encoding and application behavior. If only one known parameter should survive, build and test that case deliberately with the application owner. Analytics tags that are no longer needed can often be dropped; parameters that change the page a customer sees may need explicit handling.

For the prefix rewrite above, Nginx preserves the old request arguments because the replacement does not supply new arguments. Verify this with a request containing a sample parameter. Check both the Location response header and the final page, since a redirect can preserve a value that the destination application then ignores or interprets differently.

Validate the configuration and test the live route

Before reloading Nginx, validate the full configuration with nginx -t. A fragment can be valid in isolation but fail because it is included in the wrong context, conflicts with an existing location or contains a syntax error. Keep a copy of the current configuration and use the service’s normal change process so you can revert if the virtual host stops serving correctly.

Then test the old URL without automatically following redirects. For example:

curl -sS -D - -o /dev/null 'https://shop.example.test/old-guide?ref=mail'

Read the status and Location header. Confirm that the status is 301 and that the destination has the expected host, path and query behavior. Next request the destination directly; it should serve the intended page successfully. Finally, follow the chain once from the old address and confirm it reaches that same final URL without a loop or extra intermediate destination.

A proxy or CDN can cache redirects, and local DNS or host routing can send your test to a different server block than expected. If the response is surprising, compare the origin and public host where you have a safe way to do so, inspect the selected virtual host and review the error log. Do not infer that a rule is active merely because the configuration reload command returned successfully.

After the redirect works, update internal links, canonicals and the sitemap to use the destination directly. Use the bulk URL status checker for a set of old URLs: it reports response codes, redirect hops and final URLs. The redirect generator can format a reviewed list of path pairs into common rule formats; it does not validate your Nginx configuration or decide whether a replacement is relevant.

Find out if this is happening to you

Shipwork can report public redirect hops and final URLs for submitted addresses; it does not validate Nginx configuration files or deploy rules. Free, no account, no signup. Paste your store address.

Generate redirect rules

Questions

Does an Nginx exact location match a query string?
No. The location path is matched separately from the query string, so a request with arguments can still match the exact path. Decide whether those arguments should be kept in the redirect target.
Does a prefix rewrite keep the query string?
When the rewrite replacement does not define new request arguments, Nginx carries the original arguments forward. Test the behavior with a representative query.
Where should I put a location block?
Inside the active server block for the host and port that receive the request. Validate the full configuration and confirm that the request reaches that virtual host.
How do I test the rule without following it?
Request the old URL and inspect its HTTP status and Location header. Then request the target separately and confirm that it serves the intended page.

Keep reading