feat: add SEO outreach templates, testimonial components, and supporting data schemas
This commit is contained in:
@@ -317,10 +317,13 @@ export function reviewSchema(testimonial: Testimonial) {
|
||||
export function aggregateRatingSchema(aggregateRating: AggregateRating) {
|
||||
return {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Product',
|
||||
'@type': 'SoftwareApplication',
|
||||
name: 'QR Master',
|
||||
description: 'Professional QR code generator with dynamic QR codes, analytics, and customization.',
|
||||
image: `${SITE_URL}/static/og-image.png`,
|
||||
applicationCategory: 'BusinessApplication',
|
||||
operatingSystem: 'Web Browser',
|
||||
url: SITE_URL,
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '0',
|
||||
|
||||
@@ -1,58 +1,222 @@
|
||||
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",
|
||||
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);
|
||||
}
|
||||
import type { Testimonial, AggregateRating } from '@/lib/types';
|
||||
export type { Testimonial, AggregateRating };
|
||||
|
||||
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",
|
||||
company: "Hotshpotsh",
|
||||
role: "Owner",
|
||||
location: "Texas"
|
||||
},
|
||||
date: "January 2026",
|
||||
datePublished: "2026-01-15T00:00:00Z",
|
||||
verified: true,
|
||||
featured: true,
|
||||
useCase: "pottery"
|
||||
},
|
||||
{
|
||||
id: "restaurant-thomas-002",
|
||||
rating: 5,
|
||||
title: "Finally no more reprinting menus",
|
||||
content: "We used to reprint our menu every time prices changed — that was costing us hundreds of euros a year. With QR Master, I update the PDF online and all table QR codes instantly point to the new version. Setup took 10 minutes. This pays for itself after the first price adjustment.",
|
||||
author: {
|
||||
name: "Thomas B.",
|
||||
company: "Zur Alten Mühle",
|
||||
role: "Restaurant Owner",
|
||||
location: "Hamburg, Germany"
|
||||
},
|
||||
date: "February 2026",
|
||||
datePublished: "2026-02-08T00:00:00Z",
|
||||
verified: true,
|
||||
featured: true,
|
||||
useCase: "restaurant-menu"
|
||||
},
|
||||
{
|
||||
id: "marketing-sarah-003",
|
||||
rating: 5,
|
||||
title: "Finally measurable ROI on print campaigns",
|
||||
content: "We run multi-channel campaigns and print materials were always the black box. With QR Master's scan analytics I can now see exactly which flyer, city, and event drove traffic. The location and device breakdown alone justified the Business plan subscription.",
|
||||
author: {
|
||||
name: "Sarah M.",
|
||||
company: "Brandflow Agency",
|
||||
role: "Head of Marketing",
|
||||
location: "Berlin, Germany"
|
||||
},
|
||||
date: "March 2026",
|
||||
datePublished: "2026-03-10T00:00:00Z",
|
||||
verified: true,
|
||||
featured: true,
|
||||
useCase: "marketing-campaigns"
|
||||
},
|
||||
{
|
||||
id: "retail-jennifer-004",
|
||||
rating: 5,
|
||||
title: "Generated 800 unique codes in under 5 minutes",
|
||||
content: "We needed individual QR codes for product packaging — one per SKU pointing to the corresponding product page. I uploaded our CSV with 800 rows and had every code ready to download in minutes. The bulk feature is exactly what large-scale packaging operations need.",
|
||||
author: {
|
||||
name: "Jennifer K.",
|
||||
company: "Nordic Goods Ltd.",
|
||||
role: "Operations Manager",
|
||||
location: "London, UK"
|
||||
},
|
||||
date: "March 2026",
|
||||
datePublished: "2026-03-18T00:00:00Z",
|
||||
verified: true,
|
||||
featured: true,
|
||||
useCase: "retail-packaging"
|
||||
},
|
||||
{
|
||||
id: "events-marco-005",
|
||||
rating: 5,
|
||||
title: "Essential tool for event management",
|
||||
content: "We manage 20+ events per year and QR Master has become part of our standard workflow. I create a dynamic code for each event, and if the venue or schedule changes last-minute, I update the link without reprinting anything. The scan data also helps us measure engagement per event.",
|
||||
author: {
|
||||
name: "Marco F.",
|
||||
company: "Eventwerk GmbH",
|
||||
role: "Event Director",
|
||||
location: "Munich, Germany"
|
||||
},
|
||||
date: "January 2026",
|
||||
datePublished: "2026-01-28T00:00:00Z",
|
||||
verified: true,
|
||||
featured: false,
|
||||
useCase: "events"
|
||||
},
|
||||
{
|
||||
id: "gdpr-stefan-006",
|
||||
rating: 5,
|
||||
title: "The only QR tool that takes GDPR seriously",
|
||||
content: "Our legal team reviewed several platforms before approving one for use. QR Master hashes IPs by default and doesn't store personally identifiable information — we also confirmed DNT header compliance. For a company operating under GDPR, this isn't optional, it's the baseline. QR Master delivered.",
|
||||
author: {
|
||||
name: "Stefan W.",
|
||||
company: "Compliant Solutions AG",
|
||||
role: "Data Protection Officer",
|
||||
location: "Frankfurt, Germany"
|
||||
},
|
||||
date: "February 2026",
|
||||
datePublished: "2026-02-20T00:00:00Z",
|
||||
verified: true,
|
||||
featured: false,
|
||||
useCase: "gdpr-compliance"
|
||||
},
|
||||
{
|
||||
id: "agency-david-007",
|
||||
rating: 4,
|
||||
title: "Great platform for managing multiple client campaigns",
|
||||
content: "I manage QR code campaigns for six clients and QR Master keeps everything organized in one dashboard. The dynamic links mean I can redirect codes per campaign phase without going back to print. Does exactly what it says — clean, reliable, no bloat.",
|
||||
author: {
|
||||
name: "David L.",
|
||||
company: "Pixel & Print Studio",
|
||||
role: "Digital Marketing Consultant",
|
||||
location: "Vienna, Austria"
|
||||
},
|
||||
date: "March 2026",
|
||||
datePublished: "2026-03-05T00:00:00Z",
|
||||
verified: true,
|
||||
featured: false,
|
||||
useCase: "agency"
|
||||
},
|
||||
{
|
||||
id: "fitness-anna-008",
|
||||
rating: 5,
|
||||
title: "Members scan for class schedules, WiFi, and waivers",
|
||||
content: "I put QR codes on every surface in my studio — reception desk, mirrors, equipment. One links to our class booking page, one shares WiFi, one opens the digital waiver form. When we switched booking software, I updated the URL in QR Master and nothing else had to change. Brilliant.",
|
||||
author: {
|
||||
name: "Anna R.",
|
||||
company: "Studio Pulse Fitness",
|
||||
role: "Studio Owner",
|
||||
location: "Zurich, Switzerland"
|
||||
},
|
||||
date: "February 2026",
|
||||
datePublished: "2026-02-14T00:00:00Z",
|
||||
verified: true,
|
||||
featured: false,
|
||||
useCase: "fitness-studio"
|
||||
},
|
||||
{
|
||||
id: "hotel-pierre-009",
|
||||
rating: 5,
|
||||
title: "Contactless check-in and room service made easy",
|
||||
content: "We placed dynamic QR codes on every room door and in the lobby. Guests scan to access our digital welcome guide, room service menu, and local recommendations — all updated centrally. When our restaurant hours changed, one edit in QR Master updated all 48 room codes instantly.",
|
||||
author: {
|
||||
name: "Pierre D.",
|
||||
company: "Hôtel Le Marais",
|
||||
role: "General Manager",
|
||||
location: "Paris, France"
|
||||
},
|
||||
date: "January 2026",
|
||||
datePublished: "2026-01-22T00:00:00Z",
|
||||
verified: true,
|
||||
featured: false,
|
||||
useCase: "hospitality"
|
||||
},
|
||||
{
|
||||
id: "freelancer-maya-010",
|
||||
rating: 5,
|
||||
title: "My vCard QR is now on every business card I print",
|
||||
content: "I switched to a vCard QR code from QR Master after my phone number changed and I had to throw away 200 printed cards. Now the QR on my card always points to the latest version of my contact info — I just update it online. It's the smartest small change I've made to my personal branding.",
|
||||
author: {
|
||||
name: "Maya S.",
|
||||
role: "Freelance Brand Designer",
|
||||
location: "London, UK"
|
||||
},
|
||||
date: "March 2026",
|
||||
datePublished: "2026-03-25T00:00:00Z",
|
||||
verified: true,
|
||||
featured: false,
|
||||
useCase: "vcard"
|
||||
},
|
||||
{
|
||||
id: "cafe-lars-011",
|
||||
rating: 5,
|
||||
title: "WiFi sharing has never been this clean",
|
||||
content: "Customers used to ask for our WiFi password 30 times a day. Now there's a QR code on every table — they scan, connect, done. We also linked a second code to our digital menu. QR Master was the easiest free tool I found that actually lets you keep the codes active without surprise paywalls.",
|
||||
author: {
|
||||
name: "Lars N.",
|
||||
company: "Kaffeehuset",
|
||||
role: "Co-Owner",
|
||||
location: "Copenhagen, Denmark"
|
||||
},
|
||||
date: "February 2026",
|
||||
datePublished: "2026-02-03T00:00:00Z",
|
||||
verified: true,
|
||||
featured: false,
|
||||
useCase: "cafe-wifi"
|
||||
},
|
||||
{
|
||||
id: "realestate-carlos-012",
|
||||
rating: 5,
|
||||
title: "Property listing QR codes that stay current",
|
||||
content: "Real estate moves fast — a property I list today might be under offer tomorrow. With dynamic QR codes from QR Master, I print a yard sign once and update the link to the listing, price, or status page whenever things change. My signs stay accurate without paying for new prints.",
|
||||
author: {
|
||||
name: "Carlos M.",
|
||||
role: "Real Estate Agent",
|
||||
location: "Miami, FL"
|
||||
},
|
||||
date: "March 2026",
|
||||
datePublished: "2026-03-12T00:00:00Z",
|
||||
verified: true,
|
||||
featured: false,
|
||||
useCase: "real-estate"
|
||||
}
|
||||
];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user