feat: enhance SEO for listing and specialty pages, fix search autocomplete issue

This commit is contained in:
hamed
2026-07-20 10:26:03 +03:30
parent 9011b230b3
commit 30c3fe8637
14 changed files with 460 additions and 69 deletions
+22 -13
View File
@@ -1,20 +1,29 @@
// سیاست ایندکس صفحات لیست (/doctors و /clinics) — یک پیاده‌سازی مشترک تا دو مسیر واگرا نشوند.
//
// جستجوی داخلی (name) و ترکیب چند فیلتر واقعی نباید ایندکس شوند (crawl budget و duplicate).
// اما city/state روی دامنه‌های شهری خودکار از host تزریق می‌شوند و «فیلتر انتخابی کاربر»
// نیستند؛ شمردنشان باعث می‌شد صفحهٔ اصلی لیست روی هر ۳۵ دامنه همیشه noindex شود.
// هر کوئری جستجو/فیلتر یک صفحهٔ داینامیک با محتوای تکراری می‌سازد و نباید ایندکس شود.
// صفحهٔ فرود قابل‌ایندکسِ یک تخصص، /specialties/[slug] است نه /doctors?specialty=.
// پس فقط لیست خام (/doctors و /clinics) ایندکس می‌شود.
//
// page استثناست: pagination فیلتر جستجو نیست و صفحات ۲+ محتوای واقعاً متفاوتی دارند
// (یاسوج به‌تنهایی ~۳۸ صفحه)؛ noindex کردنشان مسیر کشف پزشکان آن صفحات را می‌بندد.
//
// follow در همهٔ حالت‌ها می‌ماند تا لینک‌های داخلی صفحه (پروفایل پزشک، صفحهٔ تخصص) دنبال شوند.
const USER_FILTER_KEYS = ["specialty", "gender", "degree", "active", "sort"];
const NON_FILTER_KEYS = new Set(["page"]);
export function listingRobots(params, { matchedCity, matchedState } = {}) {
if (params?.name) return { robots: { index: false, follow: true } };
const isEmpty = (value) =>
value === undefined || value === null || value === "";
const activeFilters = USER_FILTER_KEYS.filter((key) => params?.[key]);
/** آیا این صفحهٔ لیست، فیلتر یا جستجوی واقعی کاربر دارد؟ */
export function hasListingFilters(params) {
if (!params) return false;
return Object.entries(params).some(
([key, value]) => !NON_FILTER_KEYS.has(key) && !isEmpty(value)
);
}
// فقط city/state متفاوت از شهر/استانِ همین دامنه، انتخاب صریح کاربر است.
if (params?.city && params.city !== matchedCity?.name) activeFilters.push("city");
if (params?.state && params.state !== matchedState?.name) activeFilters.push("state");
if (activeFilters.length >= 2) return { robots: { index: false, follow: true } };
return {};
export function listingRobots(params) {
return hasListingFilters(params)
? { robots: { index: false, follow: true } }
: {};
}