HTTP Redirects for SEO in Vue
- Use 301 or 308 redirects for permanent moves. They give Google a strong canonicalization signal
- Prefer HTTP redirects. Google can process JavaScript redirects when rendering succeeds
- Avoid redirect chains: point every old URL straight at its final destination instead of hopping through intermediate pages
- Keep a redirect live for at least a year after a migration so Google's systems see it enough times to treat it as permanent
A 301 redirect tells clients a page has moved permanently. Google uses permanent redirects as a strong canonicalization signal. Missing redirects or unrelated destinations can disrupt a migration.
HTTP redirects run before page JavaScript. A working redirect lets clients reach the new URL. It does not guarantee retained rankings or AI citations.
Use 301 or 308 for permanent moves: site migrations, URL restructuring, domain changes, and deleted pages with a direct replacement. For duplicate content use canonical tags instead. For temporary moves use 302 or 307.
Quick Setup
In a Vue application, implement redirects at your host or server. These Express excerpts require pnpm add express. Register them before your page handler:
import express from 'express'
const app = express()
app.get('/old-page', (req, res) => {
res.redirect(301, '/new-page')
})
app.get('/blog/:slug', (req, res) => {
res.redirect(301, `/articles/${req.params.slug}`)
})// server.ts for Vite SSR
import express from 'express'
const app = express()
app.use((req, res, next) => {
if (req.path === '/old-page') {
return res.redirect(301, '/new-page')
}
if (req.path.startsWith('/blog/')) {
const slug = req.path.replace('/blog/', '')
return res.redirect(301, `/articles/${slug}`)
}
next()
})301 vs 302 Redirects
When to Use Each
301 (Permanent): gives Google a strong signal that the destination should become canonical. Google says permanent redirects do not lose PageRank. Use it for:
- Permanent content moves
- Domain migrations
- URL structure changes
- Deleted pages with direct replacements
- HTTP to HTTPS upgrades
302 (Temporary): signals a temporary move. It does not by itself signal that the target should become canonical. Use it for:
- A/B testing
- Temporary promotions
- Maintenance pages
- Out-of-stock product redirects
If a 302 stays active for months with no plan to revert, switch to a 301: Google treats permanent redirects as a strong canonicalization signal. Temporary redirects provide a weaker signal (Search Central).
307/308: like 302/301 but preserve the HTTP method (a POST stays a POST). Rarely needed for typical SEO work.
How Long to Keep Redirects Active
Google recommends keeping redirects for at least a year so its systems can process the move.
Keep redirects even longer if:
- External sites still link to the old URLs
- Old URLs still receive referral traffic
- High-value pages have many backlinks
Removing a redirect can break old links and interrupt migration processing.
Avoid Redirect Chains
Redirect chains (A → B → C) waste crawl budget and slow page speed; extra requests can delay loading and affect Core Web Vitals, including LCP; TTFB is a separate timing metric. Googlebot follows up to 10 redirect hops by default, then give up. Redirect directly to the final destination:
Bad:
/old → /interim → /finalGood:
/old → /final
/interim → /finalCommon Patterns
Domain Migration
import express from 'express'
const app = express()
app.use((req, res, next) => {
const host = req.get('host')
if (host === 'old-domain.com') {
const source = new URL(req.originalUrl, 'https://old-domain.com')
const target = new URL('https://new-domain.com')
target.pathname = source.pathname
target.search = source.search
return res.redirect(301, target.href)
}
next()
})// server.ts for Vite SSR
import express from 'express'
const app = express()
app.use((req, res, next) => {
const host = req.get('host')
if (host === 'old-domain.com') {
const source = new URL(req.originalUrl, 'https://old-domain.com')
const target = new URL('https://new-domain.com')
target.pathname = source.pathname
target.search = source.search
return res.redirect(301, target.href)
}
next()
})URL Structure Changes
import express from 'express'
const app = express()
app.get('/old', (req, res) => {
res.redirect(301, '/new')
})
app.get('/blog/:slug', (req, res) => {
res.redirect(301, `/articles/${req.params.slug}`)
})
app.get('/products/:id', (req, res) => {
res.redirect(301, `/shop/${req.params.id}`)
})// server.ts for Vite SSR
import express from 'express'
const app = express()
app.use((req, res, next) => {
if (req.path === '/old') {
return res.redirect(301, '/new')
}
if (req.path.startsWith('/blog/')) {
const slug = req.path.replace('/blog/', '')
return res.redirect(301, `/articles/${slug}`)
}
if (req.path.startsWith('/products/')) {
const id = req.path.replace('/products/', '')
return res.redirect(301, `/shop/${id}`)
}
next()
})HTTPS Enforcement
Configure HTTP-to-HTTPS redirects using your fixed public origin. Do not trust arbitrary forwarded headers. See HTTPS enforcement.
WWW Standardization
Choose one public hostname. Configure your host to redirect the other hostname to that fixed origin. Preserve the path and relevant query parameters. Test both variants and reject unexpected hosts.
Testing Redirects
Verify redirects work correctly before deploying:
- Check status code: use browser dev tools Network tab, confirm the intended status: 301 or 308 for permanent moves, 302 or 307 for temporary moves
- Test destination: make sure the redirect points to the correct final URL
- Verify no chains: confirm a single hop to the destination
- Test trailing slashes: check with and without a trailing slash
- Check query parameters: verify parameters carry over if needed
Useful tools:
- Google Search Console: monitor crawl errors and redirect issues
- Browser dev tools Network tab: check status codes and headers
- Screaming Frog: bulk redirect testing and chain detection
- curl:
curl -I https://example.com/old-pageshows redirect headers
Common Mistakes
Redirecting to Irrelevant Pages
Mass-redirecting deleted pages to your homepage sends users and crawlers to unrelated content. Google can treat an unrelated destination as a soft 404. Map each old URL to equivalent content, or return 404/410 when no replacement exists.
import express from 'express'
const app = express()
// Wrong destination: unrelated homepage
app.get('/blog/{*splat}', (req, res) => res.redirect(301, '/'))import express from 'express'
const app = express()
// Map each old URL to relevant replacement content
app.get('/blog/vue-tips', (req, res) => res.redirect(301, '/articles/vue-tips'))
app.get('/blog/seo-guide', (req, res) => res.redirect(301, '/articles/seo-guide'))Redirect Loops
Circular redirects break your site:
import express from 'express'
const app = express()
// Creates infinite loop
app.get('/page-a', (req, res) => res.redirect(301, '/page-b'))
app.get('/page-b', (req, res) => res.redirect(301, '/page-a'))import express from 'express'
const app = express()
// Both redirect to final destination
app.get('/page-a', (req, res) => res.redirect(301, '/final'))
app.get('/page-b', (req, res) => res.redirect(301, '/final'))Client-Side Redirects and Stale Internal Links
Google can process JavaScript redirects after rendering. Rendering failures can prevent discovery of the destination. Prefer HTTP redirects when you control the server: 301 or 308 for permanent moves, 302 or 307 for temporary moves.
Relying on redirects for internal links wastes server resources and slows page speed. Update internal links to point directly at the new URLs, and keep redirects for external links and old bookmarks.
Checklist
- Permanent URL changes use server-side 301 or 308 redirects to relevant replacements
- Redirects run in server middleware (Express, H3, or your framework's equivalent), not client-side JavaScript
- Old URLs redirect directly to their final destination, no chains
- No redirect loops
- Redirects stay active for at least a year after a migration
- Internal links point directly at the new URLs
If you're using Nuxt, Nuxt SEO runs within Nuxt, where you can configure redirects through routeRules. See redirects in Nuxt for the full setup.
Pre-launch setup, post-launch verification, and ongoing monitoring. Interactive checklist with links to every guide.