270 lines
6.7 KiB
TypeScript
270 lines
6.7 KiB
TypeScript
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,
|
|
})),
|
|
};
|
|
}
|