🔧 Apache .htaccess Implementation

💡 Most Popular Method

.htaccess redirects work on Apache servers and are the most commonly used method for implementing 301 redirects. They're processed at the server level for optimal performance.

📋 Basic Setup Requirements

1

Locate .htaccess File

Find the .htaccess file in your website's root directory (public_html, www, or similar)

2

Create Backup

Always backup your existing .htaccess file before making changes

3

Verify mod_rewrite

Ensure mod_rewrite is enabled on your server (most hosts enable this by default)

4

Test in Staging

Always test redirects in a staging environment before implementing on live site

🎯 Single Page Redirects

The simplest form of redirects for individual pages:

Simple Page Redirects
# Simple page redirect
Redirect 301 /old-page.html /new-page.html

# Multiple page redirects
Redirect 301 /old-about.html /about
Redirect 301 /old-contact.php /contact
Redirect 301 /products/old-item /products/new-item

# Redirect with file extensions
Redirect 301 /old-page.htm /new-page.html

🌐 Domain-Level Redirects

Redirect entire domains while preserving URL structure:

Domain Redirects
# Redirect entire domain to new domain
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/$1 [R=301,L]

# Redirect old domain to specific page on new domain
RewriteEngine On
RewriteCond %{HTTP_HOST} ^(www\.)?olddomain\.com$ [NC]
RewriteRule ^(.*)$ https://newdomain.com/welcome [R=301,L]

🔐 HTTP to HTTPS Redirects

Force secure connections across your entire site:

HTTPS Redirects (Multiple Methods)
# Method 1: Standard HTTPS redirect
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Method 2: Alternative for some servers
RewriteEngine On
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.yourdomain.com/$1 [R=301,L]

# Method 3: For Cloudflare users
RewriteEngine On
RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"'
RewriteRule ^(.*)$ https://yourdomain.com/$1 [L,R=301]

🌍 WWW Canonicalization

Choose between www and non-www versions of your site:

WWW Management
# Redirect www to non-www
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.yourdomain\.com$ [NC]
RewriteRule ^(.*)$ https://yourdomain.com/$1 [R=301,L]

# Redirect non-www to www
RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

📂 Trailing Slash Management

Maintain consistency in URL structure:

Slash Management
# Remove trailing slash
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.+)/$
RewriteRule ^(.*)$ /$1 [R=301,L]

# Add trailing slash
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ /$1/ [L,R=301]

🔄 Pattern-Based Redirects

Use patterns and wildcards for multiple similar redirects:

Advanced Pattern Matching
# Redirect by file extension
RedirectMatch 301 ^(.*)\.html$ /$1.php

# Redirect category structure
RedirectMatch 301 ^/old-category/(.*)$ /new-category/$1

# Redirect with parameters
RewriteEngine On
RewriteCond %{QUERY_STRING} ^id=([0-9]+)$
RewriteRule ^product\.php$ /products/%1? [R=301,L]

# Date-based blog redirects
RedirectMatch 301 ^/([0-9]{4})/([0-9]{2})/(.*)$ /blog/$3

⚠️ Common .htaccess Mistakes

  • Order Matters: Place specific redirects before general rules
  • Infinite Loops: Test redirects to prevent circular redirections
  • Missing Flags: Always use [R=301,L] for permanent redirects
  • Case Sensitivity: Use [NC] flag for case-insensitive matching
  • Special Characters: Escape dots and other regex characters

📄 Complete .htaccess Example

A comprehensive example showing proper order and structure:

Complete .htaccess Configuration
# Complete .htaccess example with multiple redirects
RewriteEngine On

# 1. Force HTTPS first
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# 2. Force www (or remove based on preference)
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ https://www.%{HTTP_HOST}/$1 [R=301,L]

# 3. Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.+)/$
RewriteRule ^(.*)$ /$1 [R=301,L]

# 4. Specific page redirects (before general rules)
Redirect 301 /old-page /new-page
Redirect 301 /old-about /about
Redirect 301 /contact-us /contact

# 5. Category redirects
RedirectMatch 301 ^/old-blog/(.*)$ /blog/$1

# 6. WordPress rules (always last)
# BEGIN WordPress
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress

🌐 Nginx Configuration

⚡ High Performance

Nginx redirects are processed at the server level and are typically faster than .htaccess redirects. Perfect for high-traffic websites.

📍 Simple Page Redirects

Basic Nginx Redirects
# Simple page redirect
location /old-page {
    return 301 /new-page;
}

# Multiple specific redirects
location /old-about {
    return 301 /about;
}

location /old-contact {
    return 301 /contact;
}

# Exact match redirect
location = /old-exact-page {
    return 301 /new-exact-page;
}

🌐 Domain-Level Nginx Redirects

Domain Redirects
# Redirect entire domain
server {
    listen 80;
    server_name olddomain.com www.olddomain.com;
    return 301 https://newdomain.com$request_uri;
}

# Redirect with path preservation
server {
    listen 80;
    listen 443 ssl;
    server_name olddomain.com;
    return 301 https://newdomain.com$request_uri;
}

🔐 HTTPS and WWW Nginx Redirects

HTTPS & WWW Configuration
# Force HTTPS
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

# Force www
server {
    listen 80;
    listen 443 ssl;
    server_name yourdomain.com;
    return 301 https://www.yourdomain.com$request_uri;
}

# Remove www
server {
    listen 80;
    listen 443 ssl;
    server_name www.yourdomain.com;
    return 301 https://yourdomain.com$request_uri;
}

🔄 Pattern-Based Nginx Redirects

Nginx Pattern Matching
# Redirect with regex
location ~ ^/old-category/(.*)$ {
    return 301 /new-category/$1;
}

# Redirect based on file extension
location ~ ^(.*)\.html$ {
    return 301 $1.php;
}

# Complex redirect with conditions
location /products {
    if ($args ~ "^id=([0-9]+)$") {
        set $product_id $1;
        return 301 /products/$product_id;
    }
    return 301 /products/;
}

📄 Complete Nginx Server Block

Complete Nginx Configuration
# Complete nginx configuration example
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://www.yourdomain.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name yourdomain.com;
    return 301 https://www.yourdomain.com$request_uri;
}

server {
    listen 443 ssl http2;
    server_name www.yourdomain.com;
    
    # SSL configuration
    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;
    
    # Specific page redirects
    location /old-page { return 301 /new-page; }
    location /old-about { return 301 /about; }
    
    # Pattern redirects
    location ~ ^/old-blog/(.*)$ {
        return 301 /blog/$1;
    }
    
    # Main site configuration
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    
    # PHP processing
    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

🐘 PHP Implementation

💻 Dynamic Redirects

PHP redirects are useful for dynamic content and when server configuration access is limited. They're processed at the application level.

📜 Basic PHP Redirect Syntax

Simple PHP Redirects
<?php
// Simple 301 redirect
header('HTTP/1.1 301 Moved Permanently');
header('Location: https://newdomain.com/new-page');
exit();
?>

// Alternative shorter syntax
<?php
header('Location: https://newdomain.com/new-page', true, 301);
exit();
?>

🎯 Conditional PHP Redirects

Conditional Redirects
<?php
// Redirect based on specific page
if ($_SERVER['REQUEST_URI'] == '/old-page/') {
    header('Location: https://yourdomain.com/new-page/', true, 301);
    exit();
}

// Redirect based on URL parameter
if (isset($_GET['old_param'])) {
    $new_url = 'https://yourdomain.com/new-page/';
    header('Location: ' . $new_url, true, 301);
    exit();
}

// Multiple redirect conditions
$redirects = [
    '/old-about/' => '/about/',
    '/old-contact/' => '/contact/',
    '/old-services/' => '/services/',
];

$current_uri = $_SERVER['REQUEST_URI'];
if (array_key_exists($current_uri, $redirects)) {
    header('Location: https://yourdomain.com' . $redirects[$current_uri], true, 301);
    exit();
}
?>

🔄 Advanced PHP Redirect System

Dynamic Redirect Manager
<?php
// Advanced redirect system with database or array
class RedirectManager {
    private $redirects = [
        '/old-product-1/' => '/products/new-product-1/',
        '/old-category/' => '/categories/new-category/',
        '/legacy/page/' => '/modern/page/',
    ];
    
    public function handleRedirect() {
        $current_uri = $_SERVER['REQUEST_URI'];
        $current_uri = rtrim($current_uri, '/') . '/'; // Normalize trailing slash
        
        if (isset($this->redirects[$current_uri])) {
            $this->redirect301($this->redirects[$current_uri]);
        }
        
        // Check for pattern matches
        foreach ($this->redirects as $pattern => $destination) {
            if (strpos($pattern, '*') !== false) {
                $regex = str_replace('*', '(.*)', preg_quote($pattern, '/'));
                if (preg_match('/^' . $regex . '$/', $current_uri, $matches)) {
                    $final_url = str_replace('$1', $matches[1], $destination);
                    $this->redirect301($final_url);
                }
            }
        }
    }
    
    private function redirect301($url) {
        header('HTTP/1.1 301 Moved Permanently');
        header('Location: https://yourdomain.com' . $url);
        exit();
    }
}

// Usage
$redirectManager = new RedirectManager();
$redirectManager->handleRedirect();
?>

🌐 WordPress-Specific PHP Redirects

WordPress Functions.php
<?php
// Add to functions.php for WordPress redirects
function custom_redirects() {
    $current_url = $_SERVER['REQUEST_URI'];
    
    // Old blog structure to new structure
    if (preg_match('/^\/(\d{4})\/(\d{2})\/(.+)\/$/', $current_url, $matches)) {
        $year = $matches[1];
        $month = $matches[2];
        $slug = $matches[3];
        wp_redirect(home_url('/blog/' . $slug . '/'), 301);
        exit();
    }
    
    // Specific page redirects
    $redirects = [
        '/old-page/' => '/new-page/',
        '/legacy-contact/' => '/contact/',
    ];
    
    if (array_key_exists($current_url, $redirects)) {
        wp_redirect(home_url($redirects[$current_url]), 301);
        exit();
    }
}
add_action('template_redirect', 'custom_redirects');
?>

🖥️ Server-Level Redirects

🎛️ cPanel Redirect Setup

1

Access cPanel

Navigate to "Domains" → "Redirects"

2

Select Redirect Type

Choose "Permanent (301)"

3

Choose Domain

Select the domain to redirect from

4

Enter Path

Add specific path if redirecting individual pages

5

Set Destination

Enter the complete destination URL

6

Save Settings

Click "Add" to implement the redirect

⚠️ cPanel Limitation

cPanel redirects are added to the end of .htaccess file and may not work properly with WordPress or other CMS systems that have their own rewrite rules.

⚙️ IIS Web.config Redirects

IIS Web.config Configuration
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <!-- Force HTTPS -->
                <rule name="Redirect to HTTPS" stopProcessing="true">
                    <match url="^(.*)$" />
                    <conditions>
                        <add input="{HTTPS}" pattern="^OFF$" />
                    </conditions>
                    <action type="Redirect" url="https://{HTTP_HOST}/{R:1}" 
                            redirectType="Permanent" />
                </rule>
                
                <!-- Remove www -->
                <rule name="Remove WWW" stopProcessing="true">
                    <match url="^(.*)$" />
                    &