- 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.
127 lines
8.1 KiB
Markdown
127 lines
8.1 KiB
Markdown
# بهینهسازی 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` را میخواند):
|
|
|
|
```js
|
|
const title =
|
|
matchedCity?.title ||
|
|
(matchedCity?.name
|
|
? `نوبتدهی آنلاین پزشکان ${matchedCity.name} | نوبت 724`
|
|
: "نوبت 724 | سیستم نوبتدهی آنلاین پزشکی");
|
|
```
|
|
|
|
نمونه رکورد فعلی `data/city.json` (فیلد `title` وجود ندارد):
|
|
|
|
```json
|
|
{
|
|
"id": 101,
|
|
"name": "تبریز",
|
|
"site_name": "تبریز نوبت",
|
|
"description": "نوبت تبریز، سامانه تخصصی نوبتدهی پزشکی شمالغرب کشور است. ...",
|
|
"slogan": "سریعترین نوبتدهی پزشکی تبریز",
|
|
"domain": "tabriz-nobat.ir",
|
|
"keywords": "نوبت تبریز, دکتر تبریز, پزشک متخصص تبریز, رزرو نوبت اینترنتی تبریز, کلینیک تبریز, بیمارستان تبریز, نوبت آنلاین آذربایجان شرقی",
|
|
"province_id": 1
|
|
}
|
|
```
|
|
|
|
## وظایف
|
|
|
|
### ۱. افزودن فیلد `title` به هر ۳۴ رکورد
|
|
|
|
بعد از فیلد `site_name` (یا کنار فیلدهای SEO) در هر رکورد اضافه کن:
|
|
|
|
```json
|
|
"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 ممنوع — هر عبارت باید نیت جستجوی واقعی داشته باشد.
|
|
|
|
### ۴. اعتبارسنجی
|
|
|
|
```bash
|
|
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 است).
|