Redirect Best Practices Template
A template and guide for implementing redirects correctly during site migrations, URL changes, and content consolidation.
Last updated October 20, 2024
This guide provides templates and best practices for implementing HTTP redirects. Proper redirect implementation preserves SEO value and ensures good user experience.
Types of Redirects
301 Redirect (Permanent)
Use for permanent URL changes:
- Domain migrations
- HTTPS transitions
- Permanent URL structure changes
- Consolidating content
SEO Impact: Passes most link equity to the new URL.
302 Redirect (Temporary)
Use for temporary situations:
- A/B testing
- Site maintenance
- Geographic redirects
- Temporary promotions
SEO Impact: Does not pass link equity; original URL remains indexed.
307 Redirect (Temporary Strict)
Similar to 302 but preserves request method:
- API redirects where POST must remain POST
- Strict HTTP method requirements
308 Redirect (Permanent Strict)
Similar to 301 but preserves request method:
- Permanent API endpoint changes
- When method preservation is critical
Redirect Mapping Template
Use this spreadsheet format for planning:
| Old URL | New URL | Type | Status | Notes |
|---|---|---|---|---|
| /old-page | /new-page | 301 | ✅ Implemented | Direct mapping |
| /product-a | /products/a | 301 | ⏳ Pending | URL restructure |
| /temp-sale | /products | 302 | ✅ Implemented | Temporary promo |
| /removed-page | - | 410 | ⏳ Pending | Intentionally removed |
Implementation Methods
Apache (.htaccess)
# Single page redirect
Redirect 301 /old-page https://example.com/new-page
# Pattern redirect
RedirectMatch 301 ^/blog/(.*)$ https://example.com/articles/$1
# Redirect entire domain
RewriteEngine On
RewriteCond %{HTTP_HOST} ^olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]
# HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Nginx
# Single page redirect
location = /old-page {
return 301 https://example.com/new-page;
}
# Pattern redirect
location ~ ^/blog/(.*)$ {
return 301 https://example.com/articles/$1;
}
# Redirect entire domain
server {
server_name olddomain.com;
return 301 $scheme://newdomain.com$request_uri;
}
# HTTP to HTTPS
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
JavaScript (Client-Side - Use Sparingly)
// Only when server-side isn't possible
window.location.replace('https://example.com/new-page');
Warning: Client-side redirects are not recommended for SEO.
Meta Refresh (Avoid)
<!-- Not recommended - use server redirects instead -->
<meta http-equiv="refresh" content="0;url=https://example.com/new-page">
Redirect Chains and Loops
Identifying Chain Problems
A redirect chain occurs when redirects go through multiple hops:
/page-a → /page-b → /page-c → /final-page
Problems:
- Each hop adds latency
- Link equity diminishes with each hop
- Crawl budget waste
Maximum Recommended Hops
| Hops | Status |
|---|---|
| 1 | ✅ Ideal |
| 2 | ⚠️ Acceptable |
| 3+ | ❌ Needs fixing |
Loop Detection
A redirect loop occurs when redirects create a cycle:
/page-a → /page-b → /page-a (loop!)
Solution: Map all redirects before implementing and verify no circular references.
Testing Redirects
Using cURL
# Follow redirects and show each hop
curl -IL https://example.com/old-page
# Show just status codes
curl -o /dev/null -s -w "%{http_code}\n" https://example.com/old-page
Using SECrawl
- Create a crawl of your site
- Check the Redirects report
- Review the Redirect Chains report
- Fix any chains with 3+ hops
Bulk Testing Script
#!/bin/bash
# test-redirects.sh
while IFS=, read -r old new; do
status=$(curl -o /dev/null -s -w "%{http_code}" -L "$old")
final=$(curl -o /dev/null -s -w "%{url_effective}" -L "$old")
echo "$old -> $final (Status: $status)"
done < redirects.csv
Common Redirect Patterns
WWW to Non-WWW (or vice versa)
# Non-WWW to WWW
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
# WWW to Non-WWW
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
Trailing Slash Normalization
# Remove trailing slashes
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [R=301,L]
# Add trailing slashes
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [R=301,L]
Case Normalization
# Force lowercase URLs
RewriteMap lowercase int:tolower
RewriteCond %{REQUEST_URI} [A-Z]
RewriteRule ^(.*)$ ${lowercase:$1} [R=301,L]
Monitoring Redirect Health
Key Metrics to Track
- Number of redirect chains
- Average chain length
- 404s from old URLs
- Crawl stats in Search Console
Regular Audit Schedule
| Task | Frequency |
|---|---|
| Review redirect chains | Monthly |
| Check for new 404s | Weekly |
| Validate redirect rules | After any change |
| Full redirect audit | Quarterly |
Redirect Cleanup
After redirects have been in place for 1+ year:
- Check if old URLs still receive traffic
- Verify old URLs no longer have valuable backlinks
- Consider removing unnecessary redirects
Note: Keep redirects for high-authority backlinks indefinitely.
Troubleshooting
| Problem | Likely Cause | Solution |
|---|---|---|
| Redirect not working | Rule order issue | Check rule priority |
| Too many redirects | Redirect loop | Map full chain |
| Soft 404s | Wrong redirect target | Verify destinations |
| Mixed content | HTTP redirect to HTTPS issue | Update all resources |
Quick Reference Card
301 = Permanent (pass equity)
302 = Temporary (no equity)
307 = Temporary + preserve method
308 = Permanent + preserve method
410 = Intentionally removed
Remember: Always use server-side redirects. Test thoroughly before and after implementation. Monitor for issues continuously.
Put these strategies into action
Use SECrawl to audit your website and implement these recommendations.
Start Free