import type { ParsedRouteParams } from './dataHelper' import { getShortRegionName } from './dataHelper' const SUBJECT_IMAGE_MAP: Record = { math: '/img/math-tutoring.png', english: '/img/english-tutoring.png', korean: '/img/korean-tutoring.png', science: '/img/science-tutoring.png', social: '/img/social-studies-tutoring.png' } const CORE_SUBJECTS = [ { key: 'math', name: '수학', desc: '개념 구멍 추적 및 킬러 문항 1:1 완파', img: '/img/math-tutoring.png' }, { key: 'english', name: '영어', desc: '교과서·부교재 전 지문 변형 및 서술형 영작', img: '/img/english-tutoring.png' }, { key: 'korean', name: '국어', desc: '비문학 독해 논리와 교과서 문학 1:1 정밀 분석', img: '/img/korean-tutoring.png' }, { key: 'science', name: '과학', desc: '통합과학 원리 이해 및 물화생지 킬러 단원 정복', img: '/img/science-tutoring.png' }, { key: 'social', name: '사회', desc: '통합사회·한국사 핵심 흐름 및 사탐 만점 전략', img: '/img/social-studies-tutoring.png' } ] const CORE_GRADES = ['초등학생', '중학생', '고등학생'] export function generateSeoMeta(parsed: ParsedRouteParams, siteName = '공부짝꿍', siteDomain = 'https://soohyun.cloud') { const { sido, sigungu, dong, shortRegionName, grade, subjectKey, subjectName, isRegionOnly } = parsed const shortSido = parsed.shortSido || sido.replace(/특별시|광역시|특별자치시|도/g, '').trim() const gradeShort = parsed.gradeShort || (grade === '초등학생' ? '초등' : grade === '고등학생' ? '고등' : '중등') const regionTitle = shortRegionName || getShortRegionName(sido, dong) const subjectImg = SUBJECT_IMAGE_MAP[subjectKey] || '/img/math-tutoring.png' // 검색어 [지역] [초등/중등/고등] [과목] 과외 / [지역] [초등/중등/고등] 과외 완벽 매칭 타이틀 const pageTitle = isRegionOnly ? `${shortSido} 중등 수학 과외 · ${shortSido} 중등 과외 | ${regionTitle} 초·중·고 1:1 맞춤 과외` : `${shortSido} ${gradeShort} ${subjectName} 과외 · ${regionTitle} ${grade} ${subjectName}과외 | ${shortSido} ${gradeShort} 과외 1:1 매칭` // 첫 문장이 정확한 타겟 키워드로 시작하는 고의도 메타 디스크립션 (더세이브 동기화) const pageDescription = isRegionOnly ? `${shortSido} 중등 수학 과외, ${shortSido} 중등 과외, ${dong} 중등 수학 과외 전문 ${siteName}! ${regionTitle} 초등·중등·고등 국영수사과 1:1 맞춤 과외, 검증된 전문 선생님 무료 시범수업과 과외비 비교를 확인하세요.` : `${shortSido} ${gradeShort} ${subjectName} 과외, ${shortSido} ${gradeShort} 과외, ${dong} ${gradeShort} ${subjectName} 과외 전문 ${siteName}! ${regionTitle} ${grade} ${subjectName} 1:1 방문·화상 맞춤 수업으로 내신·수능 성적 향상을 책임집니다. 과외비 투명 공개 및 무료 시범수업 신청하세요.` const pageKeywords = `${shortSido} ${gradeShort} ${subjectName} 과외, ${shortSido} ${gradeShort} 과외, ${dong} ${gradeShort} ${subjectName} 과외, ${dong} ${gradeShort} 과외, ${shortSido}${gradeShort}${subjectName}과외, ${shortSido}${gradeShort}과외, ${shortSido} 중등 수학 과외, ${shortSido} 중등 과외, ${shortSido} 고등 수학 과외, ${shortSido} 초등 수학 과외, ${regionTitle} ${subjectName}과외, ${dong} ${subjectName}과외, ${dong} ${grade} ${subjectName}과외, ${dong}과외, ${sigungu}과외, ${shortSido}과외` // 표준 Canonical URL (자기참조 분리) const dongUrl = `${siteDomain}/${encodeURIComponent(dong)}` const canonicalUrl = isRegionOnly ? dongUrl : `${siteDomain}/${encodeURIComponent(dong)}/${encodeURIComponent(grade)}/${encodeURIComponent(subjectName)}` // 더세이브 방식 멀티 이미지 배열 const orgImages = [ `${siteDomain}/img/og-main.png`, `${siteDomain}/img/math-tutoring.png`, `${siteDomain}/img/english-tutoring.png`, `${siteDomain}/img/korean-tutoring.png`, `${siteDomain}/img/science-tutoring.png`, `${siteDomain}/img/social-studies-tutoring.png` ] // 서브 라우터 캐러셀(ItemList) 항목 구성: 현재 동 기준 5대 과목 + 타 학년 라우터 (중복 제외 총 7개) const carouselCourses: Array<{ name: string, desc: string, url: string, image: string }> = [] for (const sub of CORE_SUBJECTS) { const cUrl = `${siteDomain}/${encodeURIComponent(dong)}/${encodeURIComponent(grade)}/${encodeURIComponent(sub.name)}` carouselCourses.push({ name: `${shortSido} ${gradeShort} ${sub.name} 과외 · ${regionTitle} ${grade} ${sub.name}과외`, desc: `${dong} 관내 학교 내신 기출 분석 및 ${sub.desc}`, url: cUrl, image: `${siteDomain}${sub.img}` }) } for (const g of CORE_GRADES) { if (g === grade) continue const gShort = g === '초등학생' ? '초등' : g === '고등학생' ? '고등' : '중등' const cUrl = `${siteDomain}/${encodeURIComponent(dong)}/${encodeURIComponent(g)}/${encodeURIComponent(subjectName)}` carouselCourses.push({ name: `${shortSido} ${gShort} ${subjectName} 과외 · ${regionTitle} ${g} ${subjectName}과외`, desc: `${dong} ${g} 학생 대상 ${subjectName} 내신·선행 1:1 밀착 지도`, url: cUrl, image: `${siteDomain}${subjectImg}` }) } const breadcrumbItems = isRegionOnly ? [ { '@type': 'ListItem', 'position': 1, 'name': '홈', 'item': `${siteDomain}/` }, { '@type': 'ListItem', 'position': 2, 'name': `${regionTitle} 과외`, 'item': dongUrl } ] : [ { '@type': 'ListItem', 'position': 1, 'name': '홈', 'item': `${siteDomain}/` }, { '@type': 'ListItem', 'position': 2, 'name': `${dong} 과외`, 'item': dongUrl }, { '@type': 'ListItem', 'position': 3, 'name': `${shortSido} ${gradeShort} ${subjectName} 과외 · ${dong} ${grade} ${subjectName}과외`, 'item': canonicalUrl } ] // 블록 1: @graph (WebSite + WebPage + ImageObject + EducationalOrganization + LocalBusiness + Course + BreadcrumbList) const graphJsonLd = { '@context': 'https://schema.org', '@graph': [ { '@type': 'WebSite', '@id': `${siteDomain}/#site`, 'url': `${siteDomain}/`, 'name': siteName, 'inLanguage': 'ko-KR' }, { '@type': 'WebPage', '@id': `${canonicalUrl}#page`, 'url': canonicalUrl, 'name': pageTitle, 'description': pageDescription, 'isPartOf': { '@id': `${siteDomain}/#site` }, 'primaryImageOfPage': { '@id': `${canonicalUrl}#img` }, 'inLanguage': 'ko-KR' }, { '@type': 'ImageObject', '@id': `${canonicalUrl}#img`, 'url': `${siteDomain}${subjectImg}`, 'contentUrl': `${siteDomain}${subjectImg}`, 'width': 1080, 'height': 1080, 'caption': `${shortSido} ${gradeShort} ${subjectName} 과외` }, { '@type': 'EducationalOrganization', 'name': siteName, 'url': siteDomain, 'image': orgImages, 'telephone': '+82-10-5961-5807', 'description': pageDescription, 'areaServed': { '@type': 'AdministrativeArea', 'name': `${sido} ${sigungu} ${dong}` } }, { '@type': 'LocalBusiness', 'name': `${shortSido} ${gradeShort} 과외 · ${regionTitle} 1:1 방문 과외`, 'image': orgImages, 'url': canonicalUrl, 'telephone': '+82-10-5961-5807', 'priceRange': '₩₩', 'address': { '@type': 'PostalAddress', 'addressLocality': sigungu, 'addressRegion': sido, 'streetAddress': dong, 'addressCountry': 'KR' }, 'areaServed': `${sido} ${sigungu} ${dong}` }, { '@type': 'Course', 'name': isRegionOnly ? `${shortSido} 중등 수학 과외 · ${regionTitle} 초·중·고 1:1 맞춤 과외` : `${shortSido} ${gradeShort} ${subjectName} 과외 · ${dong} ${grade} ${subjectName} 1:1 맞춤 과외`, 'description': `${shortSido} ${gradeShort} ${subjectName} 과외 및 ${dong} 인근 학교 내신 출제 경향 분석, ${subjectName} 1등급 도약 커리큘럼`, 'url': canonicalUrl, 'image': `${siteDomain}${subjectImg}`, 'provider': { '@type': 'Organization', 'name': siteName, 'sameAs': siteDomain }, 'offers': { '@type': 'Offer', 'category': 'Paid', 'priceCurrency': 'KRW', 'availability': 'https://schema.org/InStock', 'url': canonicalUrl }, 'hasCourseInstance': { '@type': 'CourseInstance', 'courseMode': ['onsite', 'online'] } }, { '@type': 'BreadcrumbList', 'itemListElement': breadcrumbItems } ] } // 블록 2: FAQPage 단독 JSON-LD const faqJsonLd = { '@context': 'https://schema.org', '@type': 'FAQPage', 'mainEntity': [ { '@type': 'Question', 'name': `${shortSido} ${gradeShort} ${subjectName} 과외(${dong}), 방문 수업과 화상 수업 모두 가능한가요?`, 'acceptedAnswer': { '@type': 'Answer', 'text': `네, ${shortSido} ${gradeShort} ${subjectName} 과외 및 ${shortSido} ${gradeShort} 과외는 학생과 학부모님의 선호에 따라 100% 자택 방문 대면 수업 또는 실시간 쌍방향 화상 수업 중 자유롭게 선택하실 수 있으며, ${dong} ${gradeShort} ${subjectName} 과외 전 지역 방문 지도가 가능합니다.` } }, { '@type': 'Question', 'name': `${shortSido} ${gradeShort} 과외 · ${dong} ${gradeShort} ${subjectName} 과외 전문 선생님이 학생과 맞지 않으면 교체 가능한가요?`, 'acceptedAnswer': { '@type': 'Answer', 'text': `네, ${shortSido} ${gradeShort} ${subjectName} 과외 및 ${shortSido} ${gradeShort} 과외는 1회 무료 시범수업을 통해 사전에 호흡을 맞추며, ${dong} ${gradeShort} ${subjectName} 과외 정규 수업 시작 후에도 추가 비용 없이 100% 무료 선생님 교체 및 환불 규정을 보장합니다.` } }, { '@type': 'Question', 'name': `${shortSido} ${gradeShort} ${subjectName} 과외 및 ${dong} ${gradeShort} ${subjectName} 과외 수업 비용은 어떻게 되나요?`, 'acceptedAnswer': { '@type': 'Answer', 'text': `${shortSido} ${gradeShort} ${subjectName} 과외와 ${shortSido} ${gradeShort} 과외 비용은 ${grade} 내신 단계, 주당 수업 횟수, 수업 시간(1회 60분/90분/120분)에 따라 표준 교육청 가이드라인에 맞춘 투명한 정찰제로 운영됩니다. ${dong} ${gradeShort} ${subjectName} 과외 무료 상담 시 상세 견적표를 안내해 드립니다.` } }, { '@type': 'Question', 'name': `${dong} ${gradeShort} ${subjectName} 과외로 중간·기말고사 직전 단기 족보 클리닉도 가능한가요?`, 'acceptedAnswer': { '@type': 'Answer', 'text': `네, ${shortSido} ${gradeShort} ${subjectName} 과외 및 ${shortSido} ${gradeShort} 과외 전담팀이 시험 3~4주 전 ${dong} 인근 학교별 기출 족보 풀이 및 서술형 배점 방어를 위한 ${dong} ${gradeShort} ${subjectName} 과외 단기 속성 클리닉도 상시 운영 중입니다.` } }, { '@type': 'Question', 'name': `${shortSido} ${gradeShort} ${subjectName} 과외 외에 국영수사과 다른 과목도 함께 상담받을 수 있나요?`, 'acceptedAnswer': { '@type': 'Answer', 'text': `${shortSido} ${gradeShort} ${subjectName} 과외 집중 신청은 물론, ${shortSido} ${gradeShort} 과외 국영수사과 복합 패키지 및 ${dong} ${gradeShort} ${subjectName} 과외 맞춤형 전 과목 플래너 관리로 시간표를 편성하실 수 있습니다.` } } ] } // 블록 3: ItemList 단독 JSON-LD (더세이브 검색결과 가로 이미지 줄 핵심 구조) const itemListJsonLd = { '@context': 'https://schema.org', '@type': 'ItemList', 'name': `${shortSido} ${gradeShort} ${subjectName} 과외 · ${dong} ${gradeShort} 과외`, 'numberOfItems': carouselCourses.length, 'itemListElement': carouselCourses.map((c, idx) => ({ '@type': 'ListItem', 'position': idx + 1, 'name': c.name, 'url': c.url, 'image': c.image, 'item': { '@type': 'Course', 'name': c.name, 'description': c.desc, 'url': c.url, 'image': c.image, 'provider': { '@type': 'Organization', 'name': siteName, 'sameAs': siteDomain }, 'offers': { '@type': 'Offer', 'category': 'Paid', 'priceCurrency': 'KRW', 'availability': 'https://schema.org/InStock', 'url': c.url }, 'hasCourseInstance': { '@type': 'CourseInstance', 'courseMode': ['onsite', 'online'] } } })) } return { title: pageTitle, meta: [ { name: 'robots', content: 'index,follow' }, { name: 'naver-site-verification', content: 'ec58dcc43a4785d3358d9e2b603fea6bea4d89a3' }, { name: 'description', content: pageDescription }, { name: 'keywords', content: pageKeywords }, { property: 'og:type', content: 'website' }, { property: 'og:locale', content: 'ko_KR' }, { property: 'og:title', content: pageTitle }, { property: 'og:description', content: pageDescription }, { property: 'og:url', content: canonicalUrl }, { property: 'og:site_name', content: siteName }, { property: 'og:image', content: `${siteDomain}${subjectImg}` }, { property: 'og:image:type', content: 'image/png' }, { property: 'og:image:width', content: '1200' }, { property: 'og:image:height', content: '630' }, { property: 'og:image:alt', content: `${shortSido} ${gradeShort} ${subjectName} 과외 · ${dong} ${gradeShort} ${subjectName} 과외` }, { name: 'twitter:card', content: 'summary_large_image' }, { name: 'twitter:title', content: pageTitle }, { name: 'twitter:description', content: pageDescription }, { name: 'twitter:image', content: `${siteDomain}${subjectImg}` } ], link: [ { rel: 'canonical', href: canonicalUrl } ], script: [ { type: 'application/ld+json', children: JSON.stringify(graphJsonLd) }, { type: 'application/ld+json', children: JSON.stringify(faqJsonLd) }, { type: 'application/ld+json', children: JSON.stringify(itemListJsonLd) } ] } }