Skip to main content

Overview

The Redirects Manager provides a simple interface to create and manage URL redirects without touching server configuration files. Supports 301 permanent and 302 temporary redirects with wildcard pattern matching.
Proper redirects preserve SEO value when moving or restructuring content, preventing 404 errors and maintaining link equity.

Features

301 & 302 Redirects

Permanent (301) or temporary (302) redirect types

Wildcard Support

Pattern matching with * for flexible redirects

Simple Management

Add, edit, and remove redirects from WordPress admin

Fast Execution

Runs early in WordPress loading for minimal overhead

Redirect Types

Use when: Content has permanently moved to a new URLSEO Impact:
  • Passes 90-99% of link equity to new URL
  • Tells search engines to update their index
  • Should be used for permanent changes
Examples:
  • Site restructure: /old-section/*/new-section/
  • Page rename: /contact-us/contact
  • Domain change: All pages to new domain
Use when: Content is temporarily at a different URLSEO Impact:
  • Does NOT pass link equity
  • Tells search engines the change is temporary
  • Original URL stays in index
Examples:
  • A/B testing different landing pages
  • Seasonal promotions
  • Maintenance pages
  • Limited-time campaigns

Configuration

1

Access Redirect Settings

Navigate to Settings → GEO AI → Redirects & 404
2

Add New Redirect

Click “Add Redirect” button
3

Enter URLs

  • From URL: /old-page (relative path)
  • To URL: /new-page or https://external.com/page
4

Select Type

Choose 301 Permanent or 302 Temporary
5

Save Changes

Click “Save Changes” to activate redirects

Implementation Details

Redirects Class

includes/class-geoai-redirects.php
class GeoAI_Redirects {
    private static $instance = null;

    public static function get_instance() {
        if ( null === self::$instance ) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        add_action( 'template_redirect', array( $this, 'maybe_redirect' ), 1 );
    }

    public function maybe_redirect() {
        if ( is_admin() ) {
            return;
        }

        $redirects    = get_option( 'geoai_redirects', array() );
        $request_path = $_SERVER['REQUEST_URI'];

        foreach ( $redirects as $redirect ) {
            if ( empty( $redirect['from'] ) || empty( $redirect['to'] ) ) {
                continue;
            }

            $from = $redirect['from'];
            $to   = $redirect['to'];
            $type = $redirect['type'] ?? 301;

            if ( $this->matches( $request_path, $from ) ) {
                wp_redirect( $to, $type );
                exit;
            }
        }
    }
}

Pattern Matching

includes/class-geoai-redirects.php
private function matches( $request, $pattern ) {
    $pattern = str_replace( '*', '(.*)', $pattern );
    $pattern = '#^' . $pattern . '$#';
    
    return (bool) preg_match( $pattern, $request );
}

Wildcard Patterns

Use * to match any characters:
From: /blog/*
To:   /articles/

Matches:
✓ /blog/post-1
✓ /blog/post-2  
✓ /blog/category/tech

Redirect Examples

Single Page Redirect

From URLTo URLTypeUse Case
/old-contact/contact301Page renamed
/about-us/about301URL simplified
/sale/black-friday302Temporary promo

Bulk Directory Redirects

From URLTo URLTypeUse Case
/blog/*/articles/301Section renamed
/products/*https://shop.example.com/301Moved to subdomain
/old-site/*/301Site restructure

Protocol Redirects

For HTTPS redirects, use server-level redirects (htaccess, nginx config) for better performance.

External Redirects

From URLTo URLTypeUse Case
/facebookhttps://facebook.com/yourpage301Social shortlink
/youtubehttps://youtube.com/c/yourchannel301Channel shortlink
/docshttps://docs.example.com301External docs site

Admin Interface

The redirects table allows inline editing:
includes/class-geoai-admin.php
private function render_redirects_tab() {
    $redirects = get_option( 'geoai_redirects', array() );
    ?>
    <h2><?php esc_html_e( '301/302 Redirects', 'geo-ai' ); ?></h2>
    <table class="widefat geoai-redirects-table">
        <thead>
            <tr>
                <th><?php esc_html_e( 'From URL', 'geo-ai' ); ?></th>
                <th><?php esc_html_e( 'To URL', 'geo-ai' ); ?></th>
                <th><?php esc_html_e( 'Type', 'geo-ai' ); ?></th>
                <th><?php esc_html_e( 'Actions', 'geo-ai' ); ?></th>
            </tr>
        </thead>
        <tbody id="geoai-redirects-tbody">
            <?php
            if ( ! empty( $redirects ) ) {
                foreach ( $redirects as $index => $redirect ) {
                    ?>
                    <tr>
                        <td>
                            <input type="text" 
                                   name="geoai_redirects[<?php echo esc_attr( $index ); ?>][from]" 
                                   value="<?php echo esc_attr( $redirect['from'] ?? '' ); ?>" 
                                   class="regular-text" 
                                   placeholder="/old-page" />
                        </td>
                        <td>
                            <input type="text" 
                                   name="geoai_redirects[<?php echo esc_attr( $index ); ?>][to]" 
                                   value="<?php echo esc_attr( $redirect['to'] ?? '' ); ?>" 
                                   class="regular-text" 
                                   placeholder="/new-page" />
                        </td>
                        <td>
                            <select name="geoai_redirects[<?php echo esc_attr( $index ); ?>][type]">
                                <option value="301" <?php selected( $redirect['type'] ?? 301, 301 ); ?>>
                                    301 Permanent
                                </option>
                                <option value="302" <?php selected( $redirect['type'] ?? 301, 302 ); ?>>
                                    302 Temporary
                                </option>
                            </select>
                        </td>
                        <td>
                            <button type="button" class="button geoai-remove-redirect">
                                <?php esc_html_e( 'Remove', 'geo-ai' ); ?>
                            </button>
                        </td>
                    </tr>
                    <?php
                }
            }
            ?>
        </tbody>
    </table>
    <p>
        <button type="button" id="geoai-add-redirect" class="button">
            <?php esc_html_e( 'Add Redirect', 'geo-ai' ); ?>
        </button>
    </p>
    <p class="description">
        <?php esc_html_e( 'Use * as wildcard. Example: /blog/* redirects all /blog/ pages.', 'geo-ai' ); ?>
    </p>
    <?php
}

