export interface BreadcrumbItem { name: string; url: string; } export interface BlogPost { title: string; description: string; slug: string; author: string; authorUrl: string; datePublished: string; dateModified: string; image: string; } export interface FAQItem { question: string; answer: string; } export interface ProductOffer { name: string; price: string; priceCurrency: string; availability: string; url: string; } export interface HowToStep { name: string; text: string; url?: string; } export interface HowToTask { name: string; description: string; steps: HowToStep[]; totalTime?: string; } const BASE_URL = 'https://www.qrmaster.net'; function toAbsoluteUrl(path: string): string { if (path.startsWith('http')) return path; return `${BASE_URL}${path.startsWith('/') ? '' : '/'}${path}`; } export function organizationSchema() { return { '@context': 'https://schema.org', '@type': 'Organization', '@id': `${BASE_URL}/#organization`, name: 'QR Master', alternateName: 'QRMaster', url: BASE_URL, logo: { '@type': 'ImageObject', url: `${BASE_URL}/og-image.png`, width: 1200, height: 630, }, image: `${BASE_URL}/og-image.png`, sameAs: [ 'https://twitter.com/qrmaster', ], contactPoint: { '@type': 'ContactPoint', contactType: 'Customer Support', email: 'support@qrmaster.net', availableLanguage: ['English', 'German'], }, description: 'B2B SaaS platform for dynamic QR code generation with analytics, branding, and bulk generation for enterprise marketing campaigns.', slogan: 'Dynamic QR codes that work smarter', foundingDate: '2025', areaServed: 'Worldwide', knowsAbout: [ 'QR Code Generation', 'Marketing Analytics', 'Campaign Tracking', 'Dynamic QR Codes', 'Bulk QR Generation', ], hasOfferCatalog: { '@type': 'OfferCatalog', name: 'QR Master Plans', itemListElement: [ { '@type': 'Offer', itemOffered: { '@type': 'SoftwareApplication', name: 'QR Master Free', applicationCategory: 'BusinessApplication', operatingSystem: 'Web Browser', offers: { '@type': 'Offer', price: '0', priceCurrency: 'EUR', }, aggregateRating: { '@type': 'AggregateRating', ratingValue: '4.8', ratingCount: '1250', }, }, }, { '@type': 'Offer', itemOffered: { '@type': 'SoftwareApplication', name: 'QR Master Pro', applicationCategory: 'BusinessApplication', operatingSystem: 'Web Browser', offers: { '@type': 'Offer', price: '9', priceCurrency: 'EUR', }, aggregateRating: { '@type': 'AggregateRating', ratingValue: '4.9', ratingCount: '850', }, }, }, ], }, mainEntityOfPage: BASE_URL, }; } export function websiteSchema() { return { '@context': 'https://schema.org', '@type': 'WebSite', '@id': `${BASE_URL}/#website`, name: 'QR Master', url: BASE_URL, inLanguage: 'en', mainEntityOfPage: BASE_URL, publisher: { '@id': `${BASE_URL}/#organization`, }, potentialAction: { '@type': 'SearchAction', target: { '@type': 'EntryPoint', urlTemplate: `${BASE_URL}/blog?q={search_term_string}`, }, 'query-input': 'required name=search_term_string', }, }; } export function breadcrumbSchema(items: BreadcrumbItem[]) { return { '@context': 'https://schema.org', '@type': 'BreadcrumbList', '@id': `${BASE_URL}${items[items.length - 1]?.url}#breadcrumb`, inLanguage: 'en', mainEntityOfPage: `${BASE_URL}${items[items.length - 1]?.url}`, itemListElement: items.map((item, index) => ({ '@type': 'ListItem', position: index + 1, name: item.name, item: toAbsoluteUrl(item.url), })), }; } export function blogPostingSchema(post: BlogPost) { return { '@context': 'https://schema.org', '@type': 'BlogPosting', '@id': `${BASE_URL}/blog/${post.slug}#article`, headline: post.title, description: post.description, image: toAbsoluteUrl(post.image), datePublished: post.datePublished, dateModified: post.dateModified, inLanguage: 'en', mainEntityOfPage: `${BASE_URL}/blog/${post.slug}`, author: { '@type': 'Person', name: post.author, url: post.authorUrl, }, publisher: { '@type': 'Organization', name: 'QR Master', url: BASE_URL, logo: { '@type': 'ImageObject', url: `${BASE_URL}/og-image.png`, width: 1200, height: 630, }, }, isPartOf: { '@type': 'Blog', '@id': `${BASE_URL}/blog#blog`, name: 'QR Master Blog', url: `${BASE_URL}/blog`, }, }; } export function faqPageSchema(faqs: FAQItem[]) { return { '@context': 'https://schema.org', '@type': 'FAQPage', '@id': `${BASE_URL}/faq#faqpage`, inLanguage: 'en', mainEntityOfPage: `${BASE_URL}/faq`, mainEntity: faqs.map((faq) => ({ '@type': 'Question', name: faq.question, acceptedAnswer: { '@type': 'Answer', text: faq.answer, }, })), }; } export function productSchema(product: { name: string; description: string; offers: ProductOffer[] }) { return { '@context': 'https://schema.org', '@type': 'Product', '@id': `${BASE_URL}/pricing#product`, name: product.name, description: product.description, inLanguage: 'en', mainEntityOfPage: `${BASE_URL}/pricing`, brand: { '@type': 'Organization', name: 'QR Master', }, offers: product.offers.map((offer) => ({ '@type': 'Offer', name: offer.name, price: offer.price, priceCurrency: offer.priceCurrency, availability: offer.availability, url: toAbsoluteUrl(offer.url), })), }; } export function howToSchema(task: HowToTask) { return { '@context': 'https://schema.org', '@type': 'HowTo', '@id': `${BASE_URL}/blog/${task.name.toLowerCase().replace(/\s+/g, '-')}#howto`, name: task.name, description: task.description, inLanguage: 'en', mainEntityOfPage: `${BASE_URL}/blog/${task.name.toLowerCase().replace(/\s+/g, '-')}`, totalTime: task.totalTime || 'PT5M', step: task.steps.map((step, index) => ({ '@type': 'HowToStep', position: index + 1, name: step.name, text: step.text, url: step.url ? toAbsoluteUrl(step.url) : undefined, })), }; }