چگونه مشکلات رایج سئوی فنی را در وبسایت خود پیدا و برطرف کنیم
فرض کنید یک وبسایت ساختهاید. روی طراحی آن سرمایهگذاری کردهاید، یک دامنه خریدهاید و غیره. اما یک وبسایت فقط چیزی نیست که روی صفحه میبینید. اتفاقات زیادی پشت صحنه رخ میدهد. شما باید درک کنید که...
فرض کنید یک وبسایت ساختهاید. روی طراحی آن سرمایهگذاری کردهاید، یک دامنه خریدهاید و غیره. اما یک وبسایت فقط چیزی نیست که روی صفحه میبینید. اتفاقات زیادی پشت صحنه رخ میدهد. شما باید درک کنید که اینترنت چگونه کار میکند و بهینهسازی موتور جستجو (سئو) چطور عمل میکند.
سرعت نیز بخش کلیدی دیگری از آن است. یک سایت کند میتواند سئوی بسیار ضعیفی داشته باشد، زیرا بیشتر افراد زمان زیادی را برای انتظار جهت بارگذاری یک صفحه تلف نمیکنند، بهخصوص در این روزها.
سرعت سایت یک موضوع شناختهشده است که مشکلات خاص خود را برای بررسی دارد، مانند بزرگترین ترسیم محتوا (LCP)، تغییر چیدمان تجمعی (CLS) و سرعت سرور. اما من آنها را برای مقالهای دیگر کنار میگذارم.
این مقاله درباره مشکلاتی است که مانع از دسترسی موتورهای جستجو به صفحات شما و خواندن آنها میشوند.
به نظر من، سئوی فنی بسیار سختتر از سئوی معمولی است که روی محتوا و کلمات کلیدی تمرکز دارد. بخش فنی معمولاً به دانش یک برنامهنویس نیاز دارد و ممکن است نیازمند تغییراتی باشد که اگر پیشزمینه فنی نداشته باشید، کمی دشوار به نظر برسد.
یک مشکل فنی ممکن است ماهها پنهان بماند، زیرا معمولاً آن را نمیبینید. این یک مشکل طراحی نیست. شما آن را فقط زمانی پیدا میکنید که بررسیهای خاصی را انجام دهید، برای مثال با Google PageSpeed Insights.
در این آموزش، رایجترین آنها را روی یک سایت تمرینی کوچک پیدا کرده و برطرف خواهید کرد. من نمیخواستم از یک وبسایت واقعی استفاده کنم و صاحبان آن را زیر سوال ببرم، بنابراین یک سایت تمرینی ساختم که از قبل این مشکلات در آن وجود دارد.
فهرست مطالب
- پیشنیازها
- سئوی فنی چیست؟
- این مشکلات چقدر در وبسایتهای واقعی رایج هستند؟
- نحوه راهاندازی سایت تمرینی
- نحوه بررسی کد وضعیت HTTP یک صفحه - خطای 404 نرم (Soft 404) چیست؟
- خطای 404 نرم (Soft 404) چیست؟
- نحوه پیدا کردن و رفع زنجیرههای ریدایرکت (Redirect Chains)
- نحوه اطمینان از اینکه robots.txt صفحات مهم را مسدود نکرده است
- نحوه پیدا کردن تگ noindex تصادفی، نحوه بررسی تگ متا روبات (Robots Meta Tag) و نحوه بررسی هدر X-Robots-Tag
- نحوه بررسی تگ متا روبات (Robots Meta Tag)
- نحوه بررسی هدر X-Robots-Tag
- نحوه استفاده صحیح از تگهای کنونیکال (Canonical Tags)
- نحوه رفع عناوین و توضیحات متا گمشده و تکراری
- نحوه قابل خززش کردن لینکها
- نحوه بررسی اینکه آیا محتوای شما برای نمایش به جاوا اسکریپت نیاز دارد یا خیر
- آیا میتوانید یک صفحه را در پنج دقیقه بررسی کنید؟
- نتیجهگیری
پیشنیازها
برای همراهی با این مقاله نیازی نیست یک برنامه نویس باتجربه باشید. به موارد زیر نیاز دارید:
- یک مرورگر وب، مانند کروم، فایرفاکس، اج یا سافاری. در سافاری، ابتدا گزینه Show features for web developers را در مسیر Settings > Advanced فعال کنید.
- یک ترمینال: Terminal در مکاواس، PowerShell در ویندوز، یا هر ترمینال دیگری در لینوکس.
- curl، برنامهای کوچک که صفحات وب را دانلود میکند. این ابزار به همراه مکاواس، بیشتر توزیعهای لینوکس و ویندوز ۱۰ (نسخه ۱۸۰۳ به بعد) و ویندوز ۱۱ ارائه میشود.
- Node.js، برای اجرای سایت تمرینی. این کد با Node.js 26.8 و curl 8.7 تست شده است.
در ویندوز پاورشل، به جای curl از curl.exe استفاده کنید، زیرا در آنجا curl میانبری برای یک دستور دیگر است. عبارت | grep -i "text" را با | Select-String "text" و /dev/null را با NUL جایگزین کنید.
سئوی فنی چیست؟
گوگل برنامههایی به نام خزنده (Crawler) دارد. آنها دائماً اینترنت را برای وبسایتها و صفحات جدید جستجو میکنند. هنگامی که گوگل یک آدرس جدید را کشف میکند، ممکن است صفحه را خزش کرده و محتوای آن (متن، تصاویر و ویدیوها) را پردازش کند.
اگر گوگل تشخیص دهد که صفحه ارزش ایندکس شدن را دارد، ممکن است آن را به یک پایگاه داده بسیار بزرگ از صفحات وب به نام ایندکس اضافه کند. سپس گوگل میتواند صفحات موجود در ایندکس خود را برای نتایج جستجو، زمانی که با جستجوی کاربر مرتبط هستند، در نظر بگیرد. راهنمای گوگل درباره نحوه کارکرد جستجو این سه مرحله را خزش (Crawling)، ایندکسگذاری (Indexing) و ارائه (Serving) مینامد.
بنابراین، خزش شدن تضمینی برای ایندکس شدن نیست و ایندکس شدن نیز جایگاهی را در نتایج تضمین نمیکند. همین راهنما میگوید که گوگل هیچکدام از این سه مرحله را تضمین نمیکند، حتی برای صفحهای که تمام قوانین آن را رعایت کرده باشد.
رفع مشکلات فنی لزوماً باعث نمیشود سایت شما رتبه اول را در گوگل کسب کند. اما شانس شما را برای کسب رتبه بالاتر تقویت میکند، زیرا هر مشکلی که برطرف میکنید، سایت شما را بهتر میکند.
سئوی فنی باید در کنار سئوی معمولی، مانند کلمات کلیدی، بکلینکها، تعامل در شبکههای اجتماعی و غیره، قرار گیرد.
این مشکلات چقدر در وبسایتهای واقعی رایج هستند؟
اعداد زیر از ممیزیهای انجامشده با ابزار سایتسنجی من به دست آمدهاند. هر وبسایت با استفاده از اولین ممیزی خود یک بار شمارش میشود و این دادهها مربوط به ۲۵ اکتبر هستند.
خزشها (Crawls) صفحات زیادی را در یک سایت بررسی میکنند (در اینجا میانگین ۱۰ صفحه است). ممیزیهای تکصفحهای یک صفحه را بررسی میکنند که معمولاً صفحه اصلی است.
| مشکل | میزان شیوع | نمونه |
|---|---|---|
| حداقل یک صفحه بدون تگ کانونیکال (canonical) | ۶۴.۲ درصد از سایتها | ۵۳ سایت خززششده، از اوت ۲۰۲۵ تا اکتبر ۲۰۲۶ |
| دو یا چند صفحه با دقیقاً یک عنوان (title) مشابه | ۶۱.۸ درصد از سایتها | ۳۴ سایت خزششده با دو یا چند صفحه بارگذاریشده |
| حداقل یک صفحه بدون متا دسکریپشن (meta description) | ۴۹.۱ درصد از سایتها | ۵۳ سایت خزششده |
| حداقل یک لینک منتهی به صفحهای که خطای ۴۰۴ برمیگرداند | ۱۸.۹ درصد از سایتها | ۵۳ سایت خزششده |
| صفحهای که بیشتر با جاوا اسکریپت ساخته شده است | ۱۷.۷ درصد از صفحات | ۲۷۷ ممیزی تکصفحهای، از مه تا اکتبر ۲۰۲۶ |
| حداقل یک صفحه بدون عنوان | ۱۳.۲ درصد از سایتها | ۵۳ سایت خزششده |
| لینکی که موتورهای جستجو ممکن است نتوانند آن را دنبال کنند | ۸.۳ درصد از صفحات | ۲۷۸ ممیزی تکصفحهای |
| یک فایل robots.txt دارای خطا یا فایلی که بارگذاری نشده است | ۷.۹ درصد از سایتها | ۲۵۲ ممیزی تکصفحهای، از ژوئیه تا اکتبر ۲۰۲۶ |
| صفحه مسدود شده توسط noindex یا robots.txt | ۴.۸ درصد از صفحات | ۲۵۱ ممیزی تکصفحهای، از ژوئیه تا اکتبر ۲۰۲۶ |
اینها همگی مشکلات فنی هستند، اما وزن و اهمیت یکسانی ندارند. تگهای کانونیکال گمشده در صدر قرار دارند، اما گوگل داشتن تگ کانونیکال را الزامی نکرده است؛ بنابراین، صفحهای که فاقد آن است بهخودیخود خراب محسوب نمیشود. همانطور که در بخش کانونیکال خواهید دید، این موضوع زمانی اهمیت پیدا میکند که محتوای یکسان یا بسیار مشابه از طریق بیش از یک URL قابل دسترسی باشد.
عناوین تکراری چیزی است که خودم هم تجربه کردهام: وقتی کد مینویسید، به راحتی ممکن است چنین مواردی را از قلم بیندازید. به همین دلیل است که ابزارهایی برای بررسی این مشکلات وجود دارد.
بیایید تکتک موارد موجود در جدول را بررسی کنیم تا مطمئن شویم همه آنها واضح هستند:
- تگ کانونیکال گمشده: تگ کانونیکال اساساً یکی از دهها تگی است که در بخش <head> کدهای HTML خود قرار میدهید. وقتی دو یا سه صفحه محتوای تقریباً یکسانی دارند، به موتورهای جستجویی مانند گوگل میگوید که کدام URL نسخه اصلی و اولیه است؛ یعنی همان نسخهای که ترجیح میدهید ایندکس شود. البته این تگ اجباری نیست: بدون آن، گوگل خودش نسخه اصلی را انتخاب میکند، بنابراین این موضوع بیشتر برای صفحاتی اهمیت دارد که دارای نسخههای تکراری هستند.
- عناوین تکراری: خیلی راحت ممکن است در نهایت روی دو صفحه عنوان یکسانی داشته باشید. شما عناوین تکراری نمیخواهید، زیرا مفید نیستند و میتوانند گوگل را سردرگم کنند. هر صفحه باید بگوید که موضوعش چیست.
- متا دسکریپشن گمشده: این مورد واقعاً مهم است، زیرا به موتورهای جستجو و همچنین ابزارهای هوش مصنوعی مانند ChatGPT کمک میکند. متا دسکریپشن آمده است تا به طور خلاصه توضیح دهد که صفحه درباره چیست و چه کاربردی دارد. اگر به گوگل بروید و وبسایتی را جستجو کنید، آن را زیر لینک واقعی سایت خواهید دید.
- لینک به یک صفحه ۴۰۴: این اساساً به این معناست که شما یک لینک خراب دارید (شاید لینکی که احتمالاً دیگر از آن استفاده نمیکنید) که به صفحهای اشاره میکند که وجود ندارد. بنابراین هیچ دلیلی وجود ندارد که به چیزی منتهی شود که وجود خارجی ندارد. از آن برای هدایت کاربران به چیزی مشابه یا چیزی که واقعاً وجود دارد استفاده کنید تا لینکهای شما همچنان مرتبط باقی بمانند.
- یک صفحه که عمدتاً با جاوا اسکریپت ساخته شده است: گوگل میتواند جاوا اسکریپت را اجرا کند، بنابراین این مورد به تنهایی مانع از حضور یک صفحه در گوگل نمیشود. اما محتوا تنها پس از بارگذاری و اجرای جاوا اسکریپت ظاهر میشود، که برای بازدیدکنندگان کندتر است و یک مرحله اضافی است که ممکن است با شکست مواجه شود، و همه خزندهها نیز جاوا اسکریپت را اجرا نمیکنند. به همین دلیل است که من رندر سمت سرور (server-side rendering) را برای محتوایی که اهمیت بیشتری دارد، ترجیح میدهم.
- لیگی که موتورهای جستجو نمیتوانند آن را دنبال کنند: این مسئله خیلی بزرگی نیست و واقعاً بستگی به این دارد که لینک به کجا اشاره میکند. اما فرض کنید من یک مقاله بسیار عالی نوشتهام و میخواهم به من کمک کند تا در گوگل رتبه بگیرم. اگر موتورهای جستجو نتوانند لینکِ آن را دنبال کنند، شما تمام این زمان و انرژی را روی مقالهای سرمایهگذاری کردهاید که احتمالاً افراد نسبتاً کمی آن را خواهند دید.
- خطاها در robots.txt: فایل robots.txt اساساً به شما کمک میکند تا با موتورهای جستجو گفتگو کنید. اگر خطاهایی در این فایل وجود داشته باشد، ممکن است مانع از خزیدن موتورهای جستجو در صفحاتی شوید که واقعاً میخواهید در نتایج جستجو حضور داشته باشند.
- صفحهای که توسط noindex یا robots.txt مسدود شده است: اینها دو چیز متفاوت هستند. یک قانون noindex از موتورهای جستجو میخواهد که یک صفحه را از نتایج خود دور نگه دارند، در حالی که یک قانون robots.txt فقط مانع از خزیدن آنها در آن صفحه میشود. شما در ادامه این آموزش بیشتر درباره هر دو و چرایی اهمیت این تفاوت خواهید آموخت.
خطاهای نرم ۴۰۴ (Soft 404)، زنجیرههای هدایت (redirect chains) و تگهای کانونیکال اشتباه در جدول نیستند، زیرا ممیزیها آنها را ثبت نمیکنند.
چگونگی راهاندازی سایت تمرینی
سایت تمرینی یک وبسایت کوچک برای یک فروشگاه کفش خیالی به نام Acme Shoes است. هر صفحه در آن یک مشکل داخلی دارد. نیازی نیست تک تک خطوط کد را بفهمید.
یک پوشه جدید بسازید، فایلی به نام server.js اضافه کنید و این کد را در آن قرار دهید:
// server.js: a tiny practice site with common technical SEO problems built in
const http = require('node:http');
const PORT = 8080;
const BASE = 'http://localhost:' + PORT;
// Builds a simple HTML page. Leave out a field to leave that tag out.
function page({ title, description, canonical, robots, body, script }) {
return [
'<!doctype html>',
'<html lang="en">',
'<head>',
'<meta charset="utf-8">',
title && '<title>' + title + '</title>',
description && '<meta name="description" content="' + description + '">',
canonical && '<link rel="canonical" href="' + BASE + canonical + '">',
robots && '<meta name="robots" content="' + robots + '">',
'</head>',
'<body>',
body,
script && '<script>' + script + '</script>',
'</body>',
'</html>',
]
.filter(Boolean)
.join('\n');
}
const routes = {
'/': {
html: page({
title: 'Acme Shoes: Running Shoes for Every Runner',
description: 'Lightweight running shoes for road and trail, with free returns.',
canonical: '/',
body: [
'<h1>Acme Shoes</h1>',
'<a href="/products/blue-runner">Blue Runner</a>',
'<span onclick="location.href=\'/sale\'">Summer sale</span>',
].join('\n'),
}),
},
// Problem: a vague title and no meta description
'/products/blue-runner': {
html: page({
title: 'Acme Shoes',
canonical: '/products/blue-runner',
body: '<h1>Blue Runner</h1>',
}),
},
// Problem: a missing product that still answers "200 OK" (a soft 404)
'/products/red-runner': {
html: page({
title: 'Acme Shoes',
body: '<h1>Sorry, that product could not be found.</h1>',
}),
},
// Problem: a redirect chain, /old-sale -> /sale-2025 -> /sale
'/old-sale': { redirect: '/sale-2025' },
'/sale-2025': { redirect: '/sale' },
'/sale': {
html: page({
title: 'Summer Sale: Up to 40% Off Running Shoes | Acme Shoes',
description: "Save up to 40% on last season's running shoes until August 31.",
canonical: '/sale',
body: '<h1>Summer sale</h1>',
}),
},
// Problem: a noindex header nobody can see in the page itself
'/about': {
headers: { 'X-Robots-Tag': 'noindex' },
html: page({
title: 'About Acme Shoes',
description: 'How a two-person workshop became a running shoe brand.',
canonical: '/about',
body: '<h1>About us</h1>',
}),
},
// Problem: a canonical tag that points to the home page
'/blog/choosing-trail-shoes': {
html: page({
title: 'How to Choose Trail Running Shoes | Acme Shoes',
description: 'Grip, drop and fit: what to look for in a trail running shoe.',
canonical: '/',
body: '<h1>How to choose trail running shoes</h1>',
}),
},
// Problem: the content only exists after JavaScript runs
'/catalog': {
html: page({
title: 'All Running Shoes | Acme Shoes',
description: 'Browse every Acme running shoe.',
canonical: '/catalog',
body: '<div id="app">Loading...</div>',
script:
"fetch('/api/products').then((r) => r.json()).then((products) => {" +
"document.getElementById('app').innerHTML = products.map((p) => '<h2>' + p + '</h2>').join('');" +
'});',
}),
},
'/api/products': {
type: 'application/json',
html: JSON.stringify(['Blue Runner', 'Trail Grip 2', 'City Glide']),
},
// Problem: "Disallow: /blog" blocks every path that starts with /blog
'/robots.txt': {
type: 'text/plain',
html: 'User-agent: *\nDisallow: /blog\n',
},
};
http
.createServer((req, res) => {
const path = new URL(req.url, BASE).pathname;
const route = routes[path];
if (!route) {
res.writeHead(404, { 'Content-Type': 'text/html; charset=utf-8' });
return res.end(page({ title: 'Page not found', body: '<h1>Page not found</h1>' }));
}
if (route.redirect) {
res.writeHead(301, { Location: route.redirect });
return res.end();
}
res.writeHead(200, {
'Content-Type': (route.type || 'text/html') + '; charset=utf-8',
...route.headers,
});
res.end(route.html);
})
.listen(PORT, () => console.log('Practice site running at ' + BASE));
هر کلید در مسیرها (routes) یک آدرس صفحه است. کامنتهایی که با Problem: شروع میشوند میگویند مشکل هر صفحه چیست.
سرور را از همان پوشه شروع کنید:
node server.js
شما باید این را ببینید:
Practice site running at http://localhost:8080
سرور را در حال اجرا بگذارید و یک ترمینال دوم برای دستورات زیر باز کنید. وقتی server.js را تغییر دادید، سرور را با Ctrl+C متوقف کنید و دوباره آن را شروع کنید.
چگونه کد وضعیت HTTP یک صفحه را بررسی کنیم
به یاد دارم وقتی ساخت وبسایت را شروع کردم، انواع و اقسام چیزهای کوچک را میساختم. من یک توسعهدهنده فولاستک (full stack) هستم و مرتباً آزمایشهایی انجام میدادم.
یک بار در سمت سرور مشکلی داشتم و در تب Network دیدم که یک خطای ۵۰۰ برمیگرداند. بار دیگر یک صفحه را عمداً حذف کردم، چون میخواستم ببینم آیا خطای ۴۰۴ یا مشکلات دیگری دریافت میکنم یا خیر. اگر فقط با سایتی که میسازید بازی کنید، چیزهای زیادی از نتایج آن یاد خواهید گرفت.
کدهای وضعیت HTTP اولین چیزی هستند که یک موتور جستجو میخواند. آنها روش سرور برای صحبت با کلاینت، مانند مرورگر شما هستند. این کدها به پنج بازه تقسیم میشوند: 1xx، 2xx، 3xx، 4xx و 5xx. برای مثال، کد 5xx یک مشکل سمت سرور است و کد 4xx یک مشکل سمت کلاینت است.
۴۰۴ رایجترین خطا است. این یعنی یک صفحه در سایت پیدا نشده است. شما همیشه خطاهای ۴۰۴ را میبینید و راهحل معمولاً این است که به سادگی سایت و لینکهای خود را مدیریت کنید.
کدهایی که در این آموزش خواهید دید عبارتند از:
- 200 OK: صفحه اینجاست.
- 301 Moved Permanently: صفحه در آدرس دیگری قرار دارد.
- 404 Not Found: هیچ صفحهای اینجا وجود ندارد.
طبق مستندات گوگل در مورد کدهای وضعیت HTTP، گوگل URLهایی را که کد 4xx برمیگردانند، ایندکس نمیکند.
برای مشاهده کد وضعیت صفحه اصلی سایت تمرینی، از -I که فقط هدرها را نشان میدهد، و از -s که نوار پیشرفت curl را پنهان میکند، استفاده کنید:
curl -sI http://localhost:8080/
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Date: Sun, 25 Oct 2026 17:42:53 GMT
Connection: keep-alive
Keep-Alive: timeout=5
اکنون آدرسی را درخواست کنید که در مسیرها (routes) نیست، تا ببینید یک خطای ۴۰۴ صحیح چه شکلی است:
curl -sI http://localhost:8080/products/does-not-exist
HTTP/1.1 404 Not Found
Content-Type: text/html; charset=utf-8
Date: Sun, 25 Oct 2026 17:42:53 GMT
Connection: keep-alive
Keep-Alive: timeout=5
در مرورگر، ابزارهای توسعهدهنده (F12، یا Cmd+Option+I در مک) را باز کنید، به تب Network بروید و صفحه را رفرش کنید. ستون Status کد را نشان میدهد.
خطای نرم ۴۰۴ (Soft 404) چیست؟
محصولی را بررسی کنید که فروشگاه دیگر آن را نمیفروشد:
curl -sI http://localhost:8080/products/red-runner
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Date: Sun, 25 Oct 2026 17:42:53 GMT
Connection: keep-alive
Keep-Alive: timeout=5
در مرورگر، همان صفحه میگوید: "متأسفیم، آن محصول پیدا نشد."
یک خطای نرم ۴۰۴ اساساً یک «صفحه پیدا نشد» است، اما سرور همچنان پاسخ 200 را برمیگرداند. این کار گوگل را گیج میکند، زیرا آدرس هنوز وجود دارد، اما محتوای آن دیگر بهروز نیست.
برای اصلاح آن، کاری کنید که صفحات مفقود شده یک خطای واقعی ۴۰۴ برگردانند، که این همان چیزی است که گوگل توصیه میکند. در سایت تمرینی، ورودی '/products/red-runner' را از مسیرها حذف کنید. سپس سرور پاسخ 404 را برمیگرداند.
لینکهای خراب به همان بنبست منتهی میشوند. در دادهها، ۱۸.۹ درصد از ۵۳ سایت خزششده حداقل یک لینک به صفحهای داشتند که خطای ۴۰۴ برمیگرداند.
بنابراین لینکهایی را که به چیز ناموجود منتهی میشوند، رها نکنید. آنها را بهروزرسانی کنید تا به چیزی مشابه، یا به چیزی که واقعاً وجود دارد، منتهی شوند.
اگر صفحه جابهجا شده است، یک ریدایرکت ۳۰۱ از آدرس قدیمی به آدرس جدید اضافه کنید. خطای ۴۰۴ تنها پاسخ درست برای صفحهای است که واقعاً رفته است.
چگونه زنجیرههای ریدایرکت (Redirect Chains) را پیدا و اصلاح کنیم
ریدایرکت اساساً زمانی است که میخواهید یک URL (احتمالاً URLی که دیگر وجود ندارد) را به URL دیگری (که وجود دارد) هدایت کنید. ممکن است یک ریدایرکت تنظیم کنید اگر، برای مثال، دامنه خود را از example-x.com به example-y.com تغییر دهید. شما میخواهید هر کسی که example-x.com را تایپ میکند به طور خودکار به example-y.com هدایت شود.
ریدایرکتها خوب هستند و در صورت استفاده صحیح میتوانند بسیار مفید باشند. کد 301 به این معنی است که صفحه برای همیشه جابهجا شده است. کد 302 به این معنی است که جابهجایی موقتی است. مستندات گوگل در مورد ریدایرکتها توضیح میدهد که با هر کدام چگونه برخورد میکند، و خزندههای آن تا ۱۰ هاب ریدایرکت را دنبال میکنند.
اما زنجیره ریدایرکت زمانی اتفاق میافتد که یک آدرس قدیمی، مانند دامنهای که در گذشته استفاده میکردید، به یک آدرس جدید ریدایرکت شود، و سپس آن یکی دوباره ریدایرکت شود، و دوباره... خودتان ماجرا را میگیرید. چند ریدایرکت مسئله بزرگی نیست، اما پنج، ششش یا هفت ریدایرکت میتواند یک مشکل واقعی باشد.
دستور اول در زیر هر مرحله از زنجیره را نشان میدهد. دومی یک خلاصه یکخطی به شما میدهد.
پارامتر -L را اضافه کنید تا curl ریدایرکتها را دنبال کند:
curl -sIL http://localhost:8080/old-sale
HTTP/1.1 301 Moved Permanently
Location: /sale-2025
Date: Sun, 25 Oct 2026 17:42:53 GMT
Connection: keep-alive
Keep-Alive: timeout=5
HTTP/1.1 301 Moved Permanently
Location: /sale
Date: Sun, 25 Oct 2026 17:42:53 GMT
Connection: keep-alive
Keep-Alive: timeout=5
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Date: Sun, 25 Oct 2026 17:42:53 GMT
Connection: keep-alive
Keep-Alive: timeout=5
مسیر /old-sale به /sale-2025 میرود، که آن هم به /sale میرود. برای دریافت خلاصه یکخطی:
curl -sL -o /dev/null -w "%{num_redirects} redirects, ended at %{url_effective}\n" http://localhost:8080/old-sale
2 redirects, ended at http://localhost:8080/sale
دستور -o /dev/null به curl میگوید که HTML صفحه را جایی ذخیره نکند، تا ترمینال شما پر نشود و فقط خط خلاصه (summary) چاپ شود. دستور -w تعیین میکند که آن خط خلاصه چه چیزی را نشان دهد.
برای رفع این مشکل، آدرس قبلی/اصلی را مستقیماً به صفحه نهایی هدایت کنید:
'/old-sale': { redirect: '/sale' },
سرور را مجدداً راهاندازی کنید و دستور خلاصه را دوباره اجرا کنید. اکنون عبارت 1 redirects را نشان میدهد که در http://localhost:8080/sale پایان یافته است.
چگونه مطمئن شویم که robots.txt صفحات مهم را مسدود نکرده است؟
فایل robots.txt راهی است که سایت به موتورهای جستجویی مانند گوگل (و خزندههای آنها) میگوید اجازه دارند چه چیزی را کاوش کنند و به کجا دسترسی دارند.
به فایل سایت تمرینی نگاه کنید:
curl -s http://localhost:8080/robots.txt
User-agent: *
Disallow: /blog
دستور Disallow: /blog خطرناک است زیرا مانع از خواندن هر مسیری که با /blog شروع میشود توسط خزندهها میشود. و معمولاً مقالات شما همان چیزی هستند که بیشترین بازدید را برای سایت شما به ارمغان میآورند.
مستندات robots.txt گوگل نمونه مشابهی را ارائه میدهد: Disallow: /fish همچنین /fish.html و /fishheads را مسدود میکند.
برای اصلاح آن، قانون را طوری تنظیم کنید که دقیقاً همان چیزی را که قصد مسدود کردنش را داشتید مطابقت دهد، برای مثال یک پوشه از پیشنویسها:
User-agent: *
Disallow: /blog-drafts/
در سایت تمرینی، خط html مربوط به ورودی '/robots.txt' را تغییر دهید:
html: 'User-agent: *\nDisallow: /blog-drafts/\n',
فایل robots.txt خزش (crawling) را کنترل میکند، نه ایندکس شدن را. گوگل میگوید این فایل مکانیزمی برای دور نگه داشتن یک صفحه از گوگل نیست. برای این کار، به تگ noindex نیاز دارید.
یک URL مسدود شده در robots.txt حتی میتواند در نتایج جستجو ظاهر شود، معمولاً بدون توضیحات، اگر صفحات دیگر به آن لینک داده باشند. گوگل صرفاً محتوای موجود در صفحه را نمیخواند.
چگونه یک تگ noindex تصادفی را پیدا کنیم؟
تگ noindex به گوگل میگوید که یک صفحه خاص را ایندکس نکند. این کار زمانی مضر است که روی صفحاتی قرار گیرد که میخواهید ایندکس و رتبهبندی شوند، مانند صفحه محصول یا صفحه اصلی.
اما میتواند روی صفحاتی که نیازی به رتبهبندی آنها ندارید، یا چیز زیادی به سایت اضافه نمیکنند (مانند صفحات ورود، ثبتنام)، مفید باشد.
تگ noindex تنها زمانی کار میکند که خزنده بتواند به صفحه دسترسی پیدا کند و قانون را بخواند. اگر robots.txt همان URL را مسدود کند، گوگل هرگز noindex را نمیبیند و صفحه همچنان میتواند در نتایج جستجو ظاهر شود. بنابراین برای صفحهای که میخواهید از گوگل خارج کنید، از noindex استفاده کنید و اجازه دهید صفحه قابل خزش بماند.
در دادهها، ۱۱ صفحه از ۴۵۷ صفحه بررسیشده (۲.۴٪) دارای تگ متا robots با مقدار noindex بودند. دو راه برای تنظیم آن وجود دارد و شما باید هر دو را بررسی کنید.
چگونه تگ متا Robots را بررسی کنیم؟
روش اول یک تگ در بخش <head> صفحه است:
<meta name="robots" content="noindex">
صفحه را برای کلمه زیر جستجو کنید:
curl -s http://localhost:8080/about | grep -i noindex
در صفحه درباره ما (About)، این دستور چیزی چاپ نمیکند. همچنین میتوانید روی صفحه کلیک راست کرده، گزینه View Page Source را انتخاب کنید و به دنبال noindex بگردید.
رفع مشکل noindex بسیار آسان است. اساساً آن را حذف میکنید و سپس موتورهای جستجو میتوانند صفحه را ایندکس کنند.
به دنبال آن در کد یا قالب صفحه، و در تنظیمات CMS یا افزونه سئو خود بگردید. در وردپرس، تنظیمات «جلوگیری از فهرستشدن سایت توسط موتورهای جستجو» (Discourage search engines from indexing this site) این تگ را به هر صفحه اضافه میکند.
چگونه هدر X-Robots-Tag را بررسی کنیم؟
روش دوم یک هدر HTTP است. هدرهای صفحه درباره ما را بررسی کنید:
curl -sI http://localhost:8080/about
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
X-Robots-Tag: noindex
Date: Sun, 25 Oct 2026 17:42:59 GMT
Connection: keep-alive
Keep-Alive: timeout=5
این هدر در View Page Source ظاهر نمیشود، بلکه فقط در هدرهای پاسخ (response headers) قابل مشاهده است. در دادهها، ۵ صفحه از ۱۲ صفحه مسدود شده هیچ تگ noindex در HTML خود نداشتند: ۲ صفحه دارای این هدر بودند و ۳ صفحه توسط robots.txt از خزش مسدود شده بودند.
برای رفع این مشکل در سایت تمرینی، خط headers را از ورودی '/about' حذف کنید. در یک سایت واقعی، پیکربندی سرور، تنظیمات هدر ارائهدهنده هاست و هرگونه افزونه سئویی را بررسی کنید.
چگونه به طور صحیح از تگهای کانونیکال (Canonical Tags) استفاده کنیم؟
اگر چندین صفحه دارید که کموبیش درباره یک موضوع صحبت میکنند، اما محتوای کافی برای متفاوت بودن ندارند، میخواهید یک صفحه اصلی را مشخص کنید. تگ کانونیکال به موتورهای جستجو میگوید که کدام صفحه، صفحه اصلی است.
یک صفحه ممکن است در چند آدرس مختلف نیز وجود داشته باشد:
https://example.com/blog/choosing-trail-shoes
https://example.com/blog/choosing-trail-shoes?utm_source=newsletter
https://www.example.com/blog/choosing-trail-shoes
این سه آدرس همان مقاله را نشان میدهند. اولین مورد، نسخه اصلی است: آدرسی که میخواهید گوگل در نتایج جستجو نشان دهد. بنابراین هر سه دارای یک تگ کانونیکال هستند که به آن صفحه اصلی اشاره میکند:
<link rel="canonical" href="https://example.com/blog/choosing-trail-shoes">
وقتی گوگل این تگ را در نسخه ?utm_source=newsletter میبیند، میفهمد که آن صفحه کپی از آدرس اول است. آدرس اصلی نیز همان تگ را دارد که به خودش اشاره میکند. به این کار کانونیکال خودارجاعی (self-referencing canonical) میگویند و معنایش این است: من نسخه اصلی هستم.
گوگل با آن به عنوان یک سیگنال قوی برخورد میکند، نه یک دستور قطعی. اگر از تگهای کانونیکال استفاده میکنید، داشتن یک تگ خودارجاعی در هر صفحه اصلی یک روش خوب است و گوگل آن را توصیه میکند.
اما اصلاً مجبور نیستید از تگهای کانونیکال استفاده کنید. گوگل میگوید مشخص کردن تگ کانونیکال الزامی نیست: بدون آن، گوگل ورژنی را که فکر میکند برای کاربران بهتر است انتخاب میکند. تگ کانونیکال انتخاب خوبی است هنگامی که محتوای یکسان یا بسیار مشابه در بیش از یک URL قابل دسترسی باشد، مانند سه آدرس بالا.
به همین دلیل است که گم شدن یا نبودن تگ کانونیکال به خودی خود یک نقص محسوب نمیشود. در دادهها، ۲۷.۱٪ از ۴۵۷ صفحه بررسیشده فاقد تگ کانونیکال بودند. آنچه اهمیت دارد این است که آیا هیچکدام از آنها نسخههای تکراری (مانند نسخهای با پارامترهای ردیابی) ندارند که به آن نیاز داشته باشد.
مقاله کفش کوهنوردی (trail shoe) سایت تمرینی را بررسی کنید:
curl -s http://localhost:8080/blog/choosing-trail-shoes | grep -i canonical
<link rel="canonical" href="http://localhost:8080/">
این مقاله میگوید نسخه اصلی آن صفحه اصلی سایت است، بنابراین ممکن است گوگل به جای آن، صفحه اصلی را نمایش دهد یا تگ را نادیده بگیرد.
این مقاله کپی هیچ چیزی نیست، بنابراین نسخه اصلی خودش است. برای رفع این مشکل، تگ کانونیکال مقاله را به خودِ مقاله اشاره دهید:
canonical: '/blog/choosing-trail-shoes',
چگونه عناوین و توضیحات متای گمشده و تکراری را اصلاح کنیم؟
یک عنوان یا توضیحات متا خوب دارای طول مناسبی است، بیش از حد شلوغ نیست و به طور خلاصه موضوع صفحه را بیان میکند. این در واقع عصاره صفحه است، درست مانند مقدمه آن.
به صفحه محصول Blue Runner نگاه کنید:
curl -s http://localhost:8080/products/blue-runner | grep -i -E "<title>|name=\"description\""
<title>Acme Shoes</title>
عنوان هیچ چیزی درباره صفحه نمی گوید و اصلا خط توضیحی وجود ندارد. در پاورپوینت، از | Select-String '<title>|name="description"' برای این مورد استفاده کنید.
راهنمای گوگل برای عنوانها و اسنیپتها درخواست یک عنوان و توضیحات منحصر به فرد و توصیفی در هر صفحه می کند.
برای رفع آن در سایت تمرینی، خط عنوان ورودی '/products/blue-runner' را با این جایگزین کنید:
title: 'Blue Runner Road Running Shoe | Acme Shoes',
description: 'A lightweight road running shoe with a cushioned sole and free returns.',
چگونه لینکهای خود را قابل خزیدن کنیم
به صفحه اصلی سایت تمرینی نگاه کنید:
curl -s http://localhost:8080/
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Acme Shoes: Running Shoes for Every Runner</title>
<meta name="description" content="Lightweight running shoes for road and trail, with free returns.">
<link rel="canonical" href="http://localhost:8080/">
</head>
<body>
<h1>Acme Shoes</h1>
<a href="/products/blue-runner">Blue Runner</a>
<span onclick="location.href='/sale'">Summer sale</span>
</body>
</html>
همه چیز در این صفحه خوب است: عنوان، توضیحات، تگ کانونیکال و لینک Blue Runner، که یک عنصر <a> واقعی با یک href است. تنها مشکل <span> «حراج تابستانه» است.
یک <span> اساساً HTML است که معنایی ندارد، یعنی هیچ معنایی ندارد. یک لینک واقعی معنا دارد: موتورهای جستجو می توانند بفهمند که این یک لینک است و صفحه خوانها می توانند بفهمند که یک لینک است.
کدام لینکها باید قابل خزیدن باشند؟ اساساً، هر چیزی که می خواهید موتورهای جستجو ببینند. منظورم محصولاتی که می فروشید، مقالات شما، دورههای شما و چیزهای دیگری از این قبیل است.
دستورالعملهای لینک Google می گویند که فقط می تواند به طور قابل اعتماد یک عنصر <a> را با یک href خزش کند.
برای رفع آن در سایت تمرینی، خط <span> را با این جایگزین کنید:
'<a href="/sale">Summer sale</a>',
چگونه بررسی کنیم که آیا محتوای شما برای نمایش به جاوا اسکریپت نیاز دارد یا خیر
با رندر سمت کاربر، جاوا اسکریپت باید ابتدا بارگذاری شود و تنها پس از آن محتوای دیگر می تواند بارگذاری شود.
جاوا اسکریپت معمولاً مواردی مانند لیست محصولات، قیمتها، بررسیها و منوها را می سازد. بدون آن، یک صفحه سمت کاربر اغلب فقط یک پیام بارگذاری یا یک کادر خالی را نشان می دهد.
گوگل جاوا اسکریپت را رندر می کند، اما در مرحلهای بعدی. صفحه در یک صف رندر منتظر می ماند که ممکن است چند ثانیه یا بیشتر طول بکشد، و یک اسکریپت که خراب می شود یا مسدود می شود می تواند صفحه رندر شده را بدون محتوای خود رها کند.
به همین دلیل است که رندر سمت سرور ایده خوبی است و من آن را برای محتوایی که اهمیت دارد ترجیح میدهم. راهنمای جاوا اسکریپت گوگل نیز همین را میگوید: رندر سمت سرور سایت را برای کاربران و خزندهها سریعتر میکند و همه رباتها نمیتوانند جاوا اسکریپت را اجرا کنند.
در دادهها، 17.7 درصد از 277 صفحه ممیزی شده عمدتاً با جاوا اسکریپت ساخته شده بودند. این بدان معنا نیست که گوگل نتوانسته آنها را ایندکس کند، بلکه به این معناست که محتوای اصلی آنها به اجرای صحیح جاوا اسکریپت بستگی داشته است.
با رندر سمت سرور، محتوای HTML مستقیماً به مرورگر می آید و فقط پس از آن جاوا اسکریپت رندر می شود.
گوگل می تواند صفحات ساخته شده به هر دو روش را ایندکس کند. خزنده آن جاوا اسکریپت را با نسخه بهروزی از کروم اجرا میکند، بنابراین رندر سمت سرور الزامی برای ورود به ایندکس گوگل نیست.
آزمایش بعدی بررسی میکند که آیا محتوای مهم بدون جاوا اسکریپت قابل مشاهده است یا خیر. این نشان نمی دهد که گوگل چه چیزی را می بیند، زیرا گوگل جاوا اسکریپت را اجرا می کند، اما نشان می دهد که هر خزنده قبل از اجرای هر جاوا اسکریپت چه چیزی را دریافت می کند.
http://localhost:8080/catalog را در مرورگر خود باز کنید. سه محصول را خواهید دید. اکنون آن را با curl، که جاوا اسکریپت را اجرا نمیکند، بارگیری کنید:
curl -s http://localhost:8080/catalog | grep -i "trail grip"
این چیزی چاپ نمی کند، زیرا نام محصولات در HTML که سرور ارسال می کند وجود ندارد. در داخل <body>، سرور فقط این موارد را ارسال می کند:
<div id="app">Loading...</div>
<script>fetch('/api/products').then((r) => r.json()).then((products) => {document.getElementById('app').innerHTML = products.map((p) => '<h2>' + p + '</h2>').join('');});</script>
بدون curl، از View Page Source در مرورگر خود استفاده کنید. در این صفحه، «Loading...» و اسکریپت را خواهید دید، اما هیچ یک از نام محصولات را نخواهید دید، زیرا مرورگر آنها را فقط پس از اجرای جاوا اسکریپت اضافه می کند.
در سایت خودتان، منبع را برای یک جمله مهم از صفحه جستجو کنید.
برای دیدن صفحه به شکلی که گوگل آن را رندر می کند، از ابزارهای خود گوگل در یک صفحه زنده استفاده کنید. در سایت خودتان، ابزار URL Inspection در Search Console می تواند یک تست زنده اجرا کند (Test live URL، سپس View tested page) و HTML رندر شده توسط گوگل و یک اسکرینشات را نشان دهد.
برای هر صفحه عمومی، آزمایش نتایج غنی (Rich Results Test) نیز HTML رندر شده را نشان می دهد. گوگل هر دو را توصیه می کند برای یافتن مشکلات جاوا اسکریپت. هیچکدام نمیتوانند به localhost برسند، بنابراین آنها را در سایت واقعی خود امتحان کنید.
اگر می خواهید نام محصولات از همان ابتدا در HTML باشد، آنها را در سرور رندر کنید. در سایت تمرینی، لیست محصولات را بالاتر از routes اضافه کنید:
const products = ['Blue Runner', 'Trail Grip 2', 'City Glide'];
بدنه کاتالوگ و خطوط اسکریپت را با این جایگزین کنید:
body: '<div id="app">' + products.map((p) => '<h2>' + p + '</h2>').join('') + '</div>',
و در ورودی '/api/products':
html: JSON.stringify(products),
سرور را مجدداً راه اندازی کنید و دستور curl را دوباره اجرا کنید:
<div id="app"><h2>Blue Runner</h2><h2>Trail Grip 2</h2><h2>City Glide</h2></div>
این کار می کند زیرا سرور اکنون نام محصولات را قبل از ارسال صفحه در HTML می نویسد. هر خزنده ای آنها را می بیند، حتی خزنده ای که نمی تواند جاوا اسکریپت را اجرا کند، و شما همچنان می توانید از جاوا اسکریپت برای بخشهای تعاملی استفاده کنید.
آیا می توانید یک صفحه را در پنج دقیقه بررسی کنید؟
راستش را بخواهید، بسیار دشوار است. ممکن است مشکلات زیادی وجود داشته باشد و پنج دقیقه کافی نیست.
برای اینکه واقعاً بدانید مشکلات چیست، باید یک بررسی کامل انجام دهید، مثلاً در Google PageSpeed Insights. اگر سایت متعلق به خودتان است، از ابزار بازرسی URL (URL Inspection tool) در Google Search Console نیز استفاده کنید.
دستورات این آموزش یک شروع خوب هستند:
- curl -sI برای کد وضعیت و هدر X-Robots-Tag.
- curl -sIL روی یک آدرس قدیمی برای شمارش ریدایرکتها.
- /robots.txt، خط به خط.
- مشاهده منبع صفحه (View Page Source) برای noindex، کانونیکال، <title>، توضیحات و محتوای مهم شما.
نتیجهگیری
در این آموزش، شما هشت مشکل را در یک سایت تمرینی برطرف کردید: یک خطای نرم 404، یک زنجیره هدایت (تکمیلنشده)، یک قانون robots.txt، یک هیدرف پنهان noindex، یک تگ کنونیکال اشتباه، یک عنوان مبهم و یک توضیحات گمشده، لیستی که رباتهای خزنده نمیتوانستند آن را دنبال کنند، و محتوایی که به جاوااسکریپت نیاز داشت.
مهمترین نکتهای که باید به خاطر داشته باشید این است که باید همیشه سایت خود را بررسی کنید. اسکنها را اجرا کنید، نگهداریهای لازم را انجام دهید، و مطمئن شوید چیزی خراب نمیشود، بهویژه زمانی که بهبودها یا تغییراتی در سایت ایجاد میکنید.
اگر میخواهید بیشتر پیش بروید، آموزش من درباره افزودن دادههای ساختاریافته (JSON-LD) به یک سایت Next.js گام بعدی مناسبی است.
اگر میخواهید یک صفحه زنده را از نظر بسیاری از این مشکلات به صورت یکجا بررسی کنید، ابزار رایگان من ممیزی صفحه Greadme هر URL را بدون نیاز به ثبتنام تست میکند.
نظر مهندس بهمن آبادی: سئوی فنی فراتر از کلمات کلیدی و محتواست و به زیرساختی نیاز دارد که خزندههای موتور جستجو بدون موانعی مثل خطاهای پنهان، ریدایرکتهای زنجیرهای یا تکیه بیش از حد بر جاوا اسکریپت، به آن دسترسی داشته باشند. برخلاف سئوی داخلی، مشکلات این حوزه تا زمان ممیزی دقیق پنهان میمانند؛ بنابراین ابزارهایی مثل دستورات ترمینال و بررسی کدهای وضعیت HTTP، کلید اصلی کشف و رفع آسیبهای پشتصحنه سایت هستند. ابزارها و کدهای وضعیت HTTP، خط مقدم شناسایی این چالشها هستند و باید در فرآیند توسعهی استاندارد گنجانده شوند.
منبع: https://www.freecodecamp.org/news/fix-common-technical-seo-issues/