WordPress URL redirects and 404 cleanup

Manage 301, 302 and 410 redirects with real hit logs

Set up a redirect manager WordPress sites can rely on: add a redirect from the admin, watch it run before WordPress's own canonical redirect, and see exactly how many times — and when — each one actually fired.

  • 301, 302 and 410 (Gone) support, not just two status codes.
  • Per-redirect hit count, last-hit time and a real access log.
  • Built-in loop protection — refuses a redirect that points at itself.
  • IP addresses are hashed, never stored, in the access log.
Redirect ManagerLive
/old-page→ /new-page
301842 hits
/summer-sale→ /shop
30296 hits
/old-productGone
41012 hits
1,204 hits redirectedRuns before WordPress's own canonical redirect.
Active
Quick answer

Redirect manager WordPress: what does the module actually do?

This is what a redirect manager WordPress sites get with TheOneWP: TOWP_Redirect_Manager stores redirects in a dedicated database table and checks every request against it on template_redirect, before WordPress core's own canonical redirect logic runs. Each redirect can be a 301, a 302, or a 410 (Gone), tracks its own hit count and last-hit time, and logs every access with a hashed IP, a truncated user agent and referer — kept for 90 days. The same save logic other TheOneWP modules use, like Post Type Converter when it bulk-generates redirects, checks for loops and duplicate sources before anything is written.

The moved-URL problem

Changed a URL, and now it's just a 404

Renaming a page, retiring a product, or restructuring a site's URLs leaves every old link — from search results, bookmarks, or other sites — pointing at nothing.

A 404 loses the SEO value the old URL had built up

Search engines that indexed the old address see a dead end unless something tells them where the content actually is now, or that it is intentionally gone.

Without logs, nobody knows if a redirect is even being used

A redirect added once and never checked again gives no way to tell whether it is still catching real traffic or has become dead weight in the list.

A unified WordPress solution

Every redirect, with a number behind it

The module checks incoming requests early, sends the right status code, and keeps a real record of how often each rule actually fires.

Checked before WordPress's own logic

Priority 1 on template_redirect means a configured redirect wins before core's canonical redirect gets a chance to run.

Real hit counts, not a guess

Every fired redirect increments a counter and logs the access, so "is this still used" has an actual answer.

Loops refused at save time

A redirect that would point a URL back at itself is rejected before it is ever written to the database.

Verified feature set

The complete redirect manager WordPress feature set

Every capability below is present in the class, its database schema, or the admin view.

Matching

Path or full URL as the source

Paste a full address and only its path gets extracted and normalized — matching always happens by path.

normalize_path()Domain-agnostic
Tracking

Per-redirect hits and last-hit time

Every match updates a running hit counter and timestamp on the redirect itself, visible right in the list.

hitslast_hit
Logging

90-day access log per redirect

Timestamp, truncated user agent and referer, and a hashed IP — paginated 20 rows at a time, clearable per redirect.

90-day retentionPaginated
Safety

Duplicate and loop protection

Saving refuses a second redirect for a source already in use, and refuses any redirect whose destination is the same on-site location as its source.

duplicate_sourcesame_url
Ordering

Drag-and-drop priority

When more than one rule could apply, reordering the list controls which one is checked, via jQuery UI Sortable.

sort_ordertowp_redirect_reorder
Recommended workflow

Set up a redirect manager WordPress redirect in four steps

Add it, confirm it fires, then use the log to see whether it is actually catching traffic.

01

Enter the old and new URLs

Paste a path or a full URL for "From" — only the path is used to match incoming requests.

02

Choose 301, 302, or 410

Permanent for a URL that moved for good, temporary for a short-term change, or Gone if the content is not coming back.

03

Visit the old URL to confirm it fires

The hit counter and last-hit time update immediately, confirming the rule matched.

04

Check the access log over time

Come back later to see real visits, referers and repeat-visitor patterns from the hashed IPs.

Practical use cases

Where a tracked redirect earns its keep

The module fits any situation where a URL changed and the old address still gets visited.

Site restructures and URL changes

Redirect old category, page or product URLs to their new locations without losing the SEO value they already had.

Discontinued products or offers

Return a 410 for a page that is genuinely gone, rather than a misleading redirect to an unrelated page.

Auditing which old links still get traffic

Use the hit counts and access log to decide which legacy redirects are worth keeping and which have gone quiet.

Operational benefits

Redirects you can actually audit

Every design choice in the verified code favors a real, checkable record over a fire-and-forget rule.

Runs early, every timePriority 1 on template_redirect means the rule is checked before most of WordPress's own routing logic.
Evidence, not assumptionsHit counts and a real access log answer whether a redirect is still needed.
Privacy-conscious loggingIP addresses are salted and hashed before storage — never kept in a form that identifies a visitor directly.
A shared foundation for other modulesPost Type Converter reuses this module's own loop-check and table when it generates redirects in bulk.
Performance behaviour

One indexed lookup, no scheduled cleanup job

The verified implementation keeps the redirect check itself cheap and lets log pruning happen incidentally.

Indexed path lookup

The redirects table carries a key on from_url, so matching an incoming request is a single indexed query, not a table scan.

Probabilistic log pruning

Roughly 1 in 100 redirect hits triggers a delete of log rows older than 90 days — no dedicated cron event, and no cleanup query on every single hit.

Own dedicated tables

Redirects and their logs live in two purpose-built tables, versioned and upgraded automatically rather than sharing a general-purpose options row.

Security implementation

Hashed IPs, safe redirects, guarded input

The code treats both the visitor's data and the destination URL as things to validate, not trust.

01

IP addresses are hashed, not stored

Each logged IP is SHA-256 hashed together with WordPress's own secret salt and truncated to 16 characters before it ever reaches the database.

02

wp_safe_redirect() for the actual redirect

The destination is sent through WordPress's own safe-redirect function, which restricts where a redirect can actually point.

03

manage_options and a nonce on every admin action

Saving, deleting, toggling, reordering and reading logs all check both before touching the database.

04

Loop and duplicate checks before writing

A redirect that would point at itself, or duplicate an existing source, is rejected with a specific error rather than silently saved.

Verified compatibility

A shared redirect API, not just an admin screen

The supplied code exposes a programmatic entry point other TheOneWP modules already call. No compatibility claim beyond the verified implementation is assumed.

Core hook

template_redirect

Priority 1, ahead of WordPress core's own redirect_canonical at priority 10.

Priority 1Core hook
Confirmed usage

Post Type Converter

Calls TOWP_Redirect_Manager::is_same_location() directly when bulk-generating redirects during a post type conversion, and writes into this module's own redirects table.

is_same_location()Shared table
Activation

Plugin activation routine

TOWP_Redirect_Manager::create_tables() runs on plugin activation, so both database tables exist before any module tries to use them.

create_tables()Activation hook
Solution comparison

TheOneWP versus common alternatives

Compare a real redirect manager WordPress implementation with typical dedicated redirect plugins or .htaccess rules.

CapabilityTheOneWP Redirect ManagerOther common solutions
Status codes 301, 302 and 410 (Gone), each handled correctlyOften 301/302 only, with 410 unsupported
Hit tracking Per-redirect counter, last-hit time and a real logMany plugins offer no usage data at all
Loop protection Refused at save time, checked against the actual site host.htaccess rules can create loops silently
Visitor privacy IPs salted and hashed, never stored rawVaries; some plugins log the IP address directly
Execution order Runs before WordPress core's own canonical redirectDepends on hook priority in the specific plugin
Administration One TheOneWP screen, submenu or standaloneMay require a separate plugin and its own settings
Best practices

Keep the redirect list accurate, not just long

A few habits keep redirects useful instead of accumulating indefinitely.

01

Use 410 for content that is truly gone

A 410 tells search engines to stop indexing the URL, which a 301 to an unrelated page does not communicate as clearly.

02

Check hit counts before deleting old redirects

A redirect with zero recent hits may be safe to remove; one still catching traffic after years probably is not.

03

Order overlapping rules deliberately

When more than one redirect could match a request, drag the more specific one above the broader one.

04

Review the access log after a big URL change

A spike in hits on one redirect right after a migration confirms real traffic is following the old links as expected.

Common mistakes

Avoid assumptions the code does not support

The module has a defined, verified scope — a few assumptions outside it cause confusion.

Expecting query strings or wildcards to match

Matching is by exact normalized path. There is no pattern or regex matching, and no special handling of query string parameters in the verified code.

Expecting logs to be kept forever

Entries older than 90 days are eligible for deletion on the next hit that triggers pruning — export anything needed for a longer record.

Expecting the access log to identify a specific visitor

The stored IP hash can distinguish repeat visits from the same address, but it cannot be reversed back into an actual IP address.

Frequently asked questions

Redirect Manager FAQ

These answers come directly from the verified class, its database schema and confirmed cross-module usage.

What redirect types does the module support?

301 (permanent), 302 (temporary), and 410 (Gone). A 410 tells search engines and browsers a page was intentionally and permanently removed, rather than pointing them somewhere else — no destination URL is stored or used for it.

Does a redirect take priority over WordPress's own canonical redirect?

Yes. maybe_redirect() runs on template_redirect at priority 1, specifically before WordPress core's own redirect_canonical callback at priority 10, so a configured redirect is checked first.

Can I paste a full URL as the source instead of just a path?

Yes. If the "From" field starts with http, only its path component is extracted and normalized for matching — the module always matches by path, not by full URL or domain.

What stops me from creating a redirect loop?

save_redirect() checks whether the destination points back at the exact same on-site location as the source, accounting for both relative paths and absolute URLs, and refuses to save a redirect that would loop onto itself.

What gets logged when a redirect fires?

The timestamp, a truncated user agent, a truncated referer, and a hashed IP address — never the IP itself. Each hit also increments that redirect's hit counter and updates its last-hit timestamp.

Is the logged IP address reversible?

Not from the stored value alone. It is SHA-256 hashed together with WordPress's own secret salt and truncated to 16 characters — enough to tell repeat visitors apart without storing an actual IP address.

How long are access logs kept?

90 days. Instead of a scheduled cleanup job, each redirect hit has a 1-in-100 chance of triggering a delete of log rows older than 90 days, which keeps the table bounded without a dedicated cron event.

Do other TheOneWP modules use Redirect Manager?

Yes. Post Type Converter calls its is_same_location() check directly when bulk-generating redirects for URLs that change during a conversion, and the plugin's activation routine creates this module's database tables up front.

Stop guessing which redirects still matter.See the hits, not just the rule.

Use a redirect manager WordPress admins can actually audit: real status codes, real hit counts, and an access log that respects visitor privacy.