14 blog post schedule
This commit is contained in:
@@ -1,60 +1,44 @@
|
||||
export interface BreadcrumbItem {
|
||||
name: string;
|
||||
url: string;
|
||||
}
|
||||
import type { BlogPost, AuthorProfile, PillarMeta } from "./types";
|
||||
|
||||
export interface BlogPost {
|
||||
title: string;
|
||||
description: string;
|
||||
slug: string;
|
||||
author: string;
|
||||
authorUrl: string;
|
||||
datePublished: string;
|
||||
dateModified: string;
|
||||
image: string;
|
||||
}
|
||||
const SITE_URL = "https://www.qrmaster.net";
|
||||
|
||||
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;
|
||||
export function websiteSchema() {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebSite',
|
||||
'@id': `${SITE_URL}/#website`,
|
||||
name: 'QR Master',
|
||||
url: SITE_URL,
|
||||
inLanguage: 'en',
|
||||
mainEntityOfPage: SITE_URL,
|
||||
publisher: {
|
||||
'@id': `${SITE_URL}/#organization`,
|
||||
},
|
||||
potentialAction: {
|
||||
'@type': 'SearchAction',
|
||||
target: {
|
||||
'@type': 'EntryPoint',
|
||||
urlTemplate: `${SITE_URL}/blog?q={search_term_string}`,
|
||||
},
|
||||
'query-input': 'required name=search_term_string',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function organizationSchema() {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Organization',
|
||||
'@id': 'https://www.qrmaster.net/#organization',
|
||||
'@id': `${SITE_URL}/#organization`,
|
||||
name: 'QR Master',
|
||||
alternateName: 'QRMaster',
|
||||
url: 'https://www.qrmaster.net',
|
||||
url: SITE_URL,
|
||||
logo: {
|
||||
'@type': 'ImageObject',
|
||||
url: 'https://www.qrmaster.net/static/og-image.png',
|
||||
url: `${SITE_URL}/static/og-image.png`,
|
||||
width: 1200,
|
||||
height: 630,
|
||||
},
|
||||
image: 'https://www.qrmaster.net/static/og-image.png',
|
||||
sameAs: [
|
||||
'https://twitter.com/qrmaster',
|
||||
],
|
||||
@@ -64,139 +48,97 @@ export function organizationSchema() {
|
||||
email: 'support@qrmaster.net',
|
||||
availableLanguage: ['en', 'de'],
|
||||
},
|
||||
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',
|
||||
image: 'https://www.qrmaster.net/static/og-image.png',
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '0',
|
||||
priceCurrency: 'EUR',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Offer',
|
||||
itemOffered: {
|
||||
'@type': 'SoftwareApplication',
|
||||
name: 'QR Master Pro',
|
||||
applicationCategory: 'BusinessApplication',
|
||||
operatingSystem: 'Web Browser',
|
||||
image: 'https://www.qrmaster.net/static/og-image.png',
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '9',
|
||||
priceCurrency: 'EUR',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function websiteSchema() {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebSite',
|
||||
'@id': 'https://www.qrmaster.net/#website',
|
||||
name: 'QR Master',
|
||||
url: 'https://www.qrmaster.net',
|
||||
inLanguage: 'en',
|
||||
mainEntityOfPage: 'https://www.qrmaster.net',
|
||||
publisher: {
|
||||
'@id': 'https://www.qrmaster.net/#organization',
|
||||
},
|
||||
potentialAction: {
|
||||
'@type': 'SearchAction',
|
||||
target: {
|
||||
'@type': 'EntryPoint',
|
||||
urlTemplate: 'https://www.qrmaster.net/blog?q={search_term_string}',
|
||||
},
|
||||
'query-input': 'required name=search_term_string',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function breadcrumbSchema(items: BreadcrumbItem[]) {
|
||||
export function blogPostingSchema(post: BlogPost, author?: AuthorProfile) {
|
||||
const url = `${SITE_URL}/blog/${post.slug}`;
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'BreadcrumbList',
|
||||
'@id': `https://www.qrmaster.net${items[items.length - 1]?.url}#breadcrumb`,
|
||||
inLanguage: 'en',
|
||||
mainEntityOfPage: `https://www.qrmaster.net${items[items.length - 1]?.url}`,
|
||||
itemListElement: items.map((item, index) => ({
|
||||
'@type': 'ListItem',
|
||||
position: index + 1,
|
||||
name: item.name,
|
||||
item: `https://www.qrmaster.net${item.url}`,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
export function blogPostingSchema(post: BlogPost) {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'BlogPosting',
|
||||
'@id': `https://www.qrmaster.net/blog/${post.slug}#article`,
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BlogPosting",
|
||||
headline: post.title,
|
||||
description: post.description,
|
||||
image: post.image,
|
||||
url,
|
||||
datePublished: post.datePublished,
|
||||
dateModified: post.dateModified,
|
||||
inLanguage: 'en',
|
||||
mainEntityOfPage: `https://www.qrmaster.net/blog/${post.slug}`,
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: post.author,
|
||||
url: post.authorUrl,
|
||||
},
|
||||
dateModified: post.dateModified || post.datePublished,
|
||||
image: post.heroImage ? `${SITE_URL}${post.heroImage}` : undefined,
|
||||
author: author
|
||||
? {
|
||||
"@type": "Person",
|
||||
name: author.name,
|
||||
url: `${SITE_URL}/authors/${author.slug}`,
|
||||
sameAs: author.sameAs ?? undefined,
|
||||
knowsAbout: author.knowsAbout ?? undefined
|
||||
}
|
||||
: {
|
||||
"@type": "Organization",
|
||||
name: "QR Master"
|
||||
},
|
||||
publisher: {
|
||||
'@type': 'Organization',
|
||||
name: 'QR Master',
|
||||
url: 'https://www.qrmaster.net',
|
||||
"@type": "Organization",
|
||||
name: "QR Master",
|
||||
url: SITE_URL,
|
||||
logo: {
|
||||
'@type': 'ImageObject',
|
||||
url: 'https://www.qrmaster.net/static/og-image.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
},
|
||||
url: `${SITE_URL}/static/og-image.png`,
|
||||
}
|
||||
},
|
||||
isPartOf: {
|
||||
'@type': 'Blog',
|
||||
'@id': 'https://www.qrmaster.net/blog#blog',
|
||||
'@id': `${SITE_URL}/blog#blog`,
|
||||
name: 'QR Master Blog',
|
||||
url: 'https://www.qrmaster.net/blog',
|
||||
url: `${SITE_URL}/blog`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function faqPageSchema(faqs: FAQItem[]) {
|
||||
export function howToSchema(post: BlogPost, author?: AuthorProfile) {
|
||||
const url = `${SITE_URL}/blog/${post.slug}`;
|
||||
const steps = (post.keySteps ?? []).map((text, idx) => ({
|
||||
"@type": "HowToStep",
|
||||
position: idx + 1,
|
||||
name: `Step ${idx + 1}`,
|
||||
text
|
||||
}));
|
||||
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "HowTo",
|
||||
name: post.title,
|
||||
description: post.description,
|
||||
url: `${url}#howto`,
|
||||
step: steps,
|
||||
author: author
|
||||
? { "@type": "Person", name: author.name, url: `${SITE_URL}/authors/${author.slug}` }
|
||||
: undefined
|
||||
};
|
||||
}
|
||||
|
||||
export function pillarPageSchema(meta: PillarMeta, posts: BlogPost[]) {
|
||||
const url = `${SITE_URL}/learn/${meta.key}`;
|
||||
return {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebPage",
|
||||
name: meta.title,
|
||||
description: meta.description,
|
||||
url,
|
||||
mainEntity: {
|
||||
"@type": "ItemList",
|
||||
itemListElement: posts.map((p, i) => ({
|
||||
"@type": "ListItem",
|
||||
position: i + 1,
|
||||
url: `${SITE_URL}/blog/${p.slug}`,
|
||||
name: p.title
|
||||
}))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function faqPageSchema(faqs: { question: string, answer: string }[]) {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'FAQPage',
|
||||
'@id': 'https://www.qrmaster.net/faq#faqpage',
|
||||
inLanguage: 'en',
|
||||
mainEntityOfPage: 'https://www.qrmaster.net/faq',
|
||||
mainEntity: faqs.map((faq) => ({
|
||||
'@type': 'Question',
|
||||
name: faq.question,
|
||||
@@ -208,76 +150,97 @@ export function faqPageSchema(faqs: FAQItem[]) {
|
||||
};
|
||||
}
|
||||
|
||||
export function productSchema(product: { name: string; description: string; offers: ProductOffer[] }) {
|
||||
export function breadcrumbSchema(items: { name: string; url: string }[]) {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Product',
|
||||
'@id': 'https://www.qrmaster.net/pricing#product',
|
||||
name: product.name,
|
||||
description: product.description,
|
||||
inLanguage: 'en',
|
||||
mainEntityOfPage: 'https://www.qrmaster.net/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: offer.url,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
export function howToSchema(task: HowToTask) {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'HowTo',
|
||||
'@id': `https://www.qrmaster.net/blog/${task.name.toLowerCase().replace(/\s+/g, '-')}#howto`,
|
||||
name: task.name,
|
||||
description: task.description,
|
||||
inLanguage: 'en',
|
||||
mainEntityOfPage: `https://www.qrmaster.net/blog/${task.name.toLowerCase().replace(/\s+/g, '-')}`,
|
||||
totalTime: task.totalTime || 'PT5M',
|
||||
step: task.steps.map((step, index) => ({
|
||||
'@type': 'HowToStep',
|
||||
'@type': 'BreadcrumbList',
|
||||
itemListElement: items.map((item, index) => ({
|
||||
'@type': 'ListItem',
|
||||
position: index + 1,
|
||||
name: step.name,
|
||||
text: step.text,
|
||||
url: step.url,
|
||||
name: item.name,
|
||||
item: item.url.startsWith('http') ? item.url : `https://www.qrmaster.net${item.url}`,
|
||||
})),
|
||||
};
|
||||
}
|
||||
|
||||
export function articleSchema(article: { headline: string; description: string; image: string; datePublished: string; dateModified: string; author: string; url: string }) {
|
||||
export function softwareApplicationSchema() {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'SoftwareApplication',
|
||||
name: 'QR Master',
|
||||
applicationCategory: 'BusinessApplication',
|
||||
operatingSystem: 'Web Browser',
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '0',
|
||||
priceCurrency: 'EUR'
|
||||
},
|
||||
publisher: {
|
||||
'@id': `${SITE_URL}/#organization`,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function authorPageSchema(author: AuthorProfile, posts?: BlogPost[]) {
|
||||
const url = `${SITE_URL}/authors/${author.slug}`;
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'ProfilePage',
|
||||
mainEntity: {
|
||||
'@type': 'Person',
|
||||
'@id': url,
|
||||
name: author.name,
|
||||
jobTitle: author.role,
|
||||
description: author.bio,
|
||||
image: author.image ? `${SITE_URL}${author.image}` : undefined,
|
||||
sameAs: author.sameAs?.length ? author.sameAs : undefined,
|
||||
knowsAbout: author.knowsAbout?.length ? author.knowsAbout : undefined,
|
||||
url,
|
||||
},
|
||||
about: posts?.length
|
||||
? {
|
||||
'@type': 'ItemList',
|
||||
itemListElement: posts.map((p, i) => ({
|
||||
'@type': 'ListItem',
|
||||
position: i + 1,
|
||||
url: `${SITE_URL}/blog/${p.slug}`,
|
||||
name: p.title,
|
||||
})),
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function articleSchema(params: {
|
||||
headline: string;
|
||||
description: string;
|
||||
image?: string;
|
||||
datePublished: string;
|
||||
dateModified?: string;
|
||||
author: string;
|
||||
url?: string;
|
||||
}) {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Article',
|
||||
'@id': `${article.url}#article`,
|
||||
headline: article.headline,
|
||||
description: article.description,
|
||||
image: article.image,
|
||||
datePublished: article.datePublished,
|
||||
dateModified: article.dateModified,
|
||||
inLanguage: 'en',
|
||||
mainEntityOfPage: article.url,
|
||||
headline: params.headline,
|
||||
description: params.description,
|
||||
image: params.image,
|
||||
datePublished: params.datePublished,
|
||||
dateModified: params.dateModified || params.datePublished,
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: article.author,
|
||||
'@type': 'Organization',
|
||||
name: params.author,
|
||||
},
|
||||
publisher: {
|
||||
'@type': 'Organization',
|
||||
name: 'QR Master',
|
||||
url: 'https://www.qrmaster.net',
|
||||
url: SITE_URL,
|
||||
logo: {
|
||||
'@type': 'ImageObject',
|
||||
url: 'https://www.qrmaster.net/static/og-image.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
url: `${SITE_URL}/static/og-image.png`,
|
||||
},
|
||||
},
|
||||
url: params.url,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user