#!/usr/bin/env python3 """ Gateway Page Content Generator Automates the creation of SEO-optimized gateway pages for local services """ import json import os from datetime import datetime from typing import Dict, List, Optional import re from dataclasses import dataclass from pathlib import Path @dataclass class Location: """Location data structure""" id: str name_en: str name_kr: str full_address: str landmarks: List[str] subway_stations: List[str] demographics: str latitude: float longitude: float @dataclass class Service: """Service data structure""" id: str name_en: str name_kr: str category: str description: str keywords: List[str] procedure_time: str recovery_time: str price_range: str @dataclass class Brand: """Brand/Clinic information""" name_en: str name_kr: str website: str phone: str email: str established_year: int certifications: List[str] unique_selling_points: List[str] class GatewayPageGenerator: """Main class for generating gateway page content""" def __init__(self, brand: Brand, template_path: str = "templates/"): self.brand = brand self.template_path = Path(template_path) self.generated_pages = [] def load_template(self, template_name: str) -> str: """Load a template file""" template_file = self.template_path / template_name if template_file.exists(): with open(template_file, 'r', encoding='utf-8') as f: return f.read() else: raise FileNotFoundError(f"Template {template_name} not found") def generate_meta_tags(self, service: Service, location: Location) -> Dict: """Generate SEO meta tags""" return { "title": f"{service.name_en} in {location.name_en} | Expert {service.category} | {self.brand.name_en}", "description": f"Looking for {service.name_en.lower()} in {location.name_en}? " f"{self.brand.name_en} offers professional {service.category.lower()} services. " f"✓ Experienced team ✓ Latest technology ✓ {self.brand.unique_selling_points[0]}", "keywords": ", ".join([ f"{service.name_en} {location.name_en}", f"{location.name_en} {service.name_en}", *service.keywords, f"{service.category} {location.name_en}" ]), "canonical": f"https://{self.brand.website}/{location.id}/{service.id}/", "og:title": f"{service.name_en} in {location.name_en} - {self.brand.name_en}", "og:description": f"Professional {service.name_en} services in {location.name_en}. " f"Book your consultation today.", "og:image": f"https://{self.brand.website}/images/{service.id}-{location.id}-og.jpg" } def generate_schema_markup(self, service: Service, location: Location) -> str: """Generate JSON-LD schema markup""" schema = { "@context": "https://schema.org", "@type": "MedicalBusiness", "name": f"{self.brand.name_en} - {location.name_en}", "url": f"https://{self.brand.website}", "telephone": self.brand.phone, "email": self.brand.email, "address": { "@type": "PostalAddress", "streetAddress": location.full_address, "addressLocality": location.name_en, "addressCountry": "KR" }, "geo": { "@type": "GeoCoordinates", "latitude": location.latitude, "longitude": location.longitude }, "areaServed": { "@type": "City", "name": location.name_en }, "availableService": { "@type": "MedicalProcedure", "name": service.name_en, "description": service.description }, "priceRange": service.price_range } return json.dumps(schema, indent=2, ensure_ascii=False) def generate_content_variations(self, service: Service, location: Location) -> Dict[str, List[str]]: """Generate content variations for uniqueness""" return { "hero_headlines": [ f"Professional {service.name_en} in {location.name_en}", f"{location.name_en}'s Premier {service.name_en} {service.category}", f"Expert {service.name_en} Services for {location.name_en} Residents", f"Transform Your Look with {service.name_en} in {location.name_en}" ], "intro_paragraphs": [ f"Welcome to {self.brand.name_en}, where we specialize in providing exceptional " f"{service.name_en} services to the {location.name_en} community. " f"Our state-of-the-art facility, conveniently located near {location.landmarks[0]}, " f"combines advanced technology with personalized care.", f"Looking for trusted {service.name_en} in {location.name_en}? " f"At {self.brand.name_en}, we've been serving the {location.demographics} " f"for over {datetime.now().year - self.brand.established_year} years. " f"Our expert team understands the unique needs of {location.name_en} residents.", f"Discover why {location.name_en} residents choose {self.brand.name_en} " f"for their {service.name_en} needs. Located just minutes from " f"{', '.join(location.subway_stations[:2])}, we offer {service.category} " f"services that deliver remarkable results." ], "cta_buttons": [ f"Book Your {location.name_en} Consultation", f"Schedule {service.name_en} Today", f"Get Started in {location.name_en}", f"Reserve Your Appointment" ], "trust_signals": [ f"Trusted by {location.name_en} residents since {self.brand.established_year}", f"Over 10,000 successful {service.category} treatments", f"5-star rated {service.name_en} clinic in {location.name_en}", f"Certified specialists serving {location.demographics}" ] } def localize_content(self, content: str, service: Service, location: Location) -> str: """Add local elements to content""" local_elements = { "transportation": f"Easily accessible via {', '.join(location.subway_stations)} stations", "landmarks": f"Located near {' and '.join(location.landmarks[:2])}", "community": f"Proud to serve the {location.name_en} community", "convenience": f"Convenient for {location.demographics} in {location.name_en}", "local_stats": f"Join thousands of satisfied patients from {location.name_en}" } # Add local elements naturally throughout content for key, value in local_elements.items(): placeholder = f"[LOCAL_{key.upper()}]" if placeholder in content: content = content.replace(placeholder, value) return content def generate_page(self, service: Service, location: Location, template_name: str = "gateway-page-medical.md") -> str: """Generate a complete gateway page""" # Load template template = self.load_template(template_name) # Generate components meta_tags = self.generate_meta_tags(service, location) schema = self.generate_schema_markup(service, location) variations = self.generate_content_variations(service, location) # Replace placeholders in template replacements = { "[Medical Service]": service.name_en, "[Location]": location.name_en, "[location]": location.name_en.lower(), "[Clinic Name]": self.brand.name_en, "[service-slug]": service.id, "[X years]": str(datetime.now().year - self.brand.established_year), "[specific address near landmark]": f"{location.full_address}, near {location.landmarks[0]}", "[nearby subway/bus stations]": ", ".join(location.subway_stations), "[certification details]": ", ".join(self.brand.certifications[:2]), "[equipment type]": f"{service.category} equipment", "[duration]": service.procedure_time, "[Medical Specialty]": service.category, "[phone-number]": self.brand.phone, "[website-url]": f"https://{self.brand.website}", "[page-url]": f"https://{self.brand.website}/{location.id}/{service.id}/", "[latitude]": str(location.latitude), "[longitude]": str(location.longitude), } # Apply replacements content = template for placeholder, value in replacements.items(): content = content.replace(placeholder, value) # Add localized content content = self.localize_content(content, service, location) # Add schema markup at the end if not already present if '"@context": "https://schema.org"' not in content: content += f"\n\n\n" return content def generate_batch(self, services: List[Service], locations: List[Location], output_dir: str = "output/") -> List[str]: """Generate multiple gateway pages""" output_path = Path(output_dir) output_path.mkdir(parents=True, exist_ok=True) generated_files = [] for location in locations: location_dir = output_path / location.id location_dir.mkdir(exist_ok=True) for service in services: # Generate content content = self.generate_page(service, location) # Save to file filename = f"{service.id}-{location.id}.md" filepath = location_dir / filename with open(filepath, 'w', encoding='utf-8') as f: f.write(content) generated_files.append(str(filepath)) print(f"✓ Generated: {filepath}") # Generate index file self.generate_index(services, locations, output_path) return generated_files def generate_index(self, services: List[Service], locations: List[Location], output_path: Path): """Generate an index of all created pages""" index_content = f"# Gateway Pages Index - {self.brand.name_en}\n\n" index_content += f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}\n\n" index_content += "## Pages by Location\n\n" for location in locations: index_content += f"### {location.name_en}\n" for service in services: url = f"/{location.id}/{service.id}/" index_content += f"- [{service.name_en} in {location.name_en}]({url})\n" index_content += "\n" index_content += "## Pages by Service\n\n" for service in services: index_content += f"### {service.name_en}\n" for location in locations: url = f"/{location.id}/{service.id}/" index_content += f"- [{location.name_en}]({url})\n" index_content += "\n" index_content += f"\n---\nTotal Pages Generated: {len(services) * len(locations)}\n" with open(output_path / "index.md", 'w', encoding='utf-8') as f: f.write(index_content) def create_sample_data(): """Create sample data for testing""" # Sample brand brand = Brand( name_en="Jamie Clinic", name_kr="제이미 클리닉", website="www.jamieclinic.com", phone="+82-2-1234-5678", email="info@jamieclinic.com", established_year=2010, certifications=["ISO 9001", "KAHF Certified", "JCI Accredited"], unique_selling_points=[ "Same-day appointments available", "15+ years of experience", "Latest medical technology" ] ) # Sample locations locations = [ Location( id="gangnam", name_en="Gangnam", name_kr="강남", full_address="123 Teheran-ro, Gangnam-gu, Seoul", landmarks=["COEX", "Gangnam Station", "Samsung Station"], subway_stations=["Gangnam Station (Line 2)", "Sinnonhyeon Station (Line 9)"], demographics="Young professionals and affluent residents", latitude=37.4979, longitude=127.0276 ), Location( id="myeongdong", name_en="Myeongdong", name_kr="명동", full_address="456 Myeongdong-gil, Jung-gu, Seoul", landmarks=["Myeongdong Cathedral", "Lotte Department Store"], subway_stations=["Myeongdong Station (Line 4)", "Euljiro 1-ga Station (Line 2)"], demographics="Tourists and young shoppers", latitude=37.5636, longitude=126.9869 ) ] # Sample services services = [ Service( id="laser-hair-removal", name_en="Laser Hair Removal", name_kr="레이저 제모", category="Dermatology", description="Advanced laser technology for permanent hair reduction", keywords=["permanent hair removal", "IPL", "diode laser"], procedure_time="30-60 minutes", recovery_time="No downtime", price_range="₩₩₩" ), Service( id="botox", name_en="Botox Treatment", name_kr="보톡스", category="Cosmetic Dermatology", description="FDA-approved botulinum toxin for wrinkle reduction", keywords=["wrinkle treatment", "anti-aging", "facial rejuvenation"], procedure_time="15-30 minutes", recovery_time="No downtime", price_range="₩₩₩₩" ) ] return brand, locations, services def main(): """Main execution function""" print("=" * 60) print("Gateway Page Content Generator") print("=" * 60) # Get sample data brand, locations, services = create_sample_data() # Initialize generator generator = GatewayPageGenerator(brand) # Generate pages print(f"\nGenerating {len(services) * len(locations)} gateway pages...") print("-" * 40) generated_files = generator.generate_batch(services, locations) print("-" * 40) print(f"\n✅ Successfully generated {len(generated_files)} pages!") print(f"📁 Output directory: output/") print(f"📋 Index file created: output/index.md") # Generate report print("\n" + "=" * 60) print("GENERATION REPORT") print("=" * 60) print(f"Brand: {brand.name_en}") print(f"Locations: {', '.join([loc.name_en for loc in locations])}") print(f"Services: {', '.join([svc.name_en for svc in services])}") print(f"Total Pages: {len(generated_files)}") print(f"Timestamp: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") print("=" * 60) if __name__ == "__main__": main()