feat: add canonical URL handling and entity quality checks
- 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.
This commit is contained in:
+8
-16
@@ -3,24 +3,14 @@ import Layout from "@/components/layout/StLayout";
|
||||
import { buildDoctorParams } from "@/helper";
|
||||
import { getStateInfo } from "@/lib/getStateInfo";
|
||||
import { fetchReq } from "@/lib/req";
|
||||
|
||||
|
||||
const FILTER_KEYS = ["specialty", "state", "city", "gender", "degree", "active", "sort", "name"];
|
||||
|
||||
// جستجوی داخلی و ترکیب چند فیلتر نباید ایندکس شوند — crawl budget و duplicate
|
||||
function listingRobots(params) {
|
||||
const activeFilters = FILTER_KEYS.filter((key) => params?.[key]);
|
||||
if (params?.name || activeFilters.length >= 2) {
|
||||
return { robots: { index: false, follow: true } };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
import { listingRobots } from "@/lib/listingRobots";
|
||||
|
||||
export async function generateMetadata({ searchParams }) {
|
||||
const awaitedParams = await searchParams;
|
||||
const { matchedCity, matchedState, repContext } = await getStateInfo();
|
||||
const { matchedCity, matchedState, isRoot, repContext } = await getStateInfo();
|
||||
const siteName = matchedCity?.site_name || repContext?.full_name || "نوبت 724";
|
||||
const cityName = matchedCity?.name || matchedState?.name || "";
|
||||
// روی دامنهٔ ریشه نام رکورد («نوبت 724») برند است نه شهر — نباید در Title بنشیند.
|
||||
const cityName = isRoot ? "" : matchedCity?.name || matchedState?.name || "";
|
||||
const title = cityName
|
||||
? `پزشکان ${cityName} | جستجو و رزرو نوبت | ${siteName}`
|
||||
: `جستجوی پزشک و رزرو نوبت آنلاین | ${siteName}`;
|
||||
@@ -31,7 +21,7 @@ export async function generateMetadata({ searchParams }) {
|
||||
return {
|
||||
title,
|
||||
description,
|
||||
...listingRobots(awaitedParams),
|
||||
...listingRobots(awaitedParams, { matchedCity, matchedState }),
|
||||
openGraph: { title, description, images: [image] },
|
||||
twitter: { card: "summary_large_image", title, description, images: [image] },
|
||||
};
|
||||
@@ -47,7 +37,9 @@ async function Doctors({ searchParams }) {
|
||||
const cityParams = awaitedSearchParams.city;
|
||||
|
||||
try {
|
||||
let newSearchParams = awaitedSearchParams;
|
||||
// کپی — awaitedSearchParams همان شیئی است که generateMetadata هم میخواند؛
|
||||
// تزریق city/state روی خودش، سیاست robots را به noindex میبرد.
|
||||
const newSearchParams = { ...awaitedSearchParams };
|
||||
|
||||
// Conditional State — روی دامنهٔ ریشه (nobat724) فیلتر اعمال نمیشود.
|
||||
if (stateParams) newSearchParams.state = stateParams;
|
||||
|
||||
Reference in New Issue
Block a user