feat: implement marketing comparison and alternatives hub with dedicated competitor landing pages

This commit is contained in:
Timo Knuth
2026-04-08 15:38:02 +02:00
parent a6fd2ed61f
commit 14c3cde7e6
10 changed files with 3569 additions and 4 deletions

View File

@@ -0,0 +1,158 @@
import React from 'react';
import type { Metadata } from 'next';
import Link from 'next/link';
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
import SeoJsonLd from '@/components/SeoJsonLd';
import { breadcrumbSchema } from '@/lib/schema';
import { MarketingPageTracker, TrackedCtaLink } from '@/components/marketing/MarketingAnalytics';
import { Button } from '@/components/ui/Button';
import { Card } from '@/components/ui/Card';
export const metadata: Metadata = {
title: {
absolute: 'QR Platform Comparisons | QR Master',
},
description:
'Head-to-head QR platform comparisons. See where QR Master fits against Beaconstac / Uniqode on pricing, analytics, privacy, and enterprise requirements.',
alternates: {
canonical: 'https://www.qrmaster.net/vs',
},
openGraph: {
title: 'QR Platform Comparisons | QR Master',
description:
'Head-to-head QR platform comparisons focused on pricing, analytics, GDPR, bulk creation, and enterprise fit.',
url: 'https://www.qrmaster.net/vs',
type: 'website',
images: ['/og-image.png'],
},
twitter: {
title: 'QR Platform Comparisons | QR Master',
description:
'Compare QR Master head-to-head with Beaconstac / Uniqode.',
},
};
const breadcrumbItems: BreadcrumbItem[] = [
{ name: 'Home', url: '/' },
{ name: 'Comparisons', url: '/vs' },
];
const pageSchema = {
'@context': 'https://schema.org',
'@type': 'CollectionPage',
name: 'QR Platform Comparisons',
url: 'https://www.qrmaster.net/vs',
description: 'Head-to-head comparison pages for QR Master against competing QR platforms.',
};
const comparisons = [
{
href: '/vs/beaconstac',
eyebrow: 'Head-to-head',
title: 'QR Master vs Beaconstac / Uniqode',
description:
'A detailed comparison of pricing, GDPR handling, analytics depth, bulk creation, simplicity, and enterprise requirements.',
},
];
export default function ComparisonsHubPage() {
return (
<>
<SeoJsonLd data={[pageSchema, breadcrumbSchema(breadcrumbItems)]} />
<MarketingPageTracker pageType="commercial" cluster="competitor" />
<div className="min-h-screen" style={{ backgroundColor: '#F8F7F4', color: '#18181B' }}>
<section className="border-b bg-white" style={{ borderColor: '#E4E0D9' }}>
<div className="container mx-auto max-w-7xl px-4 pb-20 pt-10 sm:px-6 lg:px-8">
<div className="mb-10">
<Breadcrumbs items={breadcrumbItems} />
</div>
<div className="max-w-3xl">
<div
className="mb-6 inline-block rounded px-3 py-1.5 text-xs font-semibold uppercase tracking-widest"
style={{ backgroundColor: '#DCFCE7', color: '#166534', letterSpacing: '0.12em' }}
>
QR Master comparisons
</div>
<h1
className="mb-6 text-4xl font-extrabold leading-[1.08] tracking-tight sm:text-5xl"
style={{ color: '#111110' }}
>
Head-to-head comparisons for teams choosing the right QR platform.
</h1>
<p className="mb-8 text-lg leading-relaxed" style={{ color: '#52525B' }}>
These pages are for direct platform decisions, not broad alternative browsing. If you already have two
tools in mind and want the tradeoffs laid out clearly, start here.
</p>
<div className="flex flex-col gap-3 sm:flex-row">
<TrackedCtaLink
href="/vs/beaconstac"
ctaLabel="Open Comparison"
ctaLocation="hero_primary"
pageType="commercial"
cluster="competitor"
>
<Button size="lg" className="h-13 w-full px-8 text-base sm:w-auto">
Open Comparison
</Button>
</TrackedCtaLink>
<TrackedCtaLink
href="/alternatives"
ctaLabel="Browse Alternatives"
ctaLocation="hero_secondary"
pageType="commercial"
cluster="competitor"
>
<Button variant="outline" size="lg" className="h-13 w-full px-8 text-base sm:w-auto">
Browse Alternatives
</Button>
</TrackedCtaLink>
</div>
</div>
</div>
</section>
<section className="py-24" style={{ backgroundColor: '#F8F7F4' }}>
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="mb-12 max-w-3xl">
<h2 className="mb-4 text-3xl font-bold tracking-tight sm:text-4xl" style={{ color: '#111110' }}>
Available Comparisons
</h2>
<p className="text-lg" style={{ color: '#71717A' }}>
Direct side-by-side analysis for pricing, privacy, analytics, and operational fit.
</p>
</div>
<div className="grid gap-6 md:grid-cols-2">
{comparisons.map((item) => (
<Link key={item.href} href={item.href} className="group block">
<Card
className="h-full rounded-xl border bg-white p-7 shadow-none transition-transform duration-150 group-hover:-translate-y-1"
style={{ borderColor: '#E4E0D9' }}
>
<p
className="mb-4 text-xs font-semibold uppercase tracking-widest"
style={{ color: '#71717A', letterSpacing: '0.12em' }}
>
{item.eyebrow}
</p>
<h3 className="mb-3 text-xl font-bold" style={{ color: '#18181B' }}>
{item.title}
</h3>
<p className="text-sm leading-relaxed" style={{ color: '#52525B' }}>
{item.description}
</p>
<p className="mt-6 text-sm font-semibold" style={{ color: '#166534' }}>
Read comparison
</p>
</Card>
</Link>
))}
</div>
</div>
</section>
</div>
</>
);
}