Best Practices

Use 301 for Permanent Changes

Always use 301 redirects when content has permanently moved. This passes SEO value.

Avoid Redirect Chains

Don’t redirect A → B → C. Always redirect directly to the final destination.

Test After Creation

Visit the old URL to verify the redirect works and points to the correct destination.

Update Internal Links

Update links in your content rather than relying on redirects indefinitely.

Monitor 404 Errors

Use the 404 Monitor to identify pages that need redirects.

Document Major Redirects

Keep a record of important redirects, especially during site migrations.

Redirect Chains

Avoid redirect chains. Each additional redirect adds ~200-500ms latency and dilutes SEO value.
Bad:
/old-page → /renamed-page → /final-page
Good:
/old-page → /final-page
/renamed-page → /final-page

Performance Considerations

Early Execution

Redirects run at priority 1 on template_redirect, before most WordPress processing.

Minimal Overhead

Simple array lookup and regex matching. Typically less than 1ms per request.

No Database Queries

Redirects stored in options cache, no additional DB hits.

Exit Early

PHP execution stops immediately after redirect, saving resources.

Server-Level Alternatives

For very high-traffic sites, consider server-level redirects:
.htaccess
# Single redirect
Redirect 301 /old-page /new-page

# Directory redirect
RedirectMatch 301 ^/blog/(.*) /articles/$1

# External redirect  
Redirect 301 /docs https://docs.example.com

Migration Workflow

When migrating or restructuring a site:
1

Audit Current URLs

Export a list of all current page URLs and their traffic
2

Plan New Structure

Map old URLs to new URLs in a spreadsheet
3

Create Redirects

Add all redirects in GEO AI before making changes
4

Test Redirects

Verify each redirect works correctly
5

Make Changes

Update your site structure/URLs
6

Monitor 404s

Check 404 Monitor for any missed redirects
7

Update Sitemaps

Submit updated sitemap to Google Search Console

Programmatic Management

Manage redirects via code:
// Get current redirects
$redirects = get_option( 'geoai_redirects', array() );

// Add new redirect
$redirects[] = array(
    'from' => '/old-page',
    'to'   => '/new-page',
    'type' => 301,
);

// Save
update_option( 'geoai_redirects', $redirects );

Bulk Import

// Import from CSV
$csv_data = array(
    array( '/old-1', '/new-1', 301 ),
    array( '/old-2', '/new-2', 301 ),
    array( '/promo', '/sale', 302 ),
);

$redirects = array();
foreach ( $csv_data as $row ) {
    $redirects[] = array(
        'from' => $row[0],
        'to'   => $row[1],
        'type' => $row[2],
    );
}

update_option( 'geoai_redirects', $redirects );

Troubleshooting

Check:
  • From URL matches exactly (case-sensitive)
  • Include leading slash: /page not page
  • Redirect is saved (click Save Changes)
  • Clear browser cache
  • Test in incognito mode
Cause: Circular redirect (A → B → A)Solution:
  • Check both GEO AI and other redirect sources
  • Verify destination URL is correct
  • Remove conflicting redirects
Common issues:
  • Pattern must match full path: /blog/* not blog/*
  • Use * not % or other wildcards
  • Test pattern with specific examples
Cause: Redirect chain or loopSolution:
  • Remove intermediate redirects
  • Redirect directly to final destination
  • Check server-level redirects (htaccess, nginx)

SEO Impact

Redirect TypeLink Equity PassedIndexing Behavior
301 Permanent~90-99%New URL indexed, old URL removed
302 Temporary0% (minimal)Old URL stays indexed
307 Temporary0% (minimal)Old URL stays indexed
Google treats 301, 302, and 307 similarly now, but 301 is still best practice for permanent moves.

Time to Re-index

After creating 301 redirects:
  • Google discovers redirect: 1-7 days
  • Link equity transfers: 2-4 weeks
  • Old URL drops from index: 4-8 weeks

404 Monitor

Track broken links needing redirects

Sitemaps

Update sitemaps after redirects

Meta Tags

Canonical URLs for duplicate content

Build docs developers (and LLMs) love