Redirects & Error Tracking#545
Merged
Merged
Conversation
A 410 status means the resource is permanently gone — it should return a plain 410 response with no Location header. Previously, all response codes (including 410) went through redirect(), which set a Location header. The destination field is also now optional when 410 is selected. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These columns are queried together on every 404 hit (exact match lookup, error recording, uniqueness checks) so they benefit from a composite index as redirect/error counts grow. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a WHERE source LIKE '%*%' clause so only wildcard redirects are loaded into memory, rather than fetching all enabled redirects and filtering in PHP. This keeps the result set small as the total redirect count grows. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move the config check to registration time so the four event listeners aren't attached at all when automatic redirects are disabled, removing the per-handler checks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
410 is semantically different from a redirect — it means the resource is permanently gone, not that it moved somewhere. Keeping it in the redirect manager creates awkward UX (destination field with no destination) and special-case handling. Users who need 410 responses can handle that in their own middleware. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The registration-time guard in the service provider is an optimization, but the subscriber also needs runtime checks so that disabling via config mid-process (e.g. in tests) is respected. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The service provider already guards subscriber registration behind the config check, so the runtime checks and their corresponding tests are unnecessary. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
jackmcdade
approved these changes
Apr 28, 2026
Member
There was a problem hiding this comment.
After a few lang tweaks and removing the 307/308s, all of this is good to go in my book! The "Test Redirect" thing we chatted about in Slack was the only add, but I don't feel like it warrants a "Request changes" status as we could ship without it.
Nice work! 👏
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds redirects to SEO Pro, allowing you to create manual redirects, auto-redirects when slugs change and 404 error tracking.
Redirects
Redirects can be created and managed in the Control Panel under
Tools > SEO Pro > Redirects. Each redirect has a source URL, destination, response code and can be enabled or disabled.You can even use wildcards in your source URLs. Each
*captures a segment, which can be referenced in the destination with$1,$2, etc:/blog/*→ Destination:/articles/$1/blog/*/posts/*→ Destination:/articles/$1/entries/$2Automatic Redirects
When enabled, SEO Pro will automatically create redirects when an entry or term's slug changes. This can be scoped to specific collections or taxonomies in the config.
If a redirect exists for the old URLs, its destination will be updated rather than creating a duplicate.
Error Tracking
When enabled, 404 errors are recorded with hit counts and timestamps. Errors can be viewed from the Control Panel, and each error has a quick link to create a redirect for that URL:
When a redirect is created, the associated error will be automatically deleted.
SEO Pro automatically purges errors older than 30 days via a scheduled command. This threshold can be changed in the
seo-pro.phpconfig file.A dashboard widget is also available to surface recently hit errors.
Multi-site
Redirects and errors are scoped to individual sites.
Source URLs are stored relative to the site root (eg.
/about, not/de/about). The source field uses a custom fieldtype which prepends the site's domain/path as a visual prefix, and strips pasted domains.Listings are automatically filtered to the selected site.
Storage
Redirects and errors are stored as YAML files by default. Redirects live in
content/seo-pro/redirectsand errors instorage/statamic/seopro/errors.Both can optionally be moved to the database by setting
'driver' => 'database'in the config then running the corresponding publish command:php please seo-pro:database-redirectsphp please seo-pro:database-errorsThe commands publish migrations and import existing file-based data. Redirects and errors can use different drivers independently.