SEO
This commit is contained in:
@@ -14,7 +14,7 @@ const competitor = competitors['bitly'];
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Bitly QR Code Alternative – Purpose-Built for QR Campaigns | QR Master',
|
||||
absolute: 'QR Master vs Bitly QR Codes | Bitly Alternative',
|
||||
},
|
||||
description:
|
||||
'Looking for a Bitly alternative for QR codes? Bitly\'s Core plan costs $10/month but only allows 2 QR codes total. QR Master is purpose-built for QR code management — 50 codes at €9/month, bulk creation, GDPR analytics. From €0.',
|
||||
@@ -24,7 +24,7 @@ export const metadata: Metadata = {
|
||||
canonical: 'https://www.qrmaster.net/alternatives/bitly',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Bitly QR Code Alternative – Purpose-Built for QR Campaigns',
|
||||
title: 'QR Master vs Bitly QR Codes | Bitly Alternative',
|
||||
description:
|
||||
'Bitly\'s Core plan costs $10/month but only gives you 2 QR codes. QR Master gives you 50 dynamic QR codes at €9/month — purpose-built for QR workflows, bulk creation, and GDPR analytics.',
|
||||
url: 'https://www.qrmaster.net/alternatives/bitly',
|
||||
@@ -32,7 +32,7 @@ export const metadata: Metadata = {
|
||||
images: ['/og-image.png'],
|
||||
},
|
||||
twitter: {
|
||||
title: 'Bitly QR Code Alternative – Purpose-Built for QR Campaigns',
|
||||
title: 'QR Master vs Bitly QR Codes | Bitly Alternative',
|
||||
description:
|
||||
'Bitly gives you 2 QR codes for $10/month. QR Master gives you 50 at €9/month — purpose-built for real QR campaigns, not link shortening with QR as an afterthought.',
|
||||
},
|
||||
@@ -40,6 +40,34 @@ export const metadata: Metadata = {
|
||||
|
||||
const comparisonRows = competitor.features;
|
||||
|
||||
const atAGlanceRows = [
|
||||
{
|
||||
useCase: 'A couple of QR codes',
|
||||
bitly: 'Reasonable if you already pay for Bitly and only need 1-2 QR codes.',
|
||||
qrMaster: 'Free plan includes 3 active dynamic QR codes plus unlimited static codes.',
|
||||
},
|
||||
{
|
||||
useCase: 'Marketing campaign with many placements',
|
||||
bitly: 'Entry plans hit QR count limits quickly.',
|
||||
qrMaster: 'Pro includes 50 dynamic QR codes; Business includes 500.',
|
||||
},
|
||||
{
|
||||
useCase: 'Bulk QR creation',
|
||||
bitly: 'No dedicated bulk QR generator.',
|
||||
qrMaster: 'CSV and Excel upload creates up to 1,000 unique QR codes per batch.',
|
||||
},
|
||||
{
|
||||
useCase: 'QR campaign analytics',
|
||||
bitly: 'Strong link analytics, but QR is a secondary workflow.',
|
||||
qrMaster: 'QR-first scan analytics with device, country, time, and UTM context.',
|
||||
},
|
||||
{
|
||||
useCase: 'Migration risk',
|
||||
bitly: 'Printed codes depend on Bitly redirect infrastructure.',
|
||||
qrMaster: 'Re-create destinations before canceling Bitly and replace codes on the next print cycle.',
|
||||
},
|
||||
];
|
||||
|
||||
const faqItems = [
|
||||
{
|
||||
question: 'How many QR codes does Bitly allow per plan?',
|
||||
@@ -256,6 +284,41 @@ export default function BitlyAlternativePage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="border-b bg-white py-20" style={{ borderColor: '#E4E0D9' }}>
|
||||
<div className="container mx-auto max-w-5xl px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="mb-3 text-3xl font-bold tracking-tight sm:text-4xl" style={{ color: '#111110' }}>
|
||||
QR Master vs Bitly at a glance
|
||||
</h2>
|
||||
<p className="mb-10 text-lg" style={{ color: '#71717A' }}>
|
||||
Bitly is strongest as a link management platform. QR Master is stronger when QR codes are the main
|
||||
campaign asset and you need predictable pricing, bulk creation, and QR-specific reporting.
|
||||
</p>
|
||||
<div className="overflow-hidden rounded-xl border" style={{ borderColor: '#E4E0D9' }}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3" style={{ backgroundColor: '#F8F7F4' }}>
|
||||
{['Use case', 'Bitly', 'QR Master'].map((heading) => (
|
||||
<div key={heading} className="p-4 text-xs font-semibold uppercase tracking-wider" style={{ color: '#71717A' }}>
|
||||
{heading}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{atAGlanceRows.map((row, index) => (
|
||||
<div
|
||||
key={row.useCase}
|
||||
className="grid grid-cols-1 md:grid-cols-3"
|
||||
style={{
|
||||
borderTop: '1px solid #E4E0D9',
|
||||
backgroundColor: index % 2 === 0 ? '#FFFFFF' : '#FAFAF8',
|
||||
}}
|
||||
>
|
||||
<div className="p-4 text-sm font-semibold" style={{ color: '#18181B' }}>{row.useCase}</div>
|
||||
<div className="p-4 text-sm" style={{ color: '#52525B' }}>{row.bitly}</div>
|
||||
<div className="p-4 text-sm font-medium" style={{ color: '#166534' }}>{row.qrMaster}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Why Bitly is the Wrong Tool */}
|
||||
<section className="py-24" style={{ backgroundColor: '#F8F7F4' }}>
|
||||
<div className="container mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
|
||||
|
||||
@@ -14,7 +14,7 @@ const competitor = competitors['flowcode'];
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Flowcode Alternative – No Forced Branding or Scan Interstitials | QR Master',
|
||||
absolute: 'QR Master vs Flowcode | Flowcode Alternative Without Forced Branding',
|
||||
},
|
||||
description:
|
||||
'Looking for a Flowcode alternative? QR Master gives you clean, customizable QR codes without Flowcode\'s logo or scan-hijacking interstitial pages — from €0 free, Pro at €9/month.',
|
||||
@@ -24,7 +24,7 @@ export const metadata: Metadata = {
|
||||
canonical: 'https://www.qrmaster.net/alternatives/flowcode',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Flowcode Alternative – No Forced Branding or Scan Interstitials',
|
||||
title: 'QR Master vs Flowcode | Flowcode Alternative Without Forced Branding',
|
||||
description:
|
||||
'Flowcode puts its logo on your QR codes and routes scans through its own branded page. QR Master gives you full branding control from the start.',
|
||||
url: 'https://www.qrmaster.net/alternatives/flowcode',
|
||||
@@ -32,7 +32,7 @@ export const metadata: Metadata = {
|
||||
images: ['/og-image.png'],
|
||||
},
|
||||
twitter: {
|
||||
title: 'Flowcode Alternative – No Forced Branding or Scan Interstitials',
|
||||
title: 'QR Master vs Flowcode | Flowcode Alternative Without Forced Branding',
|
||||
description:
|
||||
'Flowcode puts its logo on your QR codes and routes scans through its own branded page. QR Master gives you full branding control from the start.',
|
||||
},
|
||||
@@ -40,6 +40,34 @@ export const metadata: Metadata = {
|
||||
|
||||
const comparisonRows = competitor.features;
|
||||
|
||||
const atAGlanceRows = [
|
||||
{
|
||||
useCase: 'Free branded QR codes',
|
||||
flowcode: 'Flowcode branding can appear in the code style and scan path on lower tiers.',
|
||||
qrMaster: 'No forced QR Master logo or branded interstitial page.',
|
||||
},
|
||||
{
|
||||
useCase: 'White-label brand control',
|
||||
flowcode: 'Meaningful white-label control is typically tied to higher paid tiers.',
|
||||
qrMaster: 'Custom colors and logo support start on Pro at EUR 9/month.',
|
||||
},
|
||||
{
|
||||
useCase: 'Direct scan experience',
|
||||
flowcode: 'Lower-tier scans may pass through a Flowcode-branded interstitial.',
|
||||
qrMaster: 'Dynamic codes redirect directly to the destination after scan logging.',
|
||||
},
|
||||
{
|
||||
useCase: 'Bulk QR creation',
|
||||
flowcode: 'No built-in CSV or Excel bulk QR generator.',
|
||||
qrMaster: 'Business supports up to 1,000 unique QR codes per bulk upload.',
|
||||
},
|
||||
{
|
||||
useCase: 'EU privacy posture',
|
||||
flowcode: 'US platform; EU teams should review data processing terms.',
|
||||
qrMaster: 'Scan analytics hash IPs server-side before storage.',
|
||||
},
|
||||
];
|
||||
|
||||
const faqItems = [
|
||||
{
|
||||
question: 'What is the Flowcode interstitial page and why does it matter?',
|
||||
@@ -238,6 +266,41 @@ export default function FlowcodeAlternativePage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="border-b bg-white py-20" style={{ borderColor: '#E4E0D9' }}>
|
||||
<div className="container mx-auto max-w-5xl px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="mb-3 text-3xl font-bold tracking-tight sm:text-4xl" style={{ color: '#111110' }}>
|
||||
QR Master vs Flowcode at a glance
|
||||
</h2>
|
||||
<p className="mb-10 text-lg" style={{ color: '#71717A' }}>
|
||||
Flowcode is design-forward. QR Master is the cleaner fit when you need a neutral QR code, direct scan
|
||||
experience, bulk creation, and predictable pricing.
|
||||
</p>
|
||||
<div className="overflow-hidden rounded-xl border" style={{ borderColor: '#E4E0D9' }}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3" style={{ backgroundColor: '#F8F7F4' }}>
|
||||
{['Use case', 'Flowcode', 'QR Master'].map((heading) => (
|
||||
<div key={heading} className="p-4 text-xs font-semibold uppercase tracking-wider" style={{ color: '#71717A' }}>
|
||||
{heading}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{atAGlanceRows.map((row, index) => (
|
||||
<div
|
||||
key={row.useCase}
|
||||
className="grid grid-cols-1 md:grid-cols-3"
|
||||
style={{
|
||||
borderTop: '1px solid #E4E0D9',
|
||||
backgroundColor: index % 2 === 0 ? '#FFFFFF' : '#FAFAF8',
|
||||
}}
|
||||
>
|
||||
<div className="p-4 text-sm font-semibold" style={{ color: '#18181B' }}>{row.useCase}</div>
|
||||
<div className="p-4 text-sm" style={{ color: '#52525B' }}>{row.flowcode}</div>
|
||||
<div className="p-4 text-sm font-medium" style={{ color: '#166534' }}>{row.qrMaster}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* The Real Problem with Flowcode */}
|
||||
<section className="py-24" style={{ backgroundColor: '#F8F7F4' }}>
|
||||
<div className="container mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
|
||||
|
||||
@@ -4,13 +4,14 @@ import Link from 'next/link';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { FAQSection } from '@/components/aeo/FAQSection';
|
||||
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 Code Platform Alternatives | QR Master',
|
||||
absolute: 'QR Master Alternatives: Compare QR Code Platforms',
|
||||
},
|
||||
description:
|
||||
'Compare QR Master with QR-Code-Generator.com, Flowcode, Beaconstac / Uniqode, and Bitly. Find the right QR alternative for pricing, branding, analytics, and bulk creation.',
|
||||
@@ -18,7 +19,7 @@ export const metadata: Metadata = {
|
||||
canonical: 'https://www.qrmaster.net/alternatives',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'QR Code Platform Alternatives | QR Master',
|
||||
title: 'QR Master Alternatives: Compare QR Code Platforms',
|
||||
description:
|
||||
'Clean comparisons for the most common QR code platform alternatives, from pricing traps to branding limits and enterprise overkill.',
|
||||
url: 'https://www.qrmaster.net/alternatives',
|
||||
@@ -26,7 +27,7 @@ export const metadata: Metadata = {
|
||||
images: ['/og-image.png'],
|
||||
},
|
||||
twitter: {
|
||||
title: 'QR Code Platform Alternatives | QR Master',
|
||||
title: 'QR Master Alternatives: Compare QR Code Platforms',
|
||||
description:
|
||||
'Compare QR Master with Flowcode, Bitly, Beaconstac / Uniqode, and QR-Code-Generator.com.',
|
||||
},
|
||||
@@ -46,6 +47,43 @@ const pageSchema = {
|
||||
'Comparison pages for QR Master versus major QR code and adjacent link-management platforms.',
|
||||
};
|
||||
|
||||
const faqItems = [
|
||||
{
|
||||
question: 'What is the best QR code platform alternative?',
|
||||
answer:
|
||||
'The best alternative depends on the workflow. QR Master is strongest when you need dynamic QR codes, clean branding, bulk creation, and privacy-friendly analytics without enterprise pricing.',
|
||||
},
|
||||
{
|
||||
question: 'When should I choose QR Master over Bitly?',
|
||||
answer:
|
||||
'Choose QR Master when QR codes are the primary workflow. Bitly is useful for short links, but its QR code limits and link-first dashboard become restrictive for campaigns with many QR codes.',
|
||||
},
|
||||
{
|
||||
question: 'When should I choose QR Master over Flowcode?',
|
||||
answer:
|
||||
'Choose QR Master when you want a direct scan experience without third-party branding or branded interstitial pages. QR Master keeps the scan flow focused on your destination.',
|
||||
},
|
||||
{
|
||||
question: 'Is Beaconstac / Uniqode better than QR Master?',
|
||||
answer:
|
||||
'Beaconstac / Uniqode can make sense for enterprise teams that need a broad QR platform. QR Master is usually a better fit for smaller teams that want dynamic QR codes, analytics, and bulk creation at a simpler price point.',
|
||||
},
|
||||
];
|
||||
|
||||
const faqSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'FAQPage',
|
||||
'@id': 'https://www.qrmaster.net/alternatives#faq',
|
||||
mainEntity: faqItems.map((item) => ({
|
||||
'@type': 'Question',
|
||||
name: item.question,
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: item.answer,
|
||||
},
|
||||
})),
|
||||
};
|
||||
|
||||
const alternativePages = [
|
||||
{
|
||||
href: '/alternatives/qr-code-generator',
|
||||
@@ -77,10 +115,41 @@ const alternativePages = [
|
||||
},
|
||||
];
|
||||
|
||||
const comparisonRows = [
|
||||
{
|
||||
platform: 'Bitly',
|
||||
href: '/alternatives/bitly',
|
||||
bestFor: 'Short links and light QR use',
|
||||
watchOut: 'Low QR code counts on entry plans; no bulk QR creation',
|
||||
qrMasterAngle: 'QR-first workflow with 50 dynamic codes on Pro',
|
||||
},
|
||||
{
|
||||
platform: 'Flowcode',
|
||||
href: '/alternatives/flowcode',
|
||||
bestFor: 'Design-forward QR campaigns',
|
||||
watchOut: 'Branding and interstitial concerns on lower tiers',
|
||||
qrMasterAngle: 'Clean redirects and brand control without a branded scan page',
|
||||
},
|
||||
{
|
||||
platform: 'Beaconstac / Uniqode',
|
||||
href: '/alternatives/beaconstac',
|
||||
bestFor: 'Enterprise QR management',
|
||||
watchOut: 'Often more platform than small teams need',
|
||||
qrMasterAngle: 'Simpler dynamic QR, analytics, and bulk creation for SMB teams',
|
||||
},
|
||||
{
|
||||
platform: 'QR-Code-Generator.com',
|
||||
href: '/alternatives/qr-code-generator',
|
||||
bestFor: 'Fast one-off QR creation',
|
||||
watchOut: 'Dynamic QR trial limits can be painful after printing',
|
||||
qrMasterAngle: 'Free dynamic codes and transparent paid tiers',
|
||||
},
|
||||
];
|
||||
|
||||
export default function AlternativesHubPage() {
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[pageSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<SeoJsonLd data={[pageSchema, faqSchema, 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' }}>
|
||||
@@ -175,6 +244,56 @@ export default function AlternativesHubPage() {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="border-y bg-white py-24" style={{ borderColor: '#E4E0D9' }}>
|
||||
<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' }}>
|
||||
QR Master vs Bitly, Flowcode, Beaconstac and other QR platforms
|
||||
</h2>
|
||||
<p className="text-lg" style={{ color: '#71717A' }}>
|
||||
Use this table to pick the comparison page that matches your search intent: pricing, branding, bulk
|
||||
creation, analytics, or migration risk.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="overflow-hidden rounded-xl border" style={{ borderColor: '#E4E0D9' }}>
|
||||
<div className="grid grid-cols-1 md:grid-cols-5" style={{ backgroundColor: '#F8F7F4' }}>
|
||||
{['Platform', 'Best for', 'Watch out for', 'QR Master angle', 'Compare'].map((heading) => (
|
||||
<div key={heading} className="p-4 text-xs font-semibold uppercase tracking-wider" style={{ color: '#71717A' }}>
|
||||
{heading}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
{comparisonRows.map((row, index) => (
|
||||
<div
|
||||
key={row.platform}
|
||||
className="grid grid-cols-1 md:grid-cols-5"
|
||||
style={{
|
||||
borderTop: '1px solid #E4E0D9',
|
||||
backgroundColor: index % 2 === 0 ? '#FFFFFF' : '#FAFAF8',
|
||||
}}
|
||||
>
|
||||
<div className="p-4 font-semibold" style={{ color: '#18181B' }}>{row.platform}</div>
|
||||
<div className="p-4 text-sm" style={{ color: '#52525B' }}>{row.bestFor}</div>
|
||||
<div className="p-4 text-sm" style={{ color: '#52525B' }}>{row.watchOut}</div>
|
||||
<div className="p-4 text-sm font-medium" style={{ color: '#166534' }}>{row.qrMasterAngle}</div>
|
||||
<div className="p-4">
|
||||
<Link href={row.href} className="text-sm font-semibold" style={{ color: '#166534' }}>
|
||||
QR Master vs {row.platform}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-24" style={{ backgroundColor: '#F8F7F4' }}>
|
||||
<div className="container mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
|
||||
<FAQSection items={faqItems} title="Common questions about QR platform alternatives" />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -27,9 +27,10 @@ export async function generateMetadata(): Promise<Metadata> {
|
||||
'QR Master is a free QR code generator with scan analytics, dynamic QR codes, custom branding, and bulk creation. No signup required for static codes.',
|
||||
160
|
||||
);
|
||||
const brandTitle = 'QR Master | Free Dynamic QR Code Generator';
|
||||
|
||||
return {
|
||||
title,
|
||||
title: brandTitle,
|
||||
description,
|
||||
keywords: [
|
||||
'qr generator',
|
||||
@@ -51,7 +52,7 @@ export async function generateMetadata(): Promise<Metadata> {
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title,
|
||||
title: brandTitle,
|
||||
description,
|
||||
url: 'https://www.qrmaster.net/',
|
||||
type: 'website',
|
||||
@@ -65,7 +66,7 @@ export async function generateMetadata(): Promise<Metadata> {
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
title,
|
||||
title: brandTitle,
|
||||
description,
|
||||
},
|
||||
};
|
||||
@@ -118,6 +119,13 @@ export default function HomePage() {
|
||||
Upgrade to Pro for 50 codes with advanced analytics, or Business for
|
||||
500 codes with bulk creation and priority support.
|
||||
</p>
|
||||
<p>
|
||||
Frequently used QR Master tools and industry workflows include the{' '}
|
||||
<a href="/tools/teams-qr-code">Teams QR code generator</a>,{' '}
|
||||
<a href="/tools/wifi-qr-code">WiFi QR code generator</a>,{' '}
|
||||
<a href="/qr-code-erstellen">German QR code generator</a>, and{' '}
|
||||
<a href="/qr-code-for/barbershops">QR codes for barbershops</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<HomePageClient />
|
||||
|
||||
@@ -133,6 +133,8 @@ const highlightedLinks = [
|
||||
{ href: "/qr-code-tracking", title: "QR Code Tracking", description: "Measure scans from flyers, property signage, retail displays, trade shows, and offline campaigns." },
|
||||
{ href: "/bulk-qr-code-generator", title: "Bulk QR Code Generator", description: "Best fit for packaging, product lines, multi-location rollouts, and large campaigns." },
|
||||
{ href: "/tools/wifi-qr-code", title: "WiFi QR Code Tool", description: "Popular for hotels, cafes, coworking spaces, clinics, and guest-facing venues." },
|
||||
{ href: "/tools/teams-qr-code", title: "Teams QR Code Tool", description: "Useful for offices, meeting rooms, coworking spaces, and event check-in workflows." },
|
||||
{ href: "/qr-code-for/barbershops", title: "QR Codes for Barbershops", description: "A high-intent local service page for bookings, reviews, WiFi, and social profile QR codes." },
|
||||
];
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -244,7 +246,7 @@ export default function IndustryOverviewPage() {
|
||||
|
||||
<section className="py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid gap-6 lg:grid-cols-4">
|
||||
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
|
||||
{highlightedLinks.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
|
||||
@@ -205,10 +205,66 @@ export default function UseCasesHubPage() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-slate-50 py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
</section>
|
||||
|
||||
<section className="bg-white py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-8 max-w-3xl">
|
||||
<div className="text-sm font-semibold uppercase tracking-[0.22em] text-blue-700">
|
||||
Industry pages with early traction
|
||||
</div>
|
||||
<h2 className="mt-3 text-3xl font-bold text-slate-900">
|
||||
Service business QR workflows
|
||||
</h2>
|
||||
<p className="mt-4 text-lg leading-8 text-slate-600">
|
||||
These industry routes connect practical use cases with the QR
|
||||
tools local businesses usually need first.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-3">
|
||||
{[
|
||||
{
|
||||
href: "/qr-code-for/barbershops",
|
||||
title: "QR Codes for Barbershops",
|
||||
description:
|
||||
"Booking links, review prompts, WiFi access, and social profiles for barbershop visits.",
|
||||
},
|
||||
{
|
||||
href: "/tools/wifi-qr-code",
|
||||
title: "WiFi QR Code Generator",
|
||||
description:
|
||||
"A practical guest-facing QR tool for service businesses and venues.",
|
||||
},
|
||||
{
|
||||
href: "/qr-code-erstellen",
|
||||
title: "QR Code Erstellen",
|
||||
description:
|
||||
"German QR creation page for local business owners who search in German.",
|
||||
},
|
||||
].map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="rounded-2xl border border-slate-200 bg-slate-50 p-6 transition-colors hover:border-blue-200 hover:bg-blue-50/70"
|
||||
>
|
||||
<h3 className="text-xl font-bold text-slate-900">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="mt-3 text-sm leading-6 text-slate-600">
|
||||
{item.description}
|
||||
</p>
|
||||
<div className="mt-5 inline-flex items-center text-sm font-semibold text-blue-700">
|
||||
Open page <ArrowRight className="ml-2 h-4 w-4" />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-slate-50 py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(0,0.95fr)]">
|
||||
<Card className="rounded-3xl border-slate-200 bg-white p-8 shadow-sm">
|
||||
<div className="flex items-center gap-3">
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
@@ -41,6 +42,50 @@ export default function ToolsHubPage() {
|
||||
<FreeToolsGrid />
|
||||
</div>
|
||||
|
||||
<section className="bg-white px-4 py-16">
|
||||
<div className="container mx-auto max-w-5xl">
|
||||
<div className="mb-8 text-center">
|
||||
<h2 className="text-2xl font-bold text-slate-900">
|
||||
Frequently used QR tools
|
||||
</h2>
|
||||
<p className="mx-auto mt-3 max-w-2xl text-slate-600">
|
||||
These tools cover common workplace, venue, and regional QR code
|
||||
workflows.
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-3">
|
||||
{[
|
||||
{
|
||||
href: '/tools/teams-qr-code',
|
||||
title: 'Teams QR Code Generator',
|
||||
description: 'Create QR codes for meeting rooms and invites.',
|
||||
},
|
||||
{
|
||||
href: '/tools/wifi-qr-code',
|
||||
title: 'WiFi QR Code Generator',
|
||||
description: 'Share guest WiFi without typing passwords.',
|
||||
},
|
||||
{
|
||||
href: '/qr-code-erstellen',
|
||||
title: 'QR Code Erstellen',
|
||||
description: 'German QR generator page for local users.',
|
||||
},
|
||||
].map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="rounded-lg border border-slate-200 bg-slate-50 p-5 text-left transition-colors hover:border-indigo-200 hover:bg-indigo-50"
|
||||
>
|
||||
<h3 className="font-semibold text-slate-900">{item.title}</h3>
|
||||
<p className="mt-2 text-sm leading-6 text-slate-600">
|
||||
{item.description}
|
||||
</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-20 px-4">
|
||||
<div className="container mx-auto max-w-3xl text-center">
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-4">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { Hero } from '@/components/marketing/Hero';
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { Hero } from '@/components/marketing/Hero';
|
||||
import AIComingSoonBanner from '@/components/marketing/AIComingSoonBanner';
|
||||
import { StatsStrip } from '@/components/marketing/StatsStrip';
|
||||
import { TemplateCards } from '@/components/marketing/TemplateCards';
|
||||
@@ -40,10 +41,61 @@ export default function HomePageClient() {
|
||||
|
||||
<AIComingSoonBanner />
|
||||
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
{/* Testimonials Carousel */}
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
<section className="bg-white py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-8 max-w-3xl">
|
||||
<h2 className="text-3xl font-bold text-slate-900">
|
||||
Popular QR Master workflows
|
||||
</h2>
|
||||
<p className="mt-3 text-base leading-7 text-slate-600">
|
||||
Start with the pages people already use for meetings, guest WiFi,
|
||||
German QR creation, and local service businesses.
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
{[
|
||||
{
|
||||
href: '/tools/teams-qr-code',
|
||||
title: 'Teams QR Code Generator',
|
||||
description: 'Create a QR code for Microsoft Teams meetings.',
|
||||
},
|
||||
{
|
||||
href: '/tools/wifi-qr-code',
|
||||
title: 'WiFi QR Code Generator',
|
||||
description: 'Let guests scan once to join a WiFi network.',
|
||||
},
|
||||
{
|
||||
href: '/qr-code-erstellen',
|
||||
title: 'QR Code Erstellen',
|
||||
description: 'German QR code generator page for local searches.',
|
||||
},
|
||||
{
|
||||
href: '/qr-code-for/barbershops',
|
||||
title: 'QR Codes for Barbershops',
|
||||
description: 'Booking, reviews, WiFi, and social links for shops.',
|
||||
},
|
||||
].map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="group rounded-lg border border-slate-200 bg-slate-50 p-5 transition-colors hover:border-blue-200 hover:bg-blue-50"
|
||||
>
|
||||
<h3 className="text-lg font-semibold text-slate-900 group-hover:text-blue-700">
|
||||
{item.title}
|
||||
</h3>
|
||||
<p className="mt-2 text-sm leading-6 text-slate-600">
|
||||
{item.description}
|
||||
</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Testimonials Carousel */}
|
||||
<TestimonialsCarousel testimonials={testimonials} />
|
||||
|
||||
<React.Fragment>
|
||||
|
||||
@@ -122,7 +122,7 @@ export function Footer({ variant = 'marketing', t }: FooterProps) {
|
||||
<li><Link href="/privacy" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>{translations.privacy_policy}</Link></li>
|
||||
<li><Link href="/contact" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>Contact</Link></li>
|
||||
<li><Link href="/qr-code-erstellen" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>QR Code Erstellen (DE)</Link></li>
|
||||
<li><Link href="/barcode-generator" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>Barcode Generator (DE)</Link></li>
|
||||
<li><Link href="/tools/barcode-generator" className={isDashboard ? 'hover:text-primary-600' : 'hover:text-white'}>Barcode Generator</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"hero": {
|
||||
"badge": "Free QR Code Generator",
|
||||
"title": "Create QR Codes That Work Everywhere",
|
||||
"title": "QR Master: Create QR Codes That Work Everywhere",
|
||||
"subtitle": "Generate static and dynamic QR codes with tracking, custom branding, and bulk generation. Free forever.",
|
||||
"features": [
|
||||
"No credit card required to start",
|
||||
|
||||
@@ -398,6 +398,8 @@ export const blogPosts: BlogPost[] = [
|
||||
<li><strong>Link too long to encode cleanly:</strong> Teams join URLs are long. Use a dynamic QR code — it encodes a short redirect URL instead, which produces a less dense, more reliably scannable code.</li>
|
||||
</ul>
|
||||
|
||||
<p>Setting up QR codes for an office or venue? Pair Teams meeting access with a <a href="/tools/wifi-qr-code" class="text-blue-600 underline">WiFi QR code</a>, or use the German <a href="/qr-code-erstellen" class="text-blue-600 underline">QR Code Erstellen</a> page for local teams.</p>
|
||||
|
||||
<p>Ready to create yours? The <a href="/tools/teams-qr-code" class="text-blue-600 underline font-semibold">Teams QR code generator is free and takes under 60 seconds →</a></p>
|
||||
|
||||
</div>`,
|
||||
|
||||
@@ -30,9 +30,9 @@ export function organizationSchema() {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Organization',
|
||||
'@id': `${SITE_URL}/#organization`,
|
||||
name: 'QR Master',
|
||||
alternateName: 'QRMaster',
|
||||
url: SITE_URL,
|
||||
name: 'QR Master',
|
||||
alternateName: ['QRMaster', 'QR Master QR Code Generator'],
|
||||
url: SITE_URL,
|
||||
logo: {
|
||||
'@type': 'ImageObject',
|
||||
url: `${SITE_URL}/static/og-image.png`,
|
||||
|
||||
@@ -41,9 +41,18 @@ function attachAttributionCookie(req: NextRequest, response: NextResponse) {
|
||||
return response;
|
||||
}
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
const path = req.nextUrl.pathname;
|
||||
|
||||
export function middleware(req: NextRequest) {
|
||||
const path = req.nextUrl.pathname;
|
||||
const hostname = req.headers.get('host')?.split(':')[0] || req.nextUrl.hostname;
|
||||
|
||||
if (hostname === 'qrmaster.net') {
|
||||
const url = req.nextUrl.clone();
|
||||
url.protocol = 'https';
|
||||
url.port = '';
|
||||
url.hostname = 'www.qrmaster.net';
|
||||
return NextResponse.redirect(url, 301);
|
||||
}
|
||||
|
||||
// 301 Redirects for /guide -> /learn to avoid duplicate content and consolidate authority
|
||||
if (path === '/guide/tracking-analytics') {
|
||||
return attachAttributionCookie(req, NextResponse.redirect(new URL('/learn/tracking', req.url), 301));
|
||||
@@ -57,9 +66,12 @@ export function middleware(req: NextRequest) {
|
||||
if (path === '/create-qr') {
|
||||
return attachAttributionCookie(req, NextResponse.redirect(new URL('/dynamic-qr-code-generator', req.url), 301));
|
||||
}
|
||||
|
||||
// Public routes that don't require authentication
|
||||
const publicPaths = [
|
||||
if (path === '/bar-code-generator' || path === '/barcode-generator') {
|
||||
return attachAttributionCookie(req, NextResponse.redirect(new URL('/tools/barcode-generator', req.url), 301));
|
||||
}
|
||||
|
||||
// Public routes that don't require authentication
|
||||
const publicPaths = [
|
||||
'/',
|
||||
'/pricing',
|
||||
'/faq',
|
||||
@@ -78,10 +90,9 @@ export function middleware(req: NextRequest) {
|
||||
'/bulk-qr-code-generator',
|
||||
'/qr-code-tracking',
|
||||
'/qr-code-analytics',
|
||||
'/reprint-calculator',
|
||||
'/barcode-generator',
|
||||
'/custom-qr-code-generator',
|
||||
'/manage-qr-codes',
|
||||
'/reprint-calculator',
|
||||
'/custom-qr-code-generator',
|
||||
'/manage-qr-codes',
|
||||
'/coupon',
|
||||
'/feedback',
|
||||
'/vcard',
|
||||
@@ -124,13 +135,29 @@ export function middleware(req: NextRequest) {
|
||||
return attachAttributionCookie(req, NextResponse.next());
|
||||
}
|
||||
|
||||
// Allow public paths
|
||||
// Allow public paths
|
||||
if (isPublicPath) {
|
||||
return attachAttributionCookie(req, NextResponse.next());
|
||||
}
|
||||
|
||||
// For protected routes, check for userId cookie
|
||||
const userId = req.cookies.get('userId')?.value;
|
||||
|
||||
const protectedPaths = [
|
||||
'/analytics',
|
||||
'/bulk-creation',
|
||||
'/create',
|
||||
'/dashboard',
|
||||
'/integrations',
|
||||
'/onboarding',
|
||||
'/qr',
|
||||
'/settings',
|
||||
];
|
||||
const isProtectedPath = protectedPaths.some(p => path === p || path.startsWith(p + '/'));
|
||||
|
||||
if (!isProtectedPath) {
|
||||
return attachAttributionCookie(req, NextResponse.next());
|
||||
}
|
||||
|
||||
// For protected routes, check for userId cookie
|
||||
const userId = req.cookies.get('userId')?.value;
|
||||
|
||||
if (!userId) {
|
||||
// Not authenticated - redirect to signup
|
||||
|
||||
Reference in New Issue
Block a user