press releases

This commit is contained in:
Timo Knuth
2026-01-27 12:29:44 +01:00
parent be5db36b7f
commit 4dc7c29134
19 changed files with 606 additions and 16 deletions

View File

@@ -43,8 +43,8 @@ export const pillarMeta: PillarMeta[] = [
description: "Quishing prevention and safe QR rollouts.",
quickAnswer: "Security is critical for trust. Learn how to prevent 'Quishing' (QR Phishing), validate links, and ensure your QR code campaigns remain safe for your users.",
miniFaq: [
{ question: "What is Quishing?", answer: "<strong>Quishing</strong> (QR Phishing) tricks users into scanning malicious QR codes that steal credentials or install malware." },
{ question: "How to prevent QR code fraud?", answer: "Use short, branded links. Enable URL preview before redirect. Educate users to check the destination before scanning unknown codes." },
{ question: "What is Quishing?", answer: "<strong>Quishing</strong> (QR Phishing) tricks users into scanning malicious QR codes. <cite><a href='https://www.ic3.gov' target='_blank' rel='nofollow external' class='text-blue-600 hover:underline'>(Source: FBI IC3 Warning Jan 2026)</a></cite>" },
{ question: "How to prevent QR code fraud?", answer: "Verify the source. Malicious QR campaigns rose significantly in 2025. <cite><a href='https://bitly.com/blog/qr-code-statistics/' target='_blank' rel='nofollow external' class='text-blue-600 hover:underline'>(Source: Bitly Trends)</a></cite>" },
{ question: "Are dynamic QR codes secure?", answer: "Yes, when hosted on trusted platforms with HTTPS, access logs, and link expiration. Avoid free generators with sketchy redirects." },
{ question: "Can QR codes be hacked?", answer: "QR codes themselves can't be hacked, but attackers can overlay fake codes on legitimate ones. Use tamper-proof stickers and regular audits." }
],

View File

@@ -1,4 +1,4 @@
import type { BlogPost, AuthorProfile, PillarMeta } from "./types";
import type { BlogPost, AuthorProfile, PillarMeta, Testimonial, AggregateRating } from "./types";
const SITE_URL = "https://www.qrmaster.net";
@@ -244,3 +244,44 @@ export function articleSchema(params: {
url: params.url,
};
}
export function reviewSchema(testimonial: Testimonial) {
return {
'@context': 'https://schema.org',
'@type': 'Review',
itemReviewed: {
'@type': 'SoftwareApplication',
name: 'QR Master',
applicationCategory: 'BusinessApplication',
operatingSystem: 'Web Browser'
},
reviewRating: {
'@type': 'Rating',
ratingValue: testimonial.rating,
bestRating: 5,
worstRating: 1
},
author: {
'@type': 'Person',
name: testimonial.author.name
},
datePublished: testimonial.datePublished,
reviewBody: testimonial.content,
headline: testimonial.title
};
}
export function aggregateRatingSchema(aggregateRating: AggregateRating) {
return {
'@context': 'https://schema.org',
'@type': 'Product',
name: 'QR Master',
aggregateRating: {
'@type': 'AggregateRating',
ratingValue: aggregateRating.ratingValue,
reviewCount: aggregateRating.reviewCount,
bestRating: aggregateRating.bestRating,
worstRating: aggregateRating.worstRating
}
};
}

View File

@@ -0,0 +1,58 @@
export type Testimonial = {
id: string;
rating: number;
title: string;
content: string;
author: {
name: string;
location?: string;
company?: string;
role?: string;
};
date: string;
datePublished: string;
verified: boolean;
featured: boolean;
useCase?: string;
};
export type AggregateRating = {
ratingValue: number;
reviewCount: number;
bestRating: number;
worstRating: number;
};
export const testimonials: Testimonial[] = [
{
id: "pottery-claudia-knuth-001",
rating: 5,
title: "Perfect for my pottery",
content: "I use QR-Master for my pottery as a link to my homepage and as a digital business card. I place the codes directly on my pottery pieces so interested customers can instantly access my website. Reliable and practical a great solution!",
author: {
name: "Claudia Knuth",
company: "Hotshpotsh",
location: "Texas"
},
date: "January 2026",
datePublished: "2026-01-15T00:00:00Z",
verified: true,
featured: true,
useCase: "pottery"
}
];
export function getAggregateRating(): AggregateRating {
const ratings = testimonials.map(t => t.rating);
const avgRating = ratings.reduce((a, b) => a + b, 0) / ratings.length;
return {
ratingValue: Number(avgRating.toFixed(1)),
reviewCount: testimonials.length,
bestRating: 5,
worstRating: 1
};
}
export function getFeaturedTestimonials(): Testimonial[] {
return testimonials.filter(t => t.featured);
}

View File

@@ -65,3 +65,28 @@ export type PillarMeta = {
miniFaq?: FAQItem[];
order: number;
};
export type Testimonial = {
id: string;
rating: number;
title: string;
content: string;
author: {
name: string;
location?: string;
company?: string;
role?: string;
};
date: string;
datePublished: string;
verified: boolean;
featured: boolean;
useCase?: string;
};
export type AggregateRating = {
ratingValue: number;
reviewCount: number;
bestRating: number;
worstRating: number;
};