Canonical URLs tell search engines which version of a page is the "master" copy when similar content exists at multiple URLs. They're crucial for preventing duplicate content issues and consolidating SEO value.
✅ Good for:
❌ Don't use for:
Add canonical URLs to your Vue pages using Unhead composables:
useHead({
link: [
{
rel: 'canonical',
href: 'https://mysite.com/products/phone'
}
]
})
// Keep sort parameter in canonical
useHead({
link: [
{
rel: 'canonical',
href: `https://mysite.com/products?sort=${sort}`
}
]
})
useHead({
link: [
{
rel: 'canonical',
href: 'https://otherdomain.com/original-article'
}
]
})
For Vue applications, you'll need to install Unhead manually.
A canonical URL is implemented as a link tag in your page's head:
<link rel="canonical" href="https://mysite.com/page">
const { sort, filter, page } = useRoute().query
useHead({
link: [{
rel: 'canonical',
// Only include sort in canonical, remove filter and pagination
href: sort
? `https://mysite.com/products/${category}?sort=${sort}`
: `https://mysite.com/products/${category}`
}]
})
useHead({
link: [{
rel: 'canonical',
// Point all pages to first page
href: 'https://mysite.com/blog'
}]
})
For alternative pagination strategies, see Google's pagination guidelines.
useHead({
link: [{
rel: 'canonical',
// Point mobile site (m.mysite.com) to desktop version
href: `https://mysite.com/products/${id}`
}]
})
Consider using responsive design instead of separate mobile sites. See Google's mobile site guidelines.
useHead({
link: [{
rel: 'canonical',
// Point to original article source
href: article.originalUrl
}]
})
For multilingual sites, combine canonicals with hreflang:
useHead({
link: [
{
rel: 'canonical',
href: 'https://mysite.com/en/page'
},
{
rel: 'alternate',
hreflang: 'fr',
href: 'https://mysite.com/fr/page'
}
]
})
Handle through server redirects rather than canonicals:
// example using Express
app.use((req, res, next) => {
const host = req.get('host')
// Redirect non-www to www
if (!host.startsWith('www.')) {
return res.redirect(301, `https://www.${host}${req.path}`)
}
next()
})
For dynamic routes, ensure canonical URLs are consistent:
export function useCanonical(path: string) {
const siteUrl = import.meta.env.VITE_SITE_URL
return {
link: [{
rel: 'canonical',
href: `${siteUrl}${path}`
}]
}
}
If you're using Nuxt, check out Nuxt SEO which handles much of this automatically.