Files
hamed 92b8f474c1 Add SEO fields to city.json for local branding optimization
- Introduced a new `title` field for each city record, incorporating local brand names.
- Rewrote `slogan` for each city to reflect startup tone and include city keywords.
- Optimized `keywords` with relevant local and long-tail search terms.
- Ensured compliance with SEO best practices and maintained JSON structure.
2026-07-08 11:57:31 +03:30

8.1 KiB
Raw Permalink Blame History

بهینه‌سازی SEO فیلدهای city.json — افزودن title برند‌دار + بازنویسی slogan و keywords

پروژه

nobat724_front

زمینه

سایت چند-دامنه‌ای است: هر شهر دامنه خودش را دارد (tabriz-nobat.ir، esf-nobat.ir، ...) و همه SEO هر شهر از data/city.json تغذیه می‌شود. app/layout.js در generateMetadata اول matchedCity?.title را می‌خواند و چون هیچ‌کدام از ۳۴ رکورد شهر فیلد title ندارند، همیشه به الگوی fallback با برند سراسری «نوبت 724» می‌افتد — در حالی که هر شهر برند محلی خودش (site_name مثل «اراک نوبت») را دارد. slogan هم متن قابل ایندکس صفحات است (hero صفحه اصلی، about-us، پوستر پزشک) و باید هم مفهوم استارت‌آپی داشته باشد هم کلمه کلیدی شهر.

مشکل / هدف

نقش: متخصص حرفه‌ای SEO فارسی (local SEO سلامت/نوبت‌دهی پزشکی).

سه فیلد در هر ۳۴ رکورد data/city.json باید ساخته/بازنویسی شود:

  1. title (فیلد جدید): عنوان متا برای هر شهر که حتماً برند محلی (site_name) در آن باشد. الگو: نوبت‌دهی آنلاین پزشکان <name> | <site_name> مثال هدف: "title": "نوبت‌دهی آنلاین پزشکان اراک | اراک نوبت"
  2. slogan: بازنویسی با مفهوم استارت‌آپی + SEO (کلمه کلیدی شهر داخلش باشد).
  3. keywords: بهینه‌سازی با کلمات کلیدی محلی و long-tail واقعی جستجوی فارسی.

فایل‌های مرتبط

فایل نقش
nobat724_front/data/city.json تنها فایل قابل تغییر — ۳۴ رکورد شهر
nobat724_front/app/layout.js مصرف‌کننده — فقط بخوان، تغییر نده
nobat724_front/components/home/TextHeader.js نمایش slogan در hero صفحه اصلی
nobat724_front/components/aboutUs/index.js نمایش slogan در about-us
nobat724_front/components/doctor/poster/index.js نمایش slogan در پوستر پزشک

وضعیت فعلی

app/layout.js (تغییر نمی‌کند — از قبل title را می‌خواند):

const title =
  matchedCity?.title ||
  (matchedCity?.name
    ? `نوبت‌دهی آنلاین پزشکان ${matchedCity.name} | نوبت 724`
    : "نوبت 724 | سیستم نوبت‌دهی آنلاین پزشکی");

نمونه رکورد فعلی data/city.json (فیلد title وجود ندارد):

{
  "id": 101,
  "name": "تبریز",
  "site_name": "تبریز نوبت",
  "description": "نوبت تبریز، سامانه تخصصی نوبت‌دهی پزشکی شمال‌غرب کشور است. ...",
  "slogan": "سریع‌ترین نوبت‌دهی پزشکی تبریز",
  "domain": "tabriz-nobat.ir",
  "keywords": "نوبت تبریز, دکتر تبریز, پزشک متخصص تبریز, رزرو نوبت اینترنتی تبریز, کلینیک تبریز, بیمارستان تبریز, نوبت آنلاین آذربایجان شرقی",
  "province_id": 1
}

وظایف

۱. افزودن فیلد title به هر ۳۴ رکورد

بعد از فیلد site_name (یا کنار فیلدهای SEO) در هر رکورد اضافه کن:

"title": "نوبت‌دهی آنلاین پزشکان تبریز | تبریز نوبت"

قواعد:

  • الگوی ثابت: نوبت‌دهی آنلاین پزشکان <name> | <site_name> — کلمه کلیدی اصلی اول، برند آخر.
  • جداکننده | با فاصله در دو طرف (مثال کاربر فاصله نداشت — نسخه استاندارد با فاصله بنویس).
  • طول کل ≤ ۶۰ کاراکتر (برای عدم truncate در گوگل). همه نام‌های شهر ایران در این الگو جا می‌شوند.
  • name و site_name را دقیقاً از همان رکورد بردار — دست‌ساز ننویس (مثلاً اصفهان → «اصفهان نوبت»).
  • نیم‌فاصله در «نوبت‌دهی» حفظ شود (‌ = U+200C).

۲. بازنویسی slogan هر ۳۴ رکورد — استارت‌آپی + SEO

قواعد:

  • حتماً نام شهر + یکی از کلمات کلیدی (نوبت / پزشک / دکتر) داخل جمله باشد — این متن در H-level صفحه اصلی ایندکس می‌شود.
  • لحن استارت‌آپی: تمرکز بر سرعت، سادگی، دسترسی ۲۴ساعته، حذف صف — نه شعار خشک اداری.
  • کوتاه: ۴ تا ۸ کلمه؛ برای هر شهر یکتا (duplicate content بین ۳۴ دامنه ممنوع — گوگل دامنه‌ها را جدا ایندکس می‌کند ولی الگوی تکراری ارزش برند را می‌کشد).
  • نمونه‌های جهت‌دهنده (کپی نکن، برای هر شهر متفاوت بساز):
    • «نوبت دکتر در تبریز، ساده‌تر از همیشه»
    • «پزشکان اصفهان، یک کلیک تا ویزیت»
    • «سلامت اهواز، بدون صف و انتظار»

۳. بهینه‌سازی keywords هر ۳۴ رکورد

قواعد:

  • ۷ تا ۱۰ عبارت، جدا با , (فرمت فعلی حفظ شود — string، نه array).
  • ترکیب اجباری برای هر شهر:
    • نوبت دکتر <شهر> و نوبت‌دهی آنلاین <شهر> (پرجستجوترین الگوهای فارسی)
    • دکتر خوب <شهر> (الگوی long-tail رایج)
    • پزشک متخصص <شهر>
    • یک عبارت استانی (مثل نوبت آنلاین آذربایجان شرقی) از state.json با province_id
    • برند محلی: <site_name> (مثل تبریز نوبت)
  • عبارت‌های کم‌ارزش/تکراری فعلی (مثل کلینیک <شهر>, بیمارستان <شهر> خالی) را با long-tail هدفمند جایگزین کن: رزرو نوبت پزشک <شهر>، نوبت اینترنتی دکتر <شهر>.
  • keyword stuffing ممنوع — هر عبارت باید نیت جستجوی واقعی داشته باشد.

۴. اعتبارسنجی

cd nobat724_front
node -e "const d=require('./data/city.json'); \
  console.assert(d.length===34,'count'); \
  d.forEach(c=>{ \
    if(!c.title) throw new Error('no title: '+c.name); \
    if(!c.title.includes(c.site_name)) throw new Error('title missing site_name: '+c.name); \
    if(c.title.length>60) throw new Error('title too long: '+c.name); \
    if(!c.slogan.includes(c.name)&&!c.keywords.includes(c.name)) throw new Error('city name missing: '+c.name); \
  }); \
  const slogans=new Set(d.map(c=>c.slogan)); \
  console.assert(slogans.size===34,'duplicate slogans'); \
  console.log('OK')"
npm run build   # فقط اگر سریع بود؛ حداقل: node parse بالا باید OK بدهد

نکات مهم

  • فقط data/city.json تغییر می‌کند. app/layout.js از قبل matchedCity?.title را می‌خواند؛ hero و about-us هم slogan را مستقیم نمایش می‌دهند — هیچ تغییر کدی لازم نیست.
  • ساختار JSON دست نخورد: هیچ فیلدی حذف/تغییرنام نشود، ترتیب رکوردها حفظ شود، encoding UTF-8 و نیم‌فاصله‌ها سالم بمانند.
  • description و footer_description در scope این پرامپت نیستند — ولی اگر با title/slogan جدید تناقض آشکار داشتند (مثلاً برند متفاوت)، فقط گزارش بده، تغییر نده.
  • نام استان هر شهر از data/state.json با province_id قابل استخراج است.
  • برای شهرهایی که site_name آن‌ها با الگوی <شهر> نوبت نیست، همان مقدار واقعی فایل ملاک است.
  • زبان همه مقادیر: فارسی (محصول تماماً فارسی/RTL است).