- Implemented canonical URL strategies for city-specific domains and entities. - Added helper functions for domain and city resolution. - Created tests for canonical URL generation and domain resolution. - Introduced entity quality checks for doctors and clinics to ensure meaningful content. - Developed unique introductory texts for listing pages to avoid duplicate content. - Established robots.txt policies for listing pages to manage indexing based on user filters. - Enhanced specialty content with dynamic introductions and FAQs to improve SEO.
119 lines
11 KiB
JavaScript
119 lines
11 KiB
JavaScript
// متن مقدمه و سوالات متداول صفحات فرود تخصص.
|
||
//
|
||
// دو الزام SEO اینجا با هم حل میشوند:
|
||
// ۱. رفع Thin Content — canonical درست، محتوای تکراری را غیرتکراری نمیکند.
|
||
// ۲. تنوع ساختاری — متن هر شهر/تخصص باید ساختار جملهبندی متفاوتی داشته باشد،
|
||
// نه یک قالب واحد با جایگذاری نام. برای همین از سه بلوکِ مستقل با گونههای
|
||
// متفاوت استفاده میشود که با هشِ (تخصص، شهر) انتخاب میشوند — خروجی پایدار
|
||
// (بین دو رندر تغییر نمیکند) ولی بین صفحات مختلف واگراست.
|
||
|
||
function hash(...parts) {
|
||
const key = parts.join("|");
|
||
let value = 0;
|
||
for (let i = 0; i < key.length; i++) {
|
||
value = (value * 31 + key.charCodeAt(i)) >>> 0;
|
||
}
|
||
return value;
|
||
}
|
||
|
||
// seed همیشه unsigned گرفته میشود؛ با >> علامتدار، هشهای بزرگتر از 2^31 منفی
|
||
// میشدند و ایندکس منفی به undefined میرسید.
|
||
const pick = (variants, seed) => variants[(seed >>> 0) % variants.length];
|
||
|
||
function openingVariants(specialty, city) {
|
||
return [
|
||
`اگر به دنبال متخصص ${specialty} در ${city} هستید، این صفحه فهرست کاملی از پزشکان فعال این حوزه را در اختیار شما میگذارد. هر پروفایل شامل تخصصها، سوابق، محل مطب و امتیاز واقعی بیماران است تا بتوانید پیش از رزرو نوبت، انتخاب آگاهانهتری داشته باشید.`,
|
||
`انتخاب پزشک ${specialty} در ${city} وقتی سادهتر میشود که همهٔ گزینهها را یکجا و با اطلاعات یکسان ببینید. در این صفحه، متخصصان ${specialty} شهر ${city} همراه با نشانی مطب، ساعات پذیرش و بازخورد مراجعان گردآوری شدهاند.`,
|
||
`دسترسی به متخصص ${specialty} در ${city} دیگر نیازی به تماسهای پیدرپی و مراجعهٔ حضوری برای گرفتن نوبت ندارد. فهرست زیر پزشکان این تخصص را در ${city} نشان میدهد؛ از هر پروفایل میتوانید مستقیم و آنلاین نوبت بگیرید.`,
|
||
`این صفحه به معرفی پزشکان ${specialty} در ${city} اختصاص دارد. هدف، کوتاهکردن مسیر میان «جستوجوی یک متخصص خوب» و «داشتن نوبت قطعی» است؛ بنابراین اطلاعات هر پزشک بهشکلی چیده شده که مقایسه میان گزینهها سریع انجام شود.`,
|
||
];
|
||
}
|
||
|
||
function bodyVariants(specialty, city, doctorCount) {
|
||
const countPhrase =
|
||
doctorCount > 0
|
||
? `در حال حاضر ${doctorCount} پزشک ${specialty} در ${city} در این سامانه ثبت شدهاند`
|
||
: `فهرست پزشکان ${specialty} در ${city} بهطور مداوم بهروزرسانی میشود`;
|
||
|
||
return [
|
||
`${countPhrase}. برای هر پزشک، مواردی مانند مدرک و درجهٔ تخصصی، کد نظام پزشکی، خدمات قابل ارائه و موقعیت مکانی مطب نمایش داده میشود. امتیازها و نظرها از مراجعان واقعی همان پزشک جمعآوری شدهاند، نه از منابع عمومی؛ به همین دلیل تصویر دقیقتری از کیفیت خدمات به دست میدهند.`,
|
||
`${countPhrase} و اطلاعات آنها بهصورت دورهای بازبینی میشود. تفاوت این فهرست با جستوجوی ساده در آن است که هر رکورد به یک پروفایل کامل وصل است: خدمات، محلهای پذیرش، ساعات کاری هر محل و امکان رزرو مستقیم. نتیجه آنکه مقایسهٔ چند پزشک در چند دقیقه ممکن میشود.`,
|
||
`${countPhrase}. برخی از این پزشکان بیش از یک محل پذیرش دارند — مطب شخصی و یک یا چند کلینیک — و ساعات کاری هر محل جداگانه اعلام شده است. هنگام رزرو، محل مراجعه را خودتان انتخاب میکنید تا نوبتی که میگیرید با برنامهٔ رفتوآمد شما هماهنگ باشد.`,
|
||
];
|
||
}
|
||
|
||
function closingVariants(specialty, city) {
|
||
return [
|
||
`پس از انتخاب پزشک، تقویم نوبتهای خالی نمایش داده میشود و رزرو در همان لحظه قطعی میگردد؛ پیامک تأیید نیز برایتان ارسال خواهد شد. اگر برنامهتان تغییر کرد، لغو نوبت از بخش نوبتهای من در حساب کاربری ممکن است و آن بازهٔ زمانی بلافاصله برای بیمار دیگری آزاد میشود. اگر تخصص موردنظرتان ${specialty} نیست، از فهرست تخصصهای ${city} میتوانید حوزهٔ درمانی دیگری را دنبال کنید و همان مسیر رزرو را طی کنید.`,
|
||
`نوبتگیری در همین صفحه انجام میشود: تاریخ و ساعت خالی را میبینید، انتخاب میکنید و تأیید نهایی را دریافت میکنید. هزینهٔ هر خدمت پیش از تأیید نمایش داده میشود تا انتخابتان با اطلاع کامل انجام شود. برای حوزههای درمانی دیگر در ${city}، صفحهٔ تخصصها فهرست کامل رشتهها را در اختیارتان میگذارد و از هر رشته میتوانید مستقیم به پزشکان همان حوزه برسید.`,
|
||
`تمام مراحل — از مقایسهٔ پزشکان ${specialty} تا دریافت تأییدیهٔ نوبت — آنلاین و بدون مراجعهٔ حضوری طی میشود؛ نیازی به تماس تلفنی در ساعات اداری نیست و رزرو شبانهروزی انجام میگیرد. کلینیکها و مراکز درمانی ${city} نیز صفحهٔ اختصاصی خود را دارند و اگر ترجیح میدهید ابتدا مرکز درمانی را انتخاب کنید، از همان مسیر قابل رزرو هستند.`,
|
||
`برای رزرو کافی است روی پروفایل پزشک بزنید و از میان نوبتهای خالی یکی را انتخاب کنید؛ تأییدیه بلافاصله صادر و پیامک میشود. سابقهٔ نوبتهای شما در حساب کاربری باقی میماند و مراجعهٔ بعدی به همان پزشک سریعتر انجام میشود. اگر ترجیح میدهید بر اساس مرکز درمانی جستوجو کنید، فهرست کلینیکهای ${city} گزینهٔ مناسبی برای شروع است.`,
|
||
];
|
||
}
|
||
|
||
/** متن مقدمهٔ یکتا (۱۵۰–۳۰۰ کلمه) برای یک تخصص در یک شهر. */
|
||
export function buildSpecialtyIntro(specialtyName, cityName, doctorCount = 0) {
|
||
const seed = hash(specialtyName, cityName);
|
||
return [
|
||
pick(openingVariants(specialtyName, cityName), seed),
|
||
pick(bodyVariants(specialtyName, cityName, doctorCount), seed >>> 3),
|
||
pick(closingVariants(specialtyName, cityName), seed >>> 7),
|
||
].join(" ");
|
||
}
|
||
|
||
/** سوالات متداول صفحهٔ پزشک — منبع مشترک بلوک بصری و FAQPage schema. */
|
||
export function buildDoctorFaq(doctorName, specialtyName, cityName) {
|
||
const who = `دکتر ${doctorName}`;
|
||
return [
|
||
{
|
||
question: `چگونه از ${who} نوبت بگیرم؟`,
|
||
answer: `از همین صفحه، محل مراجعه و سپس تاریخ و ساعت خالی موردنظرتان را انتخاب کنید. رزرو در همان لحظه قطعی میشود و تأییدیه برایتان پیامک خواهد شد.`,
|
||
},
|
||
...(specialtyName
|
||
? [
|
||
{
|
||
question: `تخصص ${who} چیست؟`,
|
||
answer: `${who} در حوزهٔ ${specialtyName} فعالیت میکند. فهرست کامل خدمات قابل ارائه در همین صفحه آمده است.`,
|
||
},
|
||
]
|
||
: []),
|
||
...(cityName
|
||
? [
|
||
{
|
||
question: `مطب ${who} در کدام شهر است؟`,
|
||
answer: `محل یا محلهای پذیرش ${who} در ${cityName} به همراه نشانی دقیق و ساعات کاری هر محل، در بخش موقعیت مکانی همین صفحه نمایش داده شده است.`,
|
||
},
|
||
]
|
||
: []),
|
||
{
|
||
question: `امکان لغو نوبت وجود دارد؟`,
|
||
answer: `بله. از بخش نوبتهای من در حساب کاربریتان میتوانید نوبت را لغو کنید؛ لغو زودهنگام آن بازهٔ زمانی را برای بیمار دیگری آزاد میکند.`,
|
||
},
|
||
];
|
||
}
|
||
|
||
/** سوالات متداول صفحهٔ تخصص — منبع مشترک بلوک بصری و FAQPage schema. */
|
||
export function buildSpecialtyFaq(specialtyName, cityName, doctorCount = 0) {
|
||
return [
|
||
{
|
||
question: `چطور از متخصص ${specialtyName} در ${cityName} نوبت بگیرم؟`,
|
||
answer: `از فهرست همین صفحه پزشک موردنظرتان را انتخاب کنید، وارد پروفایل او شوید و از تقویم نوبتهای خالی، تاریخ و ساعت دلخواه را ثبت کنید. رزرو در همان لحظه قطعی میشود و تأییدیه برایتان پیامک میشود.`,
|
||
},
|
||
{
|
||
question: `چند پزشک ${specialtyName} در ${cityName} در دسترس است؟`,
|
||
answer:
|
||
doctorCount > 0
|
||
? `در حال حاضر ${doctorCount} پزشک ${specialtyName} در ${cityName} در این سامانه ثبت شدهاند. این عدد با افزودهشدن پزشکان جدید بهروزرسانی میشود.`
|
||
: `فهرست پزشکان ${specialtyName} در ${cityName} در حال تکمیل است و بهمرور پزشکان جدید به آن افزوده میشوند.`,
|
||
},
|
||
{
|
||
question: `هزینهٔ ویزیت متخصص ${specialtyName} چقدر است؟`,
|
||
answer: `هزینهٔ ویزیت به نوع خدمت، درجهٔ تخصصی پزشک و پوشش بیمه بستگی دارد. مبلغ هر خدمت پیش از تأیید نهایی نوبت، در همان صفحهٔ رزرو نمایش داده میشود.`,
|
||
},
|
||
{
|
||
question: `اگر نتوانم در زمان نوبت مراجعه کنم چه کنم؟`,
|
||
answer: `از بخش نوبتهای من در حساب کاربریتان میتوانید نوبت را لغو کنید. لغو زودهنگام باعث میشود آن بازهٔ زمانی برای بیمار دیگری آزاد شود.`,
|
||
},
|
||
];
|
||
}
|