The Complete URL Redirect Guide: Types, Implementation, and Best Practices
Master URL redirects: 301, 302, 307, 308, meta refresh, and JS redirects. Server configs, CMS examples, best practices, and monitoring.
Last updated: 2026-02-17
What Is a URL Redirect?
A URL redirect sends visitors and search engines from one URL to a different URL. When someone requests the original URL, the server responds with a redirect instruction instead of the page content. The browser then automatically requests the new URL.
Redirects are one of the most fundamental tools in web management. They handle domain migrations, URL restructuring, HTTPS enforcement, vanity URLs, campaign tracking, and dozens of other scenarios. They are also one of the most commonly misconfigured tools, causing SEO damage, redirect loops, and broken user experiences when done wrong.
This guide covers every type of redirect, how to implement each one, when to use each type, and how to keep your redirects healthy over time.
Types of Redirects
HTTP Status Code Redirects
These are the proper, server-side redirects. The server responds with an HTTP status code in the 3xx range and a Location header pointing to the destination URL.
| Code | Name | Type | SEO Behavior | HTTP Method |
|---|---|---|---|---|
| 301 | Moved Permanently | Permanent | Link equity transfers to new URL | May change to GET |
| 302 | Found | Temporary | Original URL stays indexed | May change to GET |
| 307 | Temporary Redirect | Temporary | Same as 302 | Preserved (POST stays POST) |
| 308 | Permanent Redirect | Permanent | Same as 301 | Preserved (POST stays POST) |
301 (Moved Permanently) is the most commonly used redirect. Use it when a URL has permanently changed and will never return to its original location. Search engines transfer link equity to the new URL and eventually de-index the old one.
302 (Found) is for temporary situations. The original URL still has a home; visitors are just being sent elsewhere for now. Search engines keep the original URL indexed and do not transfer link equity.
307 (Temporary Redirect) is functionally identical to 302 but with one technical difference: it guarantees the HTTP method is preserved. A POST request redirected with 307 stays a POST. With 302, the browser may convert it to GET.
308 (Permanent Redirect) is the method-preserving version of 301. Use it for API endpoints where you need to permanently redirect POST, PUT, or DELETE requests without the browser changing them to GET.
Meta Refresh Redirect
A meta refresh is an HTML-level redirect that tells the browser to navigate to a new URL after a specified delay.
<meta http-equiv="refresh" content="0;url=https://example.com/new-page">
The content="0" means redirect immediately (0-second delay).
When to use: Only when you cannot configure server-side redirects. This is common on static hosting platforms or shared hosting where you do not have access to server configuration.
Drawbacks:
- Not a true HTTP redirect, so search engines may not treat it the same as a 301
- The original page loads briefly before the redirect fires
- Does not pass link equity as reliably as a 301
- Can be blocked by browser security settings
JavaScript Redirect
window.location.href = "https://example.com/new-page";
// or
window.location.replace("https://example.com/new-page");
When to use: Almost never for permanent redirects. JavaScript redirects are appropriate for client-side routing in single-page applications or for conditional redirects based on browser capabilities.
Drawbacks:
- Requires JavaScript to be enabled (search engine crawlers may not execute it)
- Slowest redirect type (page loads, JS executes, then redirect fires)
- Not recognized as a proper redirect by search engines
- Does not pass link equity
For any redirect that matters for SEO, use a server-side 301 or 302. Meta refresh and JavaScript redirects are fallbacks for situations where server configuration is not available. They do not reliably transfer link equity or signal permanence to search engines.
Server-Level Implementation
Apache (.htaccess)
Single URL redirect:
Redirect 301 /old-page https://example.com/new-page
Pattern-based redirect (using mod_rewrite):
RewriteEngine On
# Redirect an entire directory
RewriteRule ^old-directory/(.*)$ https://example.com/new-directory/$1 [R=301,L]
# Redirect with query string
RewriteCond %{QUERY_STRING} ^id=123$
RewriteRule ^product\.php$ https://example.com/products/widget? [R=301,L]
Redirect entire domain:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]
Nginx
Single URL redirect:
location = /old-page {
return 301 https://example.com/new-page;
}
Pattern-based redirect:
# Redirect an entire directory
location /old-directory/ {
rewrite ^/old-directory/(.*)$ https://example.com/new-directory/$1 permanent;
}
Redirect entire domain:
server {
listen 80;
listen 443 ssl;
server_name olddomain.com www.olddomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
return 301 https://newdomain.com$request_uri;
}
IIS (web.config)
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect old page" stopProcessing="true">
<match url="^old-page$" />
<action type="Redirect" url="https://example.com/new-page"
redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Node.js (Express)
// Single redirect
app.get('/old-page', (req, res) => {
res.redirect(301, 'https://example.com/new-page');
});
// Pattern redirect
app.get('/old-directory/:slug', (req, res) => {
res.redirect(301, `https://example.com/new-directory/${req.params.slug}`);
});
Monitor every redirect on your site
Site Watcher tracks redirect chains, status codes, and destinations. Know when redirects break, change, or form loops.
CMS-Level Redirects
WordPress
Using a plugin (Redirection, Yoast, Rank Math):
Most WordPress redirect plugins provide a UI for adding redirect rules. They store rules in the database and apply them at the PHP level.
Pros: Easy to manage, no server configuration needed, usually includes logging. Cons: Slightly slower than server-level redirects (WordPress must load before the redirect fires), plugin dependency.
Using functions.php:
function custom_redirects() {
$redirects = [
'/old-page' => '/new-page',
'/legacy-post' => '/updated-post',
];
$request = $_SERVER['REQUEST_URI'];
$path = parse_url($request, PHP_URL_PATH);
if (isset($redirects[$path])) {
wp_redirect(home_url($redirects[$path]), 301);
exit;
}
}
add_action('template_redirect', 'custom_redirects');
Shopify
Shopify has built-in URL redirect management:
- Go to Online Store > Navigation
- Click URL Redirects
- Add the old path and new path
- Shopify automatically creates a 301 redirect
Next.js
// next.config.js
module.exports = {
async redirects() {
return [
{
source: '/old-page',
destination: '/new-page',
permanent: true, // 301
},
{
source: '/blog/:slug',
destination: '/articles/:slug',
permanent: true,
},
];
},
};
When to Use Each Redirect Type
| Scenario | Redirect Type | Why |
|---|---|---|
| Permanently changed a URL | 301 | Transfers link equity, updates index |
| Domain migration | 301 | Permanent move, preserve SEO value |
| HTTP to HTTPS | 301 | Permanent protocol upgrade |
| www to non-www (or vice versa) | 301 | Permanent canonicalization |
| A/B test redirect | 302 | Temporary, original URL stays indexed |
| Maintenance page | 302 | Temporary, site will return |
| Geo-targeted redirect | 302 | User-specific, original URL is canonical |
| API endpoint moved permanently | 308 | Permanent, preserves POST method |
| API temporary reroute | 307 | Temporary, preserves POST method |
Redirect Best Practices
1. Always Use 301 for Permanent Moves
This is the most common mistake: using 302 when you mean 301. Many frameworks default to 302. Always explicitly set 301 when the move is permanent.
2. Redirect to the Final Destination Directly
Never redirect to a URL that itself redirects. This creates redirect chains that waste time, lose link equity, and complicate debugging. Always point to the final canonical URL.
3. Preserve URL Structure When Possible
When restructuring URLs, maintain the path hierarchy and slug where possible. /blog/my-post redirecting to /articles/my-post is cleaner and easier to manage than a completely different path.
4. Keep a Redirect Map
Maintain a spreadsheet, database, or configuration file that documents every redirect:
- Source URL
- Destination URL
- Redirect type (301/302)
- Date added
- Reason
This map is invaluable during audits and when adding new redirects (to check for potential chains).
5. Set an Expiry Policy
Redirects should not live forever. After enough time has passed (6-12 months for most cases), the old URL has been de-indexed and most cached references have expired. Review and prune redirects periodically.
However, for high-authority pages with many backlinks, keep the redirect indefinitely. Those backlinks continue to provide value as long as the redirect is in place.
6. Test Before Deploying
Always test redirect changes in staging or with a local setup before deploying to production. A single typo in a redirect rule can create a loop that takes down your entire site.
7. Handle Query Parameters
Decide whether query parameters should be preserved, stripped, or transformed during redirects.
# Preserve query string (default behavior)
Redirect 301 /old-page https://example.com/new-page
# Strip query string (add ? at end)
RewriteRule ^old-page$ https://example.com/new-page? [R=301,L]
8. Return Proper Status Codes for Deleted Content
If a page is deleted with no equivalent replacement, use a 410 (Gone) status code instead of redirecting to the homepage. A 410 tells search engines the page is intentionally removed, while a homepage redirect signals nothing useful.
Reserve homepage redirects for domains being consolidated. For individual pages, always redirect to the most relevant equivalent page. If no equivalent exists, use a 410 Gone response.
Common Redirect Mistakes
Redirecting Everything to the Homepage
When restructuring a site, teams sometimes redirect all old URLs to the homepage. Google treats this as a soft 404, meaning the redirect provides no SEO benefit. Each old URL should redirect to its most relevant replacement.
Forgetting About Trailing Slashes
/about and /about/ are technically different URLs. If one redirects and the other does not, you have an inconsistency. Choose a convention (with or without trailing slash) and enforce it site-wide.
Not Handling Case Sensitivity
URLs are case-sensitive by specification. /About and /about are different URLs. If your URLs have mixed-case variants in the wild, add redirect rules to normalize to lowercase.
Chaining Through Intermediate URLs
Every time you restructure URLs, update existing redirects to point to the new destination. Do not just add another redirect on top of an existing one.
Ignoring Non-www and Protocol Variants
Your site has at least four URL forms:
http://example.comhttps://example.comhttp://www.example.comhttps://www.example.com
Only one should serve content. The other three should redirect to it with a single 301.
Monitoring Redirect Health
Redirects degrade over time. Destinations change, chains grow, and configuration changes can silently alter redirect behavior. Active monitoring catches these issues.
Status Code Monitoring
Chain Detection
Destination Validation
Loop Detection
Change Alerting
Redirect Audit Workflow
Run this audit quarterly, or after any major site change:
Crawl All Known URLs
Identify Chains and Loops
Check Destination Health
Verify Redirect Types
Update Redirect Map
Set Up Continuous Monitoring
URL redirects are deceptively simple in concept and endlessly complex in practice. The difference between a well-managed redirect strategy and a neglected one is measured in lost rankings, broken links, and frustrated users.
Keep Every Redirect Healthy, Automatically
Site Watcher monitors redirect chains, status codes, SSL, and uptime across all your sites. Catch redirect issues before they affect SEO or users. $39/mo unlimited, free for 3 targets.