SEO تقني · 2026-09-10 · قراءة 10 دقائق

أخطاء الـCanonicalisation في Next.js App Router

الـcanonicalisation مشكلة هوية URL. قد يعرض Next.js الصفحة الصحيحة بينما ترى محركات البحث عدة هويات لنفس المحتوى. حدد سياسة URL واحدة، ولّد metadata من نفس route params، واختبر head النهائي لا مصدر المكوّن فقط.

النطاق: هذا مرجع تنفيذ عملي. راجع توثيق Google والمنصات الحالية قبل اتخاذ قرار إصدار أو سياسة.

ضع سياسة URL واحدة

اختر HTTPS ومضيفًا واحدًا وسياسة trailing slash واحدة وبنية locale واحدة. طبّق redirects على الحافة، ثم اجعل metadataBase وcanonical وsitemap وhreflang والروابط الداخلية متطابقة.

// next.config.js
const nextConfig = {
  trailingSlash: false,
  async redirects() {
    return [{ source: '/:path*', has: [{ type: 'host', value: 'abdallahmekky.com' }], destination: 'https://www.abdallahmekky.com/:path*', permanent: true }]
  },
}

النمط الصحيح لـgenerateMetadata

استخدم نفس lookup للـslug في المحتوى والـmetadata. لا تبنِ canonical من query string غير موثوق، وأعد notFound قبل إصدار metadata لعنصر غير موجود.

import type { Metadata } from 'next'
import { notFound } from 'next/navigation'

export async function generateMetadata({ params }): Promise<Metadata> {
  const { slug } = await params
  const page = await getPageBySlug(slug)
  if (!page) notFound()
  const canonical = new URL('/resources/' + page.slug, SITE_URL)
  return { title: page.title, description: page.description, alternates: { canonical: canonical.toString() } }
}

في المواقع متعددة اللغات استخدم alternates صريحة: `en` و`ar` و`x-default`، ولا تشير إلى ترجمة غير موجودة.

اختبر العقد النهائي

زحف إلى النسخة النهائية مع slash وبدونه، على المضيفين واللغات ومع query parameters. يجب أن ترى URL واحدًا بحالة 200 وcanonical واحدًا ونسخة واحدة في sitemap. canonical مجرد hint، أما redirect والروابط المتضاربة فتضعفه.

curl -sSI https://example.com/guide/
curl -sS https://www.example.com/guide | grep -i 'canonical\|hreflang'

status == 200
canonical == final_url
sitemap_url == canonical