Asosiy kontentga o‘tish
Innovialabs

Next.js’da SEO: App Router’da metadata, sitemap va robots

Amaliyot3 daq

Qisqacha

App Router’da SEO kod orqali sozlanadi — sarlavha, canonical va hreflang uchun metadata obyekti yoki generateMetadata, skanerlash uchun sitemap.ts va robots.ts, prevyu uchun opengraph-image; asosiysi — metadataBase orqali absolyut URL va har bir sahifaning o‘z canonical’i.

App Router’da SEO qanday tuzilgan

App Router’da <head> teglarini qo‘lda yozish shart emas. Next.js ularni bir nechta manbadan yig‘adi:

  • metadata — layout.tsx yoki page.tsxdagi statik obyekt;
  • generateMetadata — dinamik sahifalar uchun funksiya;
  • app papkasidagi maxsus fayllar sitemap.ts, robots.ts, opengraph-image.tsx.

Metadata meros qilib olinadi: sahifa yuqoridagi barcha layout’lardan maydonlarni oladi va o‘zinikilari bilan almashtiradi. Bu qulay, ammo quyida keltirilgan xatolarning manbai ham shu.

Layout’dagi asosiy metadata

// app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  metadataBase: new URL('https://example.com'),
  title: { default: 'Kompaniya', template: '%s — Kompaniya' },
  description: 'Sayt haqida qisqa tavsif',
}

metadataBase canonical, hreflang va Open Graph’dagi nisbiy yo‘llarni (/blog/post) absolyut URL’ga aylantiradi. Usiz ijtimoiy tarmoqlardagi prevyu havolalari buzilishi mumkin.

Dinamik sahifalar uchun generateMetadata

// app/blog/[slug]/page.tsx
import type { Metadata } from 'next'

type Props = { params: Promise<{ slug: string }> }

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const { slug } = await params
  const post = await getPost(slug)

  return {
    title: post.title,
    description: post.description,
    alternates: {
      canonical: `/blog/${slug}`,
      languages: {
        uz: `/uz/blog/${slug}`,
        en: `/en/blog/${slug}`,
        'x-default': `/en/blog/${slug}`,
      },
    },
    openGraph: { type: 'article', title: post.title },
  }
}

Next.js’ning yangi versiyalarida params — Promise, shuning uchun uni await qilish kerak. generateMetadata va sahifaning o‘zidagi bir xil parametrli fetch so‘rovlari dedublikatsiya qilinadi, ortiqcha yuk bo‘lmaydi. Mavjud bo‘lmagan slug uchun notFound() chaqiring, shunda server 200 kodli bo‘sh sahifa emas, 404 qaytaradi.

sitemap.ts va robots.ts

// app/sitemap.ts
import type { MetadataRoute } from 'next'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const posts = await getAllPosts()
  return posts.map((p) => ({
    url: `https://example.com/uz/blog/${p.slug}`,
    lastModified: p.updatedAt,
    alternates: {
      languages: { en: `https://example.com/en/blog/${p.slug}` },
    },
  }))
}
// app/robots.ts
import type { MetadataRoute } from 'next'

export default function robots(): MetadataRoute.Robots {
  return {
    rules: { userAgent: '*', allow: '/', disallow: '/admin/' },
    sitemap: 'https://example.com/sitemap.xml',
  }
}

Sitemap’ga faqat 200 kodli kanonik URL’larni qo‘ying. Manzillar bitta fayl limitidan (50 000) ko‘p bo‘lsa, kartani generateSitemaps orqali bo‘ling.

Open Graph rasmlari

Sahifa yonidagi opengraph-image.tsx (yoki .png/.jpg) fayli og:imageni avtomatik qo‘shadi. next/ogdagi ImageResponse yordamida rasmni maqola sarlavhasidan generatsiya qilish mumkin. Tavsiya etilgan o‘lcham — 1200×630.

Sahifalar indekslanmasligiga olib keladigan odatiy xatolar

  • Ildiz layout’dagi canonical. alternates.canonical: '/' barcha sahifalarga meros bo‘lib o‘tadi va ularning hammasi bosh sahifaga ishora qiladi. Canonical’ni har bir sahifada bering.
  • metadataBase yo‘q — nisbiy canonical va og:image noto‘g‘ri yig‘iladi.
  • robots: { index: false } staging’dan qolib ketgan yoki umumiy layout’da berilgan.
  • O‘zaro bo‘lmagan hreflang: o‘zbekcha versiya inglizchaga havola beradi, inglizchasi esa yo‘q. Har bir versiya qolgan barchasini va o‘zini sanab o‘tishi kerak.
  • Sitemap’da redirektlar, 404 va kanonik bo‘lmagan manzillar — robot byudjetni behuda sarflaydi va kartaga kamroq ishonadi.
  • Bo‘sh HTML. Kontent faqat klientda 'use client' va useEffect orqali yuklansa, robot bo‘sh sahifani ko‘rishi mumkin. Asosiy matnni serverda render qiling.
  • Yumshoq 404: «topilmadi» sahifasi notFound() o‘rniga 200 kodini qaytaradi.
  • Slesh bilan nomuvofiqlik: /blog va /blog/ ikkalasi ham redirektsiz ochiladi.
  • Yupqa va takroriy sahifalar: Google minglab deyarli bir xil sahifalarni ko‘pincha skanerlaydi, lekin indekslamaydi.

Natijani qanday tekshirish mumkin

  1. Sahifaning manba kodini oching va <title>, canonical, hreflang, og:imageni toping.
  2. Brauzerda /sitemap.xml va /robots.txtni tekshiring.
  3. Search Console’da URL tekshiruvidan foydalaning: u Google qaysi canonical’ni tanlaganini va kontentni ko‘rayotganini ko‘rsatadi.

Ko‘p beriladigan savollar

Umumiy maydonlar (metadataBase, title shabloni) — layout’da, canonical esa har bir sahifada yoki uning generateMetadatasida. Aks holda canonical meros bo‘lib, ko‘plab sahifalarda bir xil bo‘lib qoladi.

Bunda yordam beramiz

O‘zingiz shug‘ullanmasdan natija olishni istasangiz — biz har kuni shu bilan shug‘ullanamiz.

Loyihani muhokama qilish

Yana o‘qing

G‘oya yoki vazifangiz bormi? Bizga aytib bering

Ish kuni davomida javob beramiz va yechim taklif qilamiz. Konsultatsiya bepul.