> For the complete documentation index, see [llms.txt](https://advanced-seo.michaelaerni.ch/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://advanced-seo.michaelaerni.ch/usage/redirects.md).

# Redirects

Create and manage manual and automatic redirects, track broken URLs, and import or export redirects.

{% hint style="info" %}
Redirects require the [Pro edition](/getting-started/editions.md).
{% endhint %}

Advanced SEO sends visitors from old or broken URLs to the right place. If a URL already belongs to published content or another working page, that page is shown instead.

Each redirect belongs to a specific site. In a multi-site setup, the same path can point to a different destination on each site.

## Setup

### Install Command

Run the install command and select **Redirects**:

```shell
php please seo:install
```

The command enables redirects in `config/advanced-seo.php` and installs `spatie/simple-excel` for importing and exporting redirects.

### Manual Setup

Enable redirects directly in your config:

```php
// config/advanced-seo.php
'redirects' => [
    'enabled' => true,
],
```

Redirect handling works without an additional dependency. To also enable importing and exporting, install `spatie/simple-excel`:

```shell
composer require spatie/simple-excel
```

See [Configuration](/usage/configuration.md#redirects) for all available options.

## Automatic Redirects

Advanced SEO can automatically create permanent redirects when the URL of a published entry or taxonomy term changes. Automatic redirects are enabled by default for every collection and taxonomy after the global redirects feature has been enabled.

To change this per content type, open **SEO** in the Control Panel, choose a collection or taxonomy, click **Configure**, and toggle **Enable Redirects**.

Only published content generates automatic redirects. Changing draft, scheduled, or expired entries does not create one.

### How Redirects Are Generated

When a published entry's slug changes, Advanced SEO creates a `301` redirect from its previous path to the entry. Dated collections are also handled when changing the date changes the entry's URL.

The destination is stored as an entry reference rather than a fixed URL. If the entry moves again, every automatic redirect pointing to it continues to resolve to its current URL.

When a taxonomy term's base slug changes, Advanced SEO creates a redirect for every affected site. Older automatic term redirects are repointed directly to the newest path to avoid redirect chains.

Automatic redirects are also maintained when content changes:

* Deleting an entry or term removes automatic redirects that point to it.
* When an entry or term moves back to a previous URL, Advanced SEO removes the conflicting automatic redirect and creates a new redirect from the URL it just left.
* Existing redirects are never overwritten when automatic generation encounters the same source.

### URL Conflicts and Reused Slugs

Live content wins over redirects. Redirect matching only runs after Statamic determines that the request would otherwise return a 404.

For example, renaming `/about` to `/company` creates an automatic redirect from `/about` to the entry. If another published entry later claims `/about`, that entry is served and the automatic redirect is removed.

Manual redirects are treated as deliberate editor decisions and are not deleted when an entry or term claims the same path. They remain stored but do not override live content. If that path returns a 404 again later, the manual redirect becomes active again.

Advanced SEO does not create an automatic redirect when another redirect already exists with the same source and site.

### Limitations

Automatic generation can reliably detect entry slug changes, URL-changing date changes, and base taxonomy term slug changes. It cannot recover the previous URL for every structural or routing change.

Create redirects manually or use the redirect error inbox when URLs change because of:

* Descendant URLs changing because a parent entry was renamed.
* Moving an entry within a structure or collection tree.
* Changing a collection route or mount.
* Changing a non-slug field used as a route token.
* Changing the overridden slug of an individual term localization.

## Creating Redirects

Open **SEO → Redirects** in the Control Panel and select **Create Redirect**.

Each redirect contains:

* **Source** — The site-relative path or pattern to match. On a multi-site installation, a site selector appears beside this field when you have access to more than one site. Use it to choose which site the redirect belongs to.
* **Destination** — A site-relative path, full URL, or published entry.
* **Response Code** — `301`, `302`, or `410`.
* **Preserve Query String** — Whether to append the request's query string to the destination.
* **Description** — An optional internal note.
* **Enabled** — Keep a redirect without making it active.

### Source Patterns

Sources support exact paths, wildcards, and regular expressions:

| Type     | Source                | Destination    | Example Result                    |
| -------- | --------------------- | -------------- | --------------------------------- |
| Exact    | `/old-page`           | `/new-page`    | `/old-page` → `/new-page`         |
| Wildcard | `/blog/*`             | `/articles/$1` | `/blog/hello` → `/articles/hello` |
| Regex    | `#^/products/(\d+)$#` | `/catalog/$1`  | `/products/42` → `/catalog/42`    |

Each `*` wildcard captures one path segment and does not cross a slash. Multiple wildcards are available as `$1`, `$2`, and so on in the destination. Regex capture groups use the same placeholders.

Exact paths and wildcards are case-insensitive. Regex patterns are case-sensitive unless you add a modifier such as `i`. Trailing slashes are normalized, so `/about` and `/about/` match the same exact redirect.

When multiple redirects match, Advanced SEO prefers:

1. An exact path.
2. The most specific wildcard.
3. A regular expression.

{% hint style="warning" %}
Keep regular expressions focused and inexpensive. They are evaluated against unmatched request paths.
{% endhint %}

### Destinations

A destination can be:

* A path such as `/about`, resolved relative to the source site.
* A full URL such as `https://example.com/about`.
* A published entry selected from Statamic's link field.

Entry destinations follow the entry's current URL when its slug, date, route, or site URL changes.

### Response Codes

| Code            | Use                                                                                   |
| --------------- | ------------------------------------------------------------------------------------- |
| `301 Permanent` | The old URL has permanently moved. This is the default.                               |
| `302 Temporary` | The move is temporary and the source URL may return later.                            |
| `410 Gone`      | The resource was deliberately removed and has no replacement. No destination is used. |

### Query Strings

**Preserve Query String** is enabled by default. A request to `/old?utm_source=newsletter` redirects to `/new?utm_source=newsletter`.

If the destination already contains a query string, the request parameters are appended. Query strings are inserted before URL fragments.

## Managing Redirects

The redirect listing shows each redirect's source, destination, response code, status, origin, hit count, and last hit. Origins indicate whether a redirect was created manually, automatically, through an import, or from a redirect error.

Available actions let you:

* Enable or disable redirects.
* Test enabled exact and wildcard redirects.
* Reset hit statistics.
* Delete redirects individually or in bulk.
* Search and filter by site, status, origin, and response code.

Hit recording runs through the queue configured in `redirects.queue`. Disable it with `redirects.hits.enabled` if you don't need usage statistics.

## Redirect Errors

The **SEO → Errors** page is an inbox of frontend paths that returned an unhandled 404. Advanced SEO groups repeated requests by path and site, and records the hit count plus the first and last time each error was seen.

Control Panel routes, API routes, requests other than `GET` and `HEAD`, and paths matched by `redirects.errors.ignore` are not recorded.

From the error listing, you can:

* Create a redirect with the source and site already filled in.
* Open a matching disabled redirect and enable or edit it.
* Delete selected errors.
* Clear all errors for the sites you can access.

Saving an enabled redirect automatically removes every recorded error it handles, including errors covered by a wildcard or regex source.

### Cleanup and Retention

Advanced SEO schedules `seo:prune-redirect-errors` to run daily when redirects and error tracking are enabled. Make sure [Laravel's scheduler](https://laravel.com/docs/12.x/scheduling#running-the-scheduler) is running in production.

The command:

* Deletes errors that have not been seen within `redirects.errors.purge_after_days`.
* Enforces `redirects.errors.max_records`, removing the least-hit and oldest records first.

The defaults retain errors for 30 days and keep up to 1,000 records. See [Redirect Configuration](/usage/configuration.md#redirects) to change these limits or ignore noisy paths.

## Import and Export

Import and export are available when `spatie/simple-excel` is installed. Open **SEO → Redirects** and select **Import / Export**.

### File Format

Imports accept CSV or JSON:

* CSV files require a header row. Header names are normalized to lowercase snake case.
* JSON files must contain an array of objects.

| Column                  | Required           | Default       | Description                                                                                                               |
| ----------------------- | ------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `source`                | Yes                | —             | Exact path, wildcard, or regex.                                                                                           |
| `destination`           | Unless using `410` | —             | Relative path, full URL, or `entry::<id>` reference. CSV files always need the column, but `410` rows may leave it blank. |
| `response_code`         | No                 | `301`         | `301`, `302`, or `410`.                                                                                                   |
| `preserve_query_string` | No                 | `true`        | Whether to forward the query string. Ignored for `410`.                                                                   |
| `site`                  | Multi-site only    | Selected site | The Statamic site handle.                                                                                                 |
| `enabled`               | No                 | `true`        | Whether the redirect is active.                                                                                           |
| `description`           | No                 | Empty         | An internal note.                                                                                                         |

Imported entry references must point to an existing, published entry.

{% tabs %}
{% tab title="CSV" %}

```csv
source,destination,response_code,preserve_query_string,site,enabled,description
/old-page,/new-page,301,true,default,true,Legacy page
/blog/*,/articles/$1,301,true,default,true,
/removed,,410,,default,true,Content removed
```

{% endtab %}

{% tab title="JSON" %}

```json
[
  {
    "source": "/old-page",
    "destination": "/new-page",
    "response_code": 301,
    "preserve_query_string": true,
    "site": "default",
    "enabled": true,
    "description": "Legacy page"
  },
  {
    "source": "/removed",
    "response_code": 410,
    "site": "default"
  }
]
```

{% endtab %}
{% endtabs %}

### Import Behavior

Imports are all-or-nothing. Every row is validated before anything is saved. If one row is invalid, no redirects are imported.

A row with the same source and site as an existing redirect updates that redirect. The imported row completely replaces its editable values, so omitted optional columns reset to their documented defaults rather than preserving old values.

Imported redirects are marked with the `Import` origin. Duplicate source and site combinations within the same file are rejected. Users may only import redirects for sites they are authorized to access.

### Export Behavior

Export redirects as CSV or JSON. You can export all redirects or only redirects matching the listing's current search and filters.

Exports contain the same columns accepted by the importer. Hit statistics, creation dates, and origins are not included. Only redirects from sites the current user can access are exported.
