/** * Structured Data (JSON-LD) Generators for Canina Iran * Conforming to Schema.org and Google Search Rich Results guidelines */ export interface OrganizationSchemaOptions { name?: string; alternateName?: string; url?: string; logo?: string; description?: string; telephone?: string; email?: string; address?: { streetAddress?: string; addressLocality?: string; addressRegion?: string; postalCode?: string; addressCountry?: string; }; sameAs?: string[]; } export function generateOrganizationSchema(options: OrganizationSchemaOptions = {}) { const brandName = options.name || 'کنینا ایران'; const siteUrl = options.url || 'https://canina.ir'; const logoUrl = options.logo || `${siteUrl}/assets/images/logo.png`; return { '@context': 'https://schema.org', '@type': 'Organization', '@id': `${siteUrl}#organization`, name: brandName, alternateName: options.alternateName || 'Canina pharma GmbH Iran Representative', url: siteUrl, logo: { '@type': 'ImageObject', url: logoUrl, caption: brandName, }, image: logoUrl, description: options.description || 'نماینده رسمی و انحصاری مکمل‌های دارویی و درمانی Canina pharma GmbH آلمان در ایران.', telephone: options.telephone || '+989211231517', email: options.email || 'caninairan@gmail.com', address: { '@type': 'PostalAddress', streetAddress: options.address?.streetAddress || 'جردن، خیابان سعیدی، ساختمان کنینا، طبقه ۵', addressLocality: options.address?.addressLocality || 'تهران', addressRegion: options.address?.addressRegion || 'تهران', postalCode: options.address?.postalCode || '1967812345', addressCountry: options.address?.addressCountry || 'IR', }, sameAs: options.sameAs || [ 'https://instagram.com/caninairan', 'https://t.me/caninairan', 'https://www.canina.de', ], contactPoint: [ { '@type': 'ContactPoint', telephone: options.telephone || '+989211231517', contactType: 'customer service', availableLanguage: ['Persian', 'English', 'German'], areaServed: 'IR', }, ], }; } export function generateLocalBusinessSchema(options: OrganizationSchemaOptions = {}) { const siteUrl = options.url || 'https://canina.ir'; const brandName = options.name || 'کنینا ایران'; const logoUrl = options.logo || `${siteUrl}/assets/images/logo.png`; return { '@context': 'https://schema.org', '@type': 'VeterinaryCare', '@id': `${siteUrl}#localbusiness`, name: `${brandName} - دفتر مرکزی و پشتیبانی تخصصی`, image: logoUrl, url: siteUrl, telephone: options.telephone || '+989211231517', priceRange: '$$', address: { '@type': 'PostalAddress', streetAddress: options.address?.streetAddress || 'تهران، جردن، خیابان سعیدی، ساختمان کنینا، طبقه ۵، واحد ۱۹', addressLocality: options.address?.addressLocality || 'تهران', addressRegion: options.address?.addressRegion || 'تهران', postalCode: options.address?.postalCode || '1967812345', addressCountry: 'IR', }, geo: { '@type': 'GeoCoordinates', latitude: 35.7785, longitude: 51.4172, }, openingHoursSpecification: [ { '@type': 'OpeningHoursSpecification', dayOfWeek: ['Saturday', 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday'], opens: '09:00', closes: '18:00', }, ], sameAs: options.sameAs || [ 'https://instagram.com/caninairan', 'https://t.me/caninairan', ], }; } export interface B2BServiceSchemaOptions { serviceName?: string; description?: string; siteUrl?: string; } export function generateB2BServiceSchema(options: B2BServiceSchemaOptions = {}) { const siteUrl = options.siteUrl || 'https://canina.ir'; return { '@context': 'https://schema.org', '@type': 'Service', '@id': `${siteUrl}/b2b#service`, name: options.serviceName || 'تأمین عمده و همکاری تجاری مکمل‌های دارویی کنینا آلمان', serviceType: 'B2B Veterinary Supply & Wholesale', provider: { '@type': 'Organization', name: 'کنینا ایران', url: siteUrl, logo: `${siteUrl}/assets/images/logo.png`, }, areaServed: { '@type': 'Country', name: 'Iran', }, description: options.description || 'تأمین مستقیم، پخش عمده و اعطای نمایندگی مکمل‌های تخصصی دامپزشکی Canina آلمان به کلینیک‌ها، بیمارستان‌های دامپزشکی و پت‌شاپ‌های معتبر سراسر کشور.', offers: { '@type': 'Offer', availability: 'https://schema.org/InStock', businessFunction: 'http://purl.org/goodrelations/v1#ProvideService', }, }; } export interface MedicalWebPageSchemaOptions { title: string; description: string; url: string; datePublished?: string; dateModified?: string; medicalAudience?: string; aspects?: string[]; } export function generateMedicalWebPageSchema(options: MedicalWebPageSchemaOptions) { return { '@context': 'https://schema.org', '@type': 'MedicalWebPage', name: options.title, headline: options.title, description: options.description, url: options.url, datePublished: options.datePublished || '2025-01-01', dateModified: options.dateModified || new Date().toISOString(), medicalAudience: { '@type': 'MedicalAudience', audienceType: options.medicalAudience || 'Veterinarians, Pet Care Professionals, and Pet Owners', }, publisher: { '@type': 'Organization', name: 'کنینا ایران', url: 'https://canina.ir', }, about: options.aspects?.map((aspect) => ({ '@type': 'MedicalCondition', name: aspect, })) || [], }; } export interface VideoObjectSchemaOptions { name: string; description: string; thumbnailUrl: string; uploadDate: string; contentUrl?: string; embedUrl?: string; duration?: string; } export function generateVideoObjectSchema(options: VideoObjectSchemaOptions) { return { '@context': 'https://schema.org', '@type': 'VideoObject', name: options.name, description: options.description, thumbnailUrl: [options.thumbnailUrl], uploadDate: options.uploadDate, contentUrl: options.contentUrl, embedUrl: options.embedUrl || options.contentUrl, duration: options.duration || 'PT3M30S', publisher: { '@type': 'Organization', name: 'کنینا ایران', logo: { '@type': 'ImageObject', url: 'https://canina.ir/assets/images/logo.png', }, }, }; } export interface BreadcrumbItem { name: string; url: string; } export function generateBreadcrumbSchema(items: BreadcrumbItem[]) { return { '@context': 'https://schema.org', '@type': 'BreadcrumbList', itemListElement: items.map((item, index) => ({ '@type': 'ListItem', position: index + 1, name: item.name, item: item.url, })), }; } /** * SEC-017: Safely serialize schema data to JSON string for application/ld+json script tags, * escaping any '' or '<' characters that could break out of the script block. */ export function safeJsonLd(schema: unknown): string { return JSON.stringify(schema) .replace(//g, '\\u003e') .replace(/&/g, '\\u0026'); }