11 seo pages
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,343 +1,343 @@
|
||||
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 { 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 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.',
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/alternatives',
|
||||
},
|
||||
openGraph: {
|
||||
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',
|
||||
type: 'website',
|
||||
images: ['/og-image.png'],
|
||||
},
|
||||
twitter: {
|
||||
title: 'QR Master Alternatives: Compare QR Code Platforms',
|
||||
description:
|
||||
'Compare QR Master with Flowcode, Bitly, Beaconstac / Uniqode, and QR-Code-Generator.com.',
|
||||
},
|
||||
};
|
||||
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Alternatives', url: '/alternatives' },
|
||||
];
|
||||
|
||||
const pageSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'CollectionPage',
|
||||
name: 'QR Code Platform Alternatives',
|
||||
url: 'https://www.qrmaster.net/alternatives',
|
||||
description:
|
||||
'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',
|
||||
eyebrow: 'Trial trap',
|
||||
title: 'QR-Code-Generator.com Alternative',
|
||||
description:
|
||||
'For teams burned by 14-day dynamic QR trials and forced annual upgrades after print is already live.',
|
||||
},
|
||||
{
|
||||
href: '/alternatives/flowcode',
|
||||
eyebrow: 'Brand control',
|
||||
title: 'Flowcode Alternative',
|
||||
description:
|
||||
'For brands and agencies that need clean QR codes without third-party logos or branded scan interstitials.',
|
||||
},
|
||||
{
|
||||
href: '/alternatives/beaconstac',
|
||||
eyebrow: 'SMB fit',
|
||||
title: 'Beaconstac / Uniqode Alternative',
|
||||
description:
|
||||
'For smaller teams that want reliable analytics and bulk QR creation without paying enterprise-platform pricing.',
|
||||
},
|
||||
{
|
||||
href: '/alternatives/bitly',
|
||||
eyebrow: 'QR-first workflow',
|
||||
title: 'Bitly Alternative',
|
||||
description:
|
||||
'For campaigns where QR codes are the main workflow, not a side feature hidden inside a link shortener.',
|
||||
},
|
||||
];
|
||||
|
||||
const comparisonRows = [
|
||||
{
|
||||
platform: 'Bitly',
|
||||
href: '/alternatives/bitly',
|
||||
price: 'Link-first paid plans',
|
||||
freePlan: 'Limited QR use',
|
||||
dynamicCodes: 'QR feature inside link management',
|
||||
analytics: 'Link analytics first',
|
||||
gdpr: 'Review DPA for EU use',
|
||||
bulk: 'No QR-first bulk workflow',
|
||||
branding: 'Bitly-branded link context',
|
||||
qrMasterAngle: 'QR-first workflow with 50 dynamic codes on Pro',
|
||||
},
|
||||
{
|
||||
platform: 'Flowcode',
|
||||
href: '/alternatives/flowcode',
|
||||
price: 'Brand and team tiers',
|
||||
freePlan: 'Limited free path',
|
||||
dynamicCodes: 'Strong QR design workflow',
|
||||
analytics: 'Paid campaign analytics',
|
||||
gdpr: 'US vendor; review data terms',
|
||||
bulk: 'Best for larger plans',
|
||||
branding: 'Design-forward, possible platform branding',
|
||||
qrMasterAngle: 'Clean redirects and brand control without a branded scan page',
|
||||
},
|
||||
{
|
||||
platform: 'Beaconstac / Uniqode',
|
||||
href: '/alternatives/beaconstac',
|
||||
price: 'Enterprise-oriented tiers',
|
||||
freePlan: 'Trial or limited evaluation',
|
||||
dynamicCodes: 'Advanced enterprise QR platform',
|
||||
analytics: 'Advanced paid analytics',
|
||||
gdpr: 'DPA and configuration review needed',
|
||||
bulk: 'Strong, often enterprise-oriented',
|
||||
branding: 'Enterprise controls',
|
||||
qrMasterAngle: 'Simpler dynamic QR, analytics, and bulk creation for SMB teams',
|
||||
},
|
||||
{
|
||||
platform: 'QR-Code-Generator.com',
|
||||
href: '/alternatives/qr-code-generator',
|
||||
price: 'Paid dynamic QR after trial',
|
||||
freePlan: 'Static QR path',
|
||||
dynamicCodes: 'Dynamic QR behind paid upgrade',
|
||||
analytics: 'Paid analytics',
|
||||
gdpr: 'Review vendor terms',
|
||||
bulk: 'Paid workflow',
|
||||
branding: 'Template-driven branding',
|
||||
qrMasterAngle: 'Free dynamic codes and transparent paid tiers',
|
||||
},
|
||||
];
|
||||
|
||||
export default function AlternativesHubPage() {
|
||||
return (
|
||||
<>
|
||||
<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' }}>
|
||||
<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 alternatives
|
||||
</div>
|
||||
<h1
|
||||
className="mb-6 text-4xl font-extrabold leading-[1.08] tracking-tight sm:text-5xl"
|
||||
style={{ color: '#111110' }}
|
||||
>
|
||||
Clean comparisons for the QR platforms people actually switch from.
|
||||
</h1>
|
||||
<p className="mb-8 text-lg leading-relaxed" style={{ color: '#52525B' }}>
|
||||
Some tools hide trial limits. Some force their brand into your scan flow. Some are simply priced for
|
||||
enterprise teams. These pages break down where each platform fits, where it does not, and when QR
|
||||
Master is the better tradeoff.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-3 sm:flex-row">
|
||||
<TrackedCtaLink
|
||||
href="/signup"
|
||||
ctaLabel="Start Free"
|
||||
ctaLocation="hero_primary"
|
||||
pageType="commercial"
|
||||
cluster="competitor"
|
||||
>
|
||||
<Button size="lg" className="h-13 w-full px-8 text-base sm:w-auto">
|
||||
Start Free
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
<TrackedCtaLink
|
||||
href="/pricing"
|
||||
ctaLabel="See Pricing"
|
||||
ctaLocation="hero_secondary"
|
||||
pageType="commercial"
|
||||
cluster="competitor"
|
||||
>
|
||||
<Button variant="outline" size="lg" className="h-13 w-full px-8 text-base sm:w-auto">
|
||||
See Pricing
|
||||
</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' }}>
|
||||
Explore Alternatives
|
||||
</h2>
|
||||
<p className="text-lg" style={{ color: '#71717A' }}>
|
||||
Pick the comparison that matches the problem you are trying to solve.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-4">
|
||||
{alternativePages.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' }}>
|
||||
Open comparison
|
||||
</p>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
</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-x-auto rounded-xl border" style={{ borderColor: '#E4E0D9' }}>
|
||||
<table className="w-full min-w-[980px] text-sm">
|
||||
<thead style={{ backgroundColor: '#F8F7F4' }}>
|
||||
<tr>
|
||||
{[
|
||||
'Platform',
|
||||
'Price',
|
||||
'Free plan',
|
||||
'Dynamic codes',
|
||||
'Analytics',
|
||||
'GDPR / EU fit',
|
||||
'Bulk',
|
||||
'Branding',
|
||||
'Compare',
|
||||
].map((heading) => (
|
||||
<th
|
||||
key={heading}
|
||||
className="p-4 text-left text-xs font-semibold uppercase tracking-wider"
|
||||
style={{ color: '#71717A' }}
|
||||
>
|
||||
{heading}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{comparisonRows.map((row, index) => (
|
||||
<tr
|
||||
key={row.platform}
|
||||
style={{
|
||||
borderTop: '1px solid #E4E0D9',
|
||||
backgroundColor: index % 2 === 0 ? '#FFFFFF' : '#FAFAF8',
|
||||
}}
|
||||
>
|
||||
<td className="p-4 font-semibold" style={{ color: '#18181B' }}>{row.platform}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.price}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.freePlan}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.dynamicCodes}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.analytics}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.gdpr}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.bulk}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.branding}</td>
|
||||
<td className="p-4">
|
||||
<Link href={row.href} className="font-semibold" style={{ color: '#166534' }}>
|
||||
QR Master vs {row.platform}
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
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 { 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 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.',
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/alternatives',
|
||||
},
|
||||
openGraph: {
|
||||
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',
|
||||
type: 'website',
|
||||
images: ['/og-image.png'],
|
||||
},
|
||||
twitter: {
|
||||
title: 'QR Master Alternatives: Compare QR Code Platforms',
|
||||
description:
|
||||
'Compare QR Master with Flowcode, Bitly, Beaconstac / Uniqode, and QR-Code-Generator.com.',
|
||||
},
|
||||
};
|
||||
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Alternatives', url: '/alternatives' },
|
||||
];
|
||||
|
||||
const pageSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'CollectionPage',
|
||||
name: 'QR Code Platform Alternatives',
|
||||
url: 'https://www.qrmaster.net/alternatives',
|
||||
description:
|
||||
'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',
|
||||
eyebrow: 'Trial trap',
|
||||
title: 'QR-Code-Generator.com Alternative',
|
||||
description:
|
||||
'For teams burned by 14-day dynamic QR trials and forced annual upgrades after print is already live.',
|
||||
},
|
||||
{
|
||||
href: '/alternatives/flowcode',
|
||||
eyebrow: 'Brand control',
|
||||
title: 'Flowcode Alternative',
|
||||
description:
|
||||
'For brands and agencies that need clean QR codes without third-party logos or branded scan interstitials.',
|
||||
},
|
||||
{
|
||||
href: '/alternatives/beaconstac',
|
||||
eyebrow: 'SMB fit',
|
||||
title: 'Beaconstac / Uniqode Alternative',
|
||||
description:
|
||||
'For smaller teams that want reliable analytics and bulk QR creation without paying enterprise-platform pricing.',
|
||||
},
|
||||
{
|
||||
href: '/alternatives/bitly',
|
||||
eyebrow: 'QR-first workflow',
|
||||
title: 'Bitly Alternative',
|
||||
description:
|
||||
'For campaigns where QR codes are the main workflow, not a side feature hidden inside a link shortener.',
|
||||
},
|
||||
];
|
||||
|
||||
const comparisonRows = [
|
||||
{
|
||||
platform: 'Bitly',
|
||||
href: '/alternatives/bitly',
|
||||
price: 'Link-first paid plans',
|
||||
freePlan: 'Limited QR use',
|
||||
dynamicCodes: 'QR feature inside link management',
|
||||
analytics: 'Link analytics first',
|
||||
gdpr: 'Review DPA for EU use',
|
||||
bulk: 'No QR-first bulk workflow',
|
||||
branding: 'Bitly-branded link context',
|
||||
qrMasterAngle: 'QR-first workflow with 50 dynamic codes on Pro',
|
||||
},
|
||||
{
|
||||
platform: 'Flowcode',
|
||||
href: '/alternatives/flowcode',
|
||||
price: 'Brand and team tiers',
|
||||
freePlan: 'Limited free path',
|
||||
dynamicCodes: 'Strong QR design workflow',
|
||||
analytics: 'Paid campaign analytics',
|
||||
gdpr: 'US vendor; review data terms',
|
||||
bulk: 'Best for larger plans',
|
||||
branding: 'Design-forward, possible platform branding',
|
||||
qrMasterAngle: 'Clean redirects and brand control without a branded scan page',
|
||||
},
|
||||
{
|
||||
platform: 'Beaconstac / Uniqode',
|
||||
href: '/alternatives/beaconstac',
|
||||
price: 'Enterprise-oriented tiers',
|
||||
freePlan: 'Trial or limited evaluation',
|
||||
dynamicCodes: 'Advanced enterprise QR platform',
|
||||
analytics: 'Advanced paid analytics',
|
||||
gdpr: 'DPA and configuration review needed',
|
||||
bulk: 'Strong, often enterprise-oriented',
|
||||
branding: 'Enterprise controls',
|
||||
qrMasterAngle: 'Simpler dynamic QR, analytics, and bulk creation for SMB teams',
|
||||
},
|
||||
{
|
||||
platform: 'QR-Code-Generator.com',
|
||||
href: '/alternatives/qr-code-generator',
|
||||
price: 'Paid dynamic QR after trial',
|
||||
freePlan: 'Static QR path',
|
||||
dynamicCodes: 'Dynamic QR behind paid upgrade',
|
||||
analytics: 'Paid analytics',
|
||||
gdpr: 'Review vendor terms',
|
||||
bulk: 'Paid workflow',
|
||||
branding: 'Template-driven branding',
|
||||
qrMasterAngle: 'Free dynamic codes and transparent paid tiers',
|
||||
},
|
||||
];
|
||||
|
||||
export default function AlternativesHubPage() {
|
||||
return (
|
||||
<>
|
||||
<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' }}>
|
||||
<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 alternatives
|
||||
</div>
|
||||
<h1
|
||||
className="mb-6 text-4xl font-extrabold leading-[1.08] tracking-tight sm:text-5xl"
|
||||
style={{ color: '#111110' }}
|
||||
>
|
||||
Clean comparisons for the QR platforms people actually switch from.
|
||||
</h1>
|
||||
<p className="mb-8 text-lg leading-relaxed" style={{ color: '#52525B' }}>
|
||||
Some tools hide trial limits. Some force their brand into your scan flow. Some are simply priced for
|
||||
enterprise teams. These pages break down where each platform fits, where it does not, and when QR
|
||||
Master is the better tradeoff.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col gap-3 sm:flex-row">
|
||||
<TrackedCtaLink
|
||||
href="/signup"
|
||||
ctaLabel="Start Free"
|
||||
ctaLocation="hero_primary"
|
||||
pageType="commercial"
|
||||
cluster="competitor"
|
||||
>
|
||||
<Button size="lg" className="h-13 w-full px-8 text-base sm:w-auto">
|
||||
Start Free
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
<TrackedCtaLink
|
||||
href="/pricing"
|
||||
ctaLabel="See Pricing"
|
||||
ctaLocation="hero_secondary"
|
||||
pageType="commercial"
|
||||
cluster="competitor"
|
||||
>
|
||||
<Button variant="outline" size="lg" className="h-13 w-full px-8 text-base sm:w-auto">
|
||||
See Pricing
|
||||
</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' }}>
|
||||
Explore Alternatives
|
||||
</h2>
|
||||
<p className="text-lg" style={{ color: '#71717A' }}>
|
||||
Pick the comparison that matches the problem you are trying to solve.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-4">
|
||||
{alternativePages.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' }}>
|
||||
Open comparison
|
||||
</p>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
</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-x-auto rounded-xl border" style={{ borderColor: '#E4E0D9' }}>
|
||||
<table className="w-full min-w-[980px] text-sm">
|
||||
<thead style={{ backgroundColor: '#F8F7F4' }}>
|
||||
<tr>
|
||||
{[
|
||||
'Platform',
|
||||
'Price',
|
||||
'Free plan',
|
||||
'Dynamic codes',
|
||||
'Analytics',
|
||||
'GDPR / EU fit',
|
||||
'Bulk',
|
||||
'Branding',
|
||||
'Compare',
|
||||
].map((heading) => (
|
||||
<th
|
||||
key={heading}
|
||||
className="p-4 text-left text-xs font-semibold uppercase tracking-wider"
|
||||
style={{ color: '#71717A' }}
|
||||
>
|
||||
{heading}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{comparisonRows.map((row, index) => (
|
||||
<tr
|
||||
key={row.platform}
|
||||
style={{
|
||||
borderTop: '1px solid #E4E0D9',
|
||||
backgroundColor: index % 2 === 0 ? '#FFFFFF' : '#FAFAF8',
|
||||
}}
|
||||
>
|
||||
<td className="p-4 font-semibold" style={{ color: '#18181B' }}>{row.platform}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.price}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.freePlan}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.dynamicCodes}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.analytics}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.gdpr}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.bulk}</td>
|
||||
<td className="p-4" style={{ color: '#52525B' }}>{row.branding}</td>
|
||||
<td className="p-4">
|
||||
<Link href={row.href} className="font-semibold" style={{ color: '#166534' }}>
|
||||
QR Master vs {row.platform}
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,165 +1,165 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import { getPublishedPostBySlug, getAuthorBySlug, getRelatedPosts, getPublishedPosts } from "@/lib/content";
|
||||
import { AnswerBox } from "@/components/aeo/AnswerBox";
|
||||
import { StepList } from "@/components/aeo/StepList";
|
||||
import { FAQSection } from "@/components/aeo/FAQSection";
|
||||
import { SourcesList } from "@/components/aeo/SourcesList";
|
||||
import { AuthorCard } from "@/components/author/AuthorCard";
|
||||
import { RelatedPosts } from "@/components/blog/RelatedPosts";
|
||||
import { blogPostingSchema, howToSchema, faqPageSchema, breadcrumbSchema } from "@/lib/schema";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
function formatIsoDate(date: string) {
|
||||
return new Date(date).toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
export function generateMetadata({ params }: { params: { slug: string } }) {
|
||||
const post = getPublishedPostBySlug(params.slug);
|
||||
if (!post) return {};
|
||||
|
||||
const ogImage = post.heroImage ? `https://www.qrmaster.net${post.heroImage}` : undefined;
|
||||
|
||||
return {
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
alternates: {
|
||||
canonical: `https://www.qrmaster.net/blog/${post.slug}`,
|
||||
},
|
||||
openGraph: {
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
type: "article",
|
||||
publishedTime: post.datePublished,
|
||||
modifiedTime: post.dateModified || post.datePublished,
|
||||
authors: ["https://www.qrmaster.net"],
|
||||
tags: post.keywords,
|
||||
images: ogImage ? [{ url: ogImage, alt: post.imageAlt || post.title }] : undefined,
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
images: ogImage ? [ogImage] : undefined,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function generateStaticParams() {
|
||||
// Only generate static params for published posts
|
||||
return getPublishedPosts().map((post) => ({
|
||||
slug: post.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
export default function BlogPostPage({ params }: { params: { slug: string } }) {
|
||||
const post = getPublishedPostBySlug(params.slug);
|
||||
if (!post) return notFound(); // STRICT 404 GATE
|
||||
|
||||
const author = getAuthorBySlug(post.authorSlug);
|
||||
const related = getRelatedPosts(post);
|
||||
|
||||
const jsonLd = blogPostingSchema(post, author);
|
||||
const howtoLd = post.keySteps?.length ? howToSchema(post, author) : null;
|
||||
const faqLd = post.faq ? faqPageSchema(post.faq) : null;
|
||||
const visibleUpdated = post.updatedAt || post.dateModified;
|
||||
const showUpdated = Boolean(visibleUpdated && visibleUpdated !== post.datePublished);
|
||||
|
||||
// Generate breadcrumb schema: Home -> Learn -> Pillar -> Post
|
||||
const pillarName = post.pillar ? post.pillar.charAt(0).toUpperCase() + post.pillar.slice(1) : "Blog";
|
||||
const breadcrumbLd = breadcrumbSchema([
|
||||
{ name: "Home", url: "/" },
|
||||
{ name: "Learn", url: "/learn" },
|
||||
{ name: pillarName, url: `/learn/${post.pillar}` },
|
||||
{ name: post.title, url: `/blog/${post.slug}` },
|
||||
]);
|
||||
|
||||
return (
|
||||
<main className="container mx-auto max-w-4xl py-12 px-4">
|
||||
<script type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
{howtoLd && (
|
||||
<script type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(howtoLd) }} />
|
||||
)}
|
||||
{faqLd && (
|
||||
<script type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(faqLd) }} />
|
||||
)}
|
||||
<script type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbLd) }} />
|
||||
|
||||
<header className="space-y-6 text-center max-w-3xl mx-auto mb-10">
|
||||
<div className="flex justify-center gap-2 text-sm text-gray-500 font-medium">
|
||||
<Link href="/learn" className="hover:text-blue-600">Hub</Link>
|
||||
<span>/</span>
|
||||
<Link href={`/learn/${post.pillar}`} className="hover:text-blue-600 capitalize">{post.pillar}</Link>
|
||||
</div>
|
||||
<h1 className="text-3xl md:text-5xl font-extrabold text-gray-900 tracking-tight leading-tight">{post.title}</h1>
|
||||
<p className="text-xl text-gray-600 relaxed">{post.description}</p>
|
||||
|
||||
{author && (
|
||||
<div className="flex items-center justify-center gap-3 pt-4">
|
||||
{author.image ? (
|
||||
<Image src={author.image} alt={author.name} width={40} height={40} className="rounded-full" />
|
||||
) : (
|
||||
<div className="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 font-bold">
|
||||
{author.name.charAt(0)}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-left text-sm">
|
||||
<div className="font-bold text-gray-900">{author.name}</div>
|
||||
<div className="text-gray-500 text-xs mt-0.5">
|
||||
Published {post.date}
|
||||
{showUpdated && visibleUpdated && (
|
||||
<> <span className="mx-1">|</span> Updated {formatIsoDate(visibleUpdated)}</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
||||
{post.heroImage && (
|
||||
<div className="relative aspect-video w-full rounded-2xl overflow-hidden shadow-lg mb-10">
|
||||
<Image
|
||||
src={post.heroImage}
|
||||
alt={post.imageAlt || post.title}
|
||||
fill
|
||||
unoptimized={post.heroImage.endsWith(".svg")}
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* AEO BLOCK: ANSWER */}
|
||||
<div className="max-w-3xl mx-auto">
|
||||
{post.quickAnswer && <AnswerBox html={post.quickAnswer} />}
|
||||
|
||||
{/* AEO BLOCK: STEPS (If defined separate from body) */}
|
||||
{!!post.keySteps?.length && <StepList steps={post.keySteps} title="Step-by-Step Guide" />}
|
||||
|
||||
{/* MAIN CONTENT */}
|
||||
<article className="prose prose-lg prose-blue max-w-none text-gray-800" dangerouslySetInnerHTML={{ __html: post.content }} />
|
||||
|
||||
{/* AEO BLOCK: FAQ */}
|
||||
{!!post.faq?.length && <div className="mt-12"><FAQSection items={post.faq} /></div>}
|
||||
|
||||
{/* AEO BLOCK: SOURCES */}
|
||||
{!!post.sources?.length && <SourcesList sources={post.sources} />}
|
||||
|
||||
<div className="border-t border-gray-100 my-12"></div>
|
||||
|
||||
{author && <AuthorCard author={author} />}
|
||||
|
||||
<div className="mt-12">
|
||||
<RelatedPosts posts={related} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
import { notFound } from "next/navigation";
|
||||
import { getPublishedPostBySlug, getAuthorBySlug, getRelatedPosts, getPublishedPosts } from "@/lib/content";
|
||||
import { AnswerBox } from "@/components/aeo/AnswerBox";
|
||||
import { StepList } from "@/components/aeo/StepList";
|
||||
import { FAQSection } from "@/components/aeo/FAQSection";
|
||||
import { SourcesList } from "@/components/aeo/SourcesList";
|
||||
import { AuthorCard } from "@/components/author/AuthorCard";
|
||||
import { RelatedPosts } from "@/components/blog/RelatedPosts";
|
||||
import { blogPostingSchema, howToSchema, faqPageSchema, breadcrumbSchema } from "@/lib/schema";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
function formatIsoDate(date: string) {
|
||||
return new Date(date).toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
});
|
||||
}
|
||||
|
||||
export function generateMetadata({ params }: { params: { slug: string } }) {
|
||||
const post = getPublishedPostBySlug(params.slug);
|
||||
if (!post) return {};
|
||||
|
||||
const ogImage = post.heroImage ? `https://www.qrmaster.net${post.heroImage}` : undefined;
|
||||
|
||||
return {
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
alternates: {
|
||||
canonical: `https://www.qrmaster.net/blog/${post.slug}`,
|
||||
},
|
||||
openGraph: {
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
type: "article",
|
||||
publishedTime: post.datePublished,
|
||||
modifiedTime: post.dateModified || post.datePublished,
|
||||
authors: ["https://www.qrmaster.net"],
|
||||
tags: post.keywords,
|
||||
images: ogImage ? [{ url: ogImage, alt: post.imageAlt || post.title }] : undefined,
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
images: ogImage ? [ogImage] : undefined,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function generateStaticParams() {
|
||||
// Only generate static params for published posts
|
||||
return getPublishedPosts().map((post) => ({
|
||||
slug: post.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
export default function BlogPostPage({ params }: { params: { slug: string } }) {
|
||||
const post = getPublishedPostBySlug(params.slug);
|
||||
if (!post) return notFound(); // STRICT 404 GATE
|
||||
|
||||
const author = getAuthorBySlug(post.authorSlug);
|
||||
const related = getRelatedPosts(post);
|
||||
|
||||
const jsonLd = blogPostingSchema(post, author);
|
||||
const howtoLd = post.keySteps?.length ? howToSchema(post, author) : null;
|
||||
const faqLd = post.faq ? faqPageSchema(post.faq) : null;
|
||||
const visibleUpdated = post.updatedAt || post.dateModified;
|
||||
const showUpdated = Boolean(visibleUpdated && visibleUpdated !== post.datePublished);
|
||||
|
||||
// Generate breadcrumb schema: Home -> Learn -> Pillar -> Post
|
||||
const pillarName = post.pillar ? post.pillar.charAt(0).toUpperCase() + post.pillar.slice(1) : "Blog";
|
||||
const breadcrumbLd = breadcrumbSchema([
|
||||
{ name: "Home", url: "/" },
|
||||
{ name: "Learn", url: "/learn" },
|
||||
{ name: pillarName, url: `/learn/${post.pillar}` },
|
||||
{ name: post.title, url: `/blog/${post.slug}` },
|
||||
]);
|
||||
|
||||
return (
|
||||
<main className="container mx-auto max-w-4xl py-12 px-4">
|
||||
<script type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
{howtoLd && (
|
||||
<script type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(howtoLd) }} />
|
||||
)}
|
||||
{faqLd && (
|
||||
<script type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(faqLd) }} />
|
||||
)}
|
||||
<script type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbLd) }} />
|
||||
|
||||
<header className="space-y-6 text-center max-w-3xl mx-auto mb-10">
|
||||
<div className="flex justify-center gap-2 text-sm text-gray-500 font-medium">
|
||||
<Link href="/learn" className="hover:text-blue-600">Hub</Link>
|
||||
<span>/</span>
|
||||
<Link href={`/learn/${post.pillar}`} className="hover:text-blue-600 capitalize">{post.pillar}</Link>
|
||||
</div>
|
||||
<h1 className="text-3xl md:text-5xl font-extrabold text-gray-900 tracking-tight leading-tight">{post.title}</h1>
|
||||
<p className="text-xl text-gray-600 relaxed">{post.description}</p>
|
||||
|
||||
{author && (
|
||||
<div className="flex items-center justify-center gap-3 pt-4">
|
||||
{author.image ? (
|
||||
<Image src={author.image} alt={author.name} width={40} height={40} className="rounded-full" />
|
||||
) : (
|
||||
<div className="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 font-bold">
|
||||
{author.name.charAt(0)}
|
||||
</div>
|
||||
)}
|
||||
<div className="text-left text-sm">
|
||||
<div className="font-bold text-gray-900">{author.name}</div>
|
||||
<div className="text-gray-500 text-xs mt-0.5">
|
||||
Published {post.date}
|
||||
{showUpdated && visibleUpdated && (
|
||||
<> <span className="mx-1">|</span> Updated {formatIsoDate(visibleUpdated)}</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
||||
{post.heroImage && (
|
||||
<div className="relative aspect-video w-full rounded-2xl overflow-hidden shadow-lg mb-10">
|
||||
<Image
|
||||
src={post.heroImage}
|
||||
alt={post.imageAlt || post.title}
|
||||
fill
|
||||
unoptimized={post.heroImage.endsWith(".svg")}
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* AEO BLOCK: ANSWER */}
|
||||
<div className="max-w-3xl mx-auto">
|
||||
{post.quickAnswer && <AnswerBox html={post.quickAnswer} />}
|
||||
|
||||
{/* AEO BLOCK: STEPS (If defined separate from body) */}
|
||||
{!!post.keySteps?.length && <StepList steps={post.keySteps} title="Step-by-Step Guide" />}
|
||||
|
||||
{/* MAIN CONTENT */}
|
||||
<article className="prose prose-lg prose-blue max-w-none text-gray-800" dangerouslySetInnerHTML={{ __html: post.content }} />
|
||||
|
||||
{/* AEO BLOCK: FAQ */}
|
||||
{!!post.faq?.length && <div className="mt-12"><FAQSection items={post.faq} /></div>}
|
||||
|
||||
{/* AEO BLOCK: SOURCES */}
|
||||
{!!post.sources?.length && <SourcesList sources={post.sources} />}
|
||||
|
||||
<div className="border-t border-gray-100 my-12"></div>
|
||||
|
||||
{author && <AuthorCard author={author} />}
|
||||
|
||||
<div className="mt-12">
|
||||
<RelatedPosts posts={related} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,134 +1,134 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import {
|
||||
websiteSchema,
|
||||
softwareApplicationSchema,
|
||||
} from '@/lib/schema';
|
||||
import { getAggregateRating } from '@/lib/testimonial-data';
|
||||
import HomePageClient from '@/components/marketing/HomePageClient';
|
||||
|
||||
function truncateAtWord(text: string, maxLength: number): string {
|
||||
if (text.length <= maxLength) return text;
|
||||
const truncated = text.slice(0, maxLength);
|
||||
const lastSpace = truncated.lastIndexOf(' ');
|
||||
return lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated;
|
||||
}
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const description = truncateAtWord(
|
||||
'QR Master is a free dynamic QR code generator with tracking, editable destinations, custom branding, and bulk QR creation. Create static QR codes without signup.',
|
||||
160
|
||||
);
|
||||
const brandTitle = 'QR Master - Free Dynamic QR Code Generator with Tracking';
|
||||
|
||||
return {
|
||||
title: brandTitle,
|
||||
description,
|
||||
keywords: [
|
||||
'qr generator',
|
||||
'free qr code generator',
|
||||
'custom qr code generator',
|
||||
'qr code maker',
|
||||
'online qr code generator',
|
||||
'dynamic qr code',
|
||||
'qr code with logo',
|
||||
'barcode generator',
|
||||
'free barcode generator',
|
||||
'qr master',
|
||||
'qrmaster',
|
||||
'qr code master',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/',
|
||||
en: 'https://www.qrmaster.net/',
|
||||
de: 'https://www.qrmaster.net/qr-code-erstellen',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: brandTitle,
|
||||
description,
|
||||
url: 'https://www.qrmaster.net/',
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url: 'https://www.qrmaster.net/og-image.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'QR Master - Dynamic QR Code Generator and Analytics Platform',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
title: brandTitle,
|
||||
description,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default function HomePage() {
|
||||
const aggregateRating = getAggregateRating();
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd
|
||||
data={[
|
||||
websiteSchema(),
|
||||
softwareApplicationSchema(aggregateRating),
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Server-rendered SEO content for crawlers */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
<p>
|
||||
Create professional QR codes for your business with QR Master. Our
|
||||
dynamic QR code generator lets you create trackable QR codes, edit
|
||||
destinations anytime, and view detailed analytics. Perfect for
|
||||
restaurants, retail, events, and marketing campaigns.
|
||||
</p>
|
||||
<p>
|
||||
Features include: Dynamic QR codes with real-time tracking, bulk QR
|
||||
code generation from Excel/CSV, custom branding with colors and logos,
|
||||
advanced scan analytics showing device types and locations, vCard QR
|
||||
codes for digital business cards, restaurant menu QR codes, and a free{' '}
|
||||
<a href="/tools/barcode-generator">barcode generator</a> for EAN-13,
|
||||
UPC-A, and Code 128 barcodes.
|
||||
</p>
|
||||
<p>
|
||||
Popular QR Master workflows include the{' '}
|
||||
<a href="/dynamic-qr-code-generator">
|
||||
free dynamic QR code generator
|
||||
</a>
|
||||
, <a href="/qr-code-tracking">QR code tracking</a>, and the{' '}
|
||||
<a href="/custom-qr-code-generator">custom QR code generator</a> for
|
||||
branded print campaigns.
|
||||
</p>
|
||||
<p>
|
||||
Start free with 3 active dynamic QR codes and unlimited static codes.
|
||||
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>
|
||||
<p>
|
||||
High-intent QR Master pages include the{' '}
|
||||
<a href="/bulk-qr-code-generator">
|
||||
bulk QR code generator for Excel and CSV files
|
||||
</a>
|
||||
, <a href="/alternatives">QR code platform alternatives</a>,{' '}
|
||||
<a href="/alternatives/beaconstac">Beaconstac alternative</a>, and{' '}
|
||||
<a href="/alternatives/bitly">Bitly QR code alternative</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<HomePageClient />
|
||||
</>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import {
|
||||
websiteSchema,
|
||||
softwareApplicationSchema,
|
||||
} from '@/lib/schema';
|
||||
import { getAggregateRating } from '@/lib/testimonial-data';
|
||||
import HomePageClient from '@/components/marketing/HomePageClient';
|
||||
|
||||
function truncateAtWord(text: string, maxLength: number): string {
|
||||
if (text.length <= maxLength) return text;
|
||||
const truncated = text.slice(0, maxLength);
|
||||
const lastSpace = truncated.lastIndexOf(' ');
|
||||
return lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated;
|
||||
}
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const description = truncateAtWord(
|
||||
'QR Master is a free dynamic QR code generator with tracking, editable destinations, custom branding, and bulk QR creation. Create static QR codes without signup.',
|
||||
160
|
||||
);
|
||||
const brandTitle = 'QR Master - Free Dynamic QR Code Generator with Tracking';
|
||||
|
||||
return {
|
||||
title: brandTitle,
|
||||
description,
|
||||
keywords: [
|
||||
'qr generator',
|
||||
'free qr code generator',
|
||||
'custom qr code generator',
|
||||
'qr code maker',
|
||||
'online qr code generator',
|
||||
'dynamic qr code',
|
||||
'qr code with logo',
|
||||
'barcode generator',
|
||||
'free barcode generator',
|
||||
'qr master',
|
||||
'qrmaster',
|
||||
'qr code master',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/',
|
||||
en: 'https://www.qrmaster.net/',
|
||||
de: 'https://www.qrmaster.net/qr-code-erstellen',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: brandTitle,
|
||||
description,
|
||||
url: 'https://www.qrmaster.net/',
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url: 'https://www.qrmaster.net/og-image.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'QR Master - Dynamic QR Code Generator and Analytics Platform',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
title: brandTitle,
|
||||
description,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default function HomePage() {
|
||||
const aggregateRating = getAggregateRating();
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd
|
||||
data={[
|
||||
websiteSchema(),
|
||||
softwareApplicationSchema(aggregateRating),
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Server-rendered SEO content for crawlers */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
<p>
|
||||
Create professional QR codes for your business with QR Master. Our
|
||||
dynamic QR code generator lets you create trackable QR codes, edit
|
||||
destinations anytime, and view detailed analytics. Perfect for
|
||||
restaurants, retail, events, and marketing campaigns.
|
||||
</p>
|
||||
<p>
|
||||
Features include: Dynamic QR codes with real-time tracking, bulk QR
|
||||
code generation from Excel/CSV, custom branding with colors and logos,
|
||||
advanced scan analytics showing device types and locations, vCard QR
|
||||
codes for digital business cards, restaurant menu QR codes, and a free{' '}
|
||||
<a href="/tools/barcode-generator">barcode generator</a> for EAN-13,
|
||||
UPC-A, and Code 128 barcodes.
|
||||
</p>
|
||||
<p>
|
||||
Popular QR Master workflows include the{' '}
|
||||
<a href="/dynamic-qr-code-generator">
|
||||
free dynamic QR code generator
|
||||
</a>
|
||||
, <a href="/qr-code-tracking">QR code tracking</a>, and the{' '}
|
||||
<a href="/custom-qr-code-generator">custom QR code generator</a> for
|
||||
branded print campaigns.
|
||||
</p>
|
||||
<p>
|
||||
Start free with 3 active dynamic QR codes and unlimited static codes.
|
||||
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>
|
||||
<p>
|
||||
High-intent QR Master pages include the{' '}
|
||||
<a href="/bulk-qr-code-generator">
|
||||
bulk QR code generator for Excel and CSV files
|
||||
</a>
|
||||
, <a href="/alternatives">QR code platform alternatives</a>,{' '}
|
||||
<a href="/alternatives/beaconstac">Beaconstac alternative</a>, and{' '}
|
||||
<a href="/alternatives/bitly">Bitly QR code alternative</a>.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<HomePageClient />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,227 +1,227 @@
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
import {
|
||||
buildUseCaseMetadata,
|
||||
UseCasePageTemplate,
|
||||
} from '@/components/marketing/UseCasePageTemplate';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
|
||||
export const metadata: Metadata = buildUseCaseMetadata({
|
||||
title: 'QR Code Analytics: Measure Offline Campaigns',
|
||||
description:
|
||||
'Use QR code analytics to interpret scan data, compare placements, measure offline campaigns, and decide what to update or reprint next.',
|
||||
canonicalPath: '/qr-code-analytics',
|
||||
});
|
||||
|
||||
const softwareSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'SoftwareApplication',
|
||||
'@id': 'https://www.qrmaster.net/qr-code-analytics#software',
|
||||
name: 'QR Master - QR Code Analytics',
|
||||
applicationCategory: 'BusinessApplication',
|
||||
operatingSystem: 'Web Browser',
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '0',
|
||||
priceCurrency: 'USD',
|
||||
availability: 'https://schema.org/InStock',
|
||||
},
|
||||
description:
|
||||
'QR analytics software for measuring scans by placement, timing, device context, and offline campaign routing.',
|
||||
featureList: [
|
||||
'Placement-level scan reporting',
|
||||
'Device and timing context',
|
||||
'Offline-to-online campaign attribution',
|
||||
'Scan visibility across print workflows',
|
||||
'Destination updates without reprinting',
|
||||
],
|
||||
};
|
||||
|
||||
export default function QRCodeAnalyticsPage() {
|
||||
return (
|
||||
<>
|
||||
<UseCasePageTemplate
|
||||
title="QR Code Analytics: Measure Offline Campaigns"
|
||||
description="Use QR code analytics to interpret scan data, compare placements, measure offline campaigns, and decide what to update or reprint next."
|
||||
eyebrow="Analytics interpretation"
|
||||
intro="QR code analytics turns scan events into decisions: which printed placement worked, which destination needs work, and what should be changed before the next print run."
|
||||
pageType="commercial"
|
||||
cluster="qr-analytics"
|
||||
useCase="qr-analytics"
|
||||
breadcrumbs={[
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'QR Code Analytics', url: '/qr-code-analytics' },
|
||||
]}
|
||||
answer="QR code analytics helps teams interpret QR scan data by placement, timing, device context, and campaign route so offline marketing decisions are based on evidence rather than raw scan counts alone."
|
||||
whenToUse={[
|
||||
'You need more than raw scan counts from campaigns, packaging, or offline placements.',
|
||||
'You want to compare where scans happen and which printed surfaces actually drive action.',
|
||||
'You need a clearer bridge between QR scans and business outcomes such as signup, offers, or support engagement.',
|
||||
]}
|
||||
comparisonItems={[
|
||||
{
|
||||
label: 'Tracking collects scan events',
|
||||
text: 'Input data',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: 'Analytics explains performance',
|
||||
text: 'Decision layer',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: 'Reprint decisions',
|
||||
text: 'Based on evidence',
|
||||
value: true,
|
||||
},
|
||||
]}
|
||||
howToSteps={[
|
||||
'Create QR flows that map to real placements or workflow contexts instead of one generic code for every use case.',
|
||||
'Track scans with enough context to compare signs, flyers, inserts, or support surfaces cleanly.',
|
||||
'Use the reporting to decide which destinations, offers, or print placements deserve the next round of investment.',
|
||||
]}
|
||||
primaryCta={{
|
||||
href: '/signup',
|
||||
label: 'Start measuring QR scans',
|
||||
}}
|
||||
secondaryCta={{
|
||||
href: '/use-cases',
|
||||
label: 'Browse measured workflows',
|
||||
}}
|
||||
workflowTitle="Questions QR analytics should answer"
|
||||
workflowIntro="The point of analytics is not to produce dashboards for their own sake. It is to decide what to print again, where to place it, and what should happen after the scan."
|
||||
workflowCards={[
|
||||
{
|
||||
title: 'Which placement worked?',
|
||||
description:
|
||||
'Separate flyer, packaging, sign, event, or service-surface traffic so you know which printed context actually creates useful scan activity.',
|
||||
},
|
||||
{
|
||||
title: 'What should change next?',
|
||||
description:
|
||||
'Review performance and then improve the destination, offer, or next action without replacing every physical code already in circulation.',
|
||||
},
|
||||
{
|
||||
title: 'What should be reprinted?',
|
||||
description:
|
||||
'Give marketing, operations, or support teams a clearer view of which physical QR programs deserve another batch.',
|
||||
},
|
||||
]}
|
||||
checklistTitle="QR analytics checklist"
|
||||
checklist={[
|
||||
'Define which placements or workflow surfaces should be compared before launching the QR program.',
|
||||
'Use naming or routing that lets scans be grouped by real business context, not only by one generic campaign.',
|
||||
'Make the first post-scan step relevant enough that a scan can become a useful action, not a bounce.',
|
||||
'Review analytics before reprinting so the next batch reflects real-world performance.',
|
||||
]}
|
||||
supportLinks={[
|
||||
{
|
||||
href: '/use-cases/packaging-qr-codes',
|
||||
title: 'Use case: Packaging QR Codes',
|
||||
description:
|
||||
'See how packaging scans can become a measurable post-purchase signal instead of a blind spot.',
|
||||
},
|
||||
{
|
||||
href: '/qr-code-for-marketing-campaigns',
|
||||
title: 'QR Codes for Marketing Campaigns',
|
||||
description:
|
||||
'Plan campaign QR workflows around attribution, creative testing, and print distribution.',
|
||||
},
|
||||
{
|
||||
href: '/use-cases/flyer-qr-codes',
|
||||
title: 'Use case: Flyer QR Codes',
|
||||
description:
|
||||
'Useful when scan performance needs to be reviewed by distribution point or campaign wave.',
|
||||
},
|
||||
{
|
||||
href: '/blog/utm-parameter-qr-codes',
|
||||
title: 'UTM Parameters with QR Codes',
|
||||
description:
|
||||
'Use GA4 campaign parameters when QR scan data needs to connect to post-scan conversions.',
|
||||
},
|
||||
{
|
||||
href: '/blog/trackable-qr-codes',
|
||||
title: 'Trackable QR Codes',
|
||||
description:
|
||||
'Support article for understanding what measurable QR setups should capture and why it matters.',
|
||||
},
|
||||
]}
|
||||
faq={[
|
||||
{
|
||||
question: 'What can QR code analytics show?',
|
||||
answer:
|
||||
'QR code analytics can show scan activity by placement, time, device context, and campaign route so teams can see which physical programs are actually performing.',
|
||||
},
|
||||
{
|
||||
question:
|
||||
'What is the difference between QR tracking and QR analytics?',
|
||||
answer:
|
||||
'QR tracking collects scan events. QR analytics interprets those events so teams can compare placements, understand campaign performance, and decide what to update or reprint.',
|
||||
},
|
||||
{
|
||||
question: 'Why are QR code analytics useful for offline campaigns?',
|
||||
answer:
|
||||
'They help turn offline placements such as flyers, packaging, signs, or event materials into something measurable instead of relying on assumptions about what worked.',
|
||||
},
|
||||
{
|
||||
question: 'Do I need dynamic QR codes for analytics?',
|
||||
answer:
|
||||
'In most cases yes, because analytics usually depends on a managed redirect or reporting layer that also lets you update destinations without reprinting.',
|
||||
},
|
||||
]}
|
||||
schemaData={[softwareSchema]}
|
||||
/>
|
||||
<GrowthLinksSection
|
||||
eyebrow="Related workflows"
|
||||
title="Analytics is only the start"
|
||||
description="Tracking scans is more useful when it connects to destination flexibility, campaign comparison, and cost planning."
|
||||
links={[
|
||||
{
|
||||
href: '/qr-code-tracking',
|
||||
title: 'QR Code Tracking',
|
||||
description:
|
||||
'See device, time, and location context for every scan. Understand which placements drive real activity.',
|
||||
ctaLabel: 'Track QR code scans',
|
||||
},
|
||||
{
|
||||
href: '/dynamic-qr-code-generator',
|
||||
title: 'Dynamic QR Code Generator',
|
||||
description:
|
||||
'Create QR codes with updatable destinations so analytics can inform what to change — without reprinting.',
|
||||
ctaLabel: 'Create dynamic QR code',
|
||||
},
|
||||
{
|
||||
href: '/reprint-calculator',
|
||||
title: 'Reprint Cost Calculator',
|
||||
description:
|
||||
'Calculate how much static reprints are costing vs one dynamic QR subscription.',
|
||||
ctaLabel: 'Calculate reprint savings',
|
||||
},
|
||||
{
|
||||
href: '/qr-code-for-marketing-campaigns',
|
||||
title: 'QR Codes for Marketing Campaigns',
|
||||
description:
|
||||
'Plan offline campaigns where each placement has a measurable QR route and follow-up action.',
|
||||
ctaLabel: 'Measure offline QR campaigns',
|
||||
},
|
||||
{
|
||||
href: '/use-cases/qr-codes-for-review-collection',
|
||||
title: 'QR Codes for Review Collection',
|
||||
description:
|
||||
'Compare receipts, table cards, packaging, and counters as measurable review-request placements.',
|
||||
ctaLabel: 'Measure review QR placements',
|
||||
},
|
||||
{
|
||||
href: '/pricing',
|
||||
title: 'Compare Plans',
|
||||
description:
|
||||
'See which plan gives you the scan volume, analytics depth, and QR code count your workflows need.',
|
||||
ctaLabel: 'Compare plans',
|
||||
},
|
||||
]}
|
||||
pageType="commercial"
|
||||
cluster="qr-analytics"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
import type { Metadata } from 'next';
|
||||
|
||||
import {
|
||||
buildUseCaseMetadata,
|
||||
UseCasePageTemplate,
|
||||
} from '@/components/marketing/UseCasePageTemplate';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
|
||||
export const metadata: Metadata = buildUseCaseMetadata({
|
||||
title: 'QR Code Analytics: Measure Offline Campaigns',
|
||||
description:
|
||||
'Use QR code analytics to interpret scan data, compare placements, measure offline campaigns, and decide what to update or reprint next.',
|
||||
canonicalPath: '/qr-code-analytics',
|
||||
});
|
||||
|
||||
const softwareSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'SoftwareApplication',
|
||||
'@id': 'https://www.qrmaster.net/qr-code-analytics#software',
|
||||
name: 'QR Master - QR Code Analytics',
|
||||
applicationCategory: 'BusinessApplication',
|
||||
operatingSystem: 'Web Browser',
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '0',
|
||||
priceCurrency: 'USD',
|
||||
availability: 'https://schema.org/InStock',
|
||||
},
|
||||
description:
|
||||
'QR analytics software for measuring scans by placement, timing, device context, and offline campaign routing.',
|
||||
featureList: [
|
||||
'Placement-level scan reporting',
|
||||
'Device and timing context',
|
||||
'Offline-to-online campaign attribution',
|
||||
'Scan visibility across print workflows',
|
||||
'Destination updates without reprinting',
|
||||
],
|
||||
};
|
||||
|
||||
export default function QRCodeAnalyticsPage() {
|
||||
return (
|
||||
<>
|
||||
<UseCasePageTemplate
|
||||
title="QR Code Analytics: Measure Offline Campaigns"
|
||||
description="Use QR code analytics to interpret scan data, compare placements, measure offline campaigns, and decide what to update or reprint next."
|
||||
eyebrow="Analytics interpretation"
|
||||
intro="QR code analytics turns scan events into decisions: which printed placement worked, which destination needs work, and what should be changed before the next print run."
|
||||
pageType="commercial"
|
||||
cluster="qr-analytics"
|
||||
useCase="qr-analytics"
|
||||
breadcrumbs={[
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'QR Code Analytics', url: '/qr-code-analytics' },
|
||||
]}
|
||||
answer="QR code analytics helps teams interpret QR scan data by placement, timing, device context, and campaign route so offline marketing decisions are based on evidence rather than raw scan counts alone."
|
||||
whenToUse={[
|
||||
'You need more than raw scan counts from campaigns, packaging, or offline placements.',
|
||||
'You want to compare where scans happen and which printed surfaces actually drive action.',
|
||||
'You need a clearer bridge between QR scans and business outcomes such as signup, offers, or support engagement.',
|
||||
]}
|
||||
comparisonItems={[
|
||||
{
|
||||
label: 'Tracking collects scan events',
|
||||
text: 'Input data',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: 'Analytics explains performance',
|
||||
text: 'Decision layer',
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
label: 'Reprint decisions',
|
||||
text: 'Based on evidence',
|
||||
value: true,
|
||||
},
|
||||
]}
|
||||
howToSteps={[
|
||||
'Create QR flows that map to real placements or workflow contexts instead of one generic code for every use case.',
|
||||
'Track scans with enough context to compare signs, flyers, inserts, or support surfaces cleanly.',
|
||||
'Use the reporting to decide which destinations, offers, or print placements deserve the next round of investment.',
|
||||
]}
|
||||
primaryCta={{
|
||||
href: '/signup',
|
||||
label: 'Start measuring QR scans',
|
||||
}}
|
||||
secondaryCta={{
|
||||
href: '/use-cases',
|
||||
label: 'Browse measured workflows',
|
||||
}}
|
||||
workflowTitle="Questions QR analytics should answer"
|
||||
workflowIntro="The point of analytics is not to produce dashboards for their own sake. It is to decide what to print again, where to place it, and what should happen after the scan."
|
||||
workflowCards={[
|
||||
{
|
||||
title: 'Which placement worked?',
|
||||
description:
|
||||
'Separate flyer, packaging, sign, event, or service-surface traffic so you know which printed context actually creates useful scan activity.',
|
||||
},
|
||||
{
|
||||
title: 'What should change next?',
|
||||
description:
|
||||
'Review performance and then improve the destination, offer, or next action without replacing every physical code already in circulation.',
|
||||
},
|
||||
{
|
||||
title: 'What should be reprinted?',
|
||||
description:
|
||||
'Give marketing, operations, or support teams a clearer view of which physical QR programs deserve another batch.',
|
||||
},
|
||||
]}
|
||||
checklistTitle="QR analytics checklist"
|
||||
checklist={[
|
||||
'Define which placements or workflow surfaces should be compared before launching the QR program.',
|
||||
'Use naming or routing that lets scans be grouped by real business context, not only by one generic campaign.',
|
||||
'Make the first post-scan step relevant enough that a scan can become a useful action, not a bounce.',
|
||||
'Review analytics before reprinting so the next batch reflects real-world performance.',
|
||||
]}
|
||||
supportLinks={[
|
||||
{
|
||||
href: '/use-cases/packaging-qr-codes',
|
||||
title: 'Use case: Packaging QR Codes',
|
||||
description:
|
||||
'See how packaging scans can become a measurable post-purchase signal instead of a blind spot.',
|
||||
},
|
||||
{
|
||||
href: '/qr-code-for-marketing-campaigns',
|
||||
title: 'QR Codes for Marketing Campaigns',
|
||||
description:
|
||||
'Plan campaign QR workflows around attribution, creative testing, and print distribution.',
|
||||
},
|
||||
{
|
||||
href: '/use-cases/flyer-qr-codes',
|
||||
title: 'Use case: Flyer QR Codes',
|
||||
description:
|
||||
'Useful when scan performance needs to be reviewed by distribution point or campaign wave.',
|
||||
},
|
||||
{
|
||||
href: '/blog/utm-parameter-qr-codes',
|
||||
title: 'UTM Parameters with QR Codes',
|
||||
description:
|
||||
'Use GA4 campaign parameters when QR scan data needs to connect to post-scan conversions.',
|
||||
},
|
||||
{
|
||||
href: '/blog/trackable-qr-codes',
|
||||
title: 'Trackable QR Codes',
|
||||
description:
|
||||
'Support article for understanding what measurable QR setups should capture and why it matters.',
|
||||
},
|
||||
]}
|
||||
faq={[
|
||||
{
|
||||
question: 'What can QR code analytics show?',
|
||||
answer:
|
||||
'QR code analytics can show scan activity by placement, time, device context, and campaign route so teams can see which physical programs are actually performing.',
|
||||
},
|
||||
{
|
||||
question:
|
||||
'What is the difference between QR tracking and QR analytics?',
|
||||
answer:
|
||||
'QR tracking collects scan events. QR analytics interprets those events so teams can compare placements, understand campaign performance, and decide what to update or reprint.',
|
||||
},
|
||||
{
|
||||
question: 'Why are QR code analytics useful for offline campaigns?',
|
||||
answer:
|
||||
'They help turn offline placements such as flyers, packaging, signs, or event materials into something measurable instead of relying on assumptions about what worked.',
|
||||
},
|
||||
{
|
||||
question: 'Do I need dynamic QR codes for analytics?',
|
||||
answer:
|
||||
'In most cases yes, because analytics usually depends on a managed redirect or reporting layer that also lets you update destinations without reprinting.',
|
||||
},
|
||||
]}
|
||||
schemaData={[softwareSchema]}
|
||||
/>
|
||||
<GrowthLinksSection
|
||||
eyebrow="Related workflows"
|
||||
title="Analytics is only the start"
|
||||
description="Tracking scans is more useful when it connects to destination flexibility, campaign comparison, and cost planning."
|
||||
links={[
|
||||
{
|
||||
href: '/qr-code-tracking',
|
||||
title: 'QR Code Tracking',
|
||||
description:
|
||||
'See device, time, and location context for every scan. Understand which placements drive real activity.',
|
||||
ctaLabel: 'Track QR code scans',
|
||||
},
|
||||
{
|
||||
href: '/dynamic-qr-code-generator',
|
||||
title: 'Dynamic QR Code Generator',
|
||||
description:
|
||||
'Create QR codes with updatable destinations so analytics can inform what to change — without reprinting.',
|
||||
ctaLabel: 'Create dynamic QR code',
|
||||
},
|
||||
{
|
||||
href: '/reprint-calculator',
|
||||
title: 'Reprint Cost Calculator',
|
||||
description:
|
||||
'Calculate how much static reprints are costing vs one dynamic QR subscription.',
|
||||
ctaLabel: 'Calculate reprint savings',
|
||||
},
|
||||
{
|
||||
href: '/qr-code-for-marketing-campaigns',
|
||||
title: 'QR Codes for Marketing Campaigns',
|
||||
description:
|
||||
'Plan offline campaigns where each placement has a measurable QR route and follow-up action.',
|
||||
ctaLabel: 'Measure offline QR campaigns',
|
||||
},
|
||||
{
|
||||
href: '/use-cases/qr-codes-for-review-collection',
|
||||
title: 'QR Codes for Review Collection',
|
||||
description:
|
||||
'Compare receipts, table cards, packaging, and counters as measurable review-request placements.',
|
||||
ctaLabel: 'Measure review QR placements',
|
||||
},
|
||||
{
|
||||
href: '/pricing',
|
||||
title: 'Compare Plans',
|
||||
description:
|
||||
'See which plan gives you the scan volume, analytics depth, and QR code count your workflows need.',
|
||||
ctaLabel: 'Compare plans',
|
||||
},
|
||||
]}
|
||||
pageType="commercial"
|
||||
cluster="qr-analytics"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,168 +1,168 @@
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
import {
|
||||
buildIndustryMetadata,
|
||||
IndustryPageTemplate,
|
||||
} from "@/components/marketing/IndustryPageTemplate";
|
||||
import { industryPages } from "@/lib/industry-pages";
|
||||
|
||||
type Cta = {
|
||||
href: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
const toolsMap: Record<string, { href: string; title: string; description: string }> = {
|
||||
"url-qr-code": { href: "/tools/url-qr-code", title: "URL QR Code Generator", description: "Create a scannable link to any webpage and update the destination any time." },
|
||||
"wifi-qr-code": { href: "/tools/wifi-qr-code", title: "WiFi QR Code Generator", description: "Print once, let guests scan to connect, and remove the friction of sharing passwords." },
|
||||
"vcard-qr-code": { href: "/tools/vcard-qr-code", title: "vCard QR Code", description: "Share contact details with a single scan so prospects can save your team instantly." },
|
||||
"email-qr-code": { href: "/tools/email-qr-code", title: "Email QR Code", description: "Open a pre-addressed email draft so customers can contact you faster." },
|
||||
"sms-qr-code": { href: "/tools/sms-qr-code", title: "SMS QR Code", description: "Pre-fill a text message to support bookings, follow-ups, and reminder flows." },
|
||||
"instagram-qr-code": { href: "/tools/instagram-qr-code", title: "Instagram QR Code", description: "Send visitors directly to your Instagram profile, gallery, or creator page." },
|
||||
"facebook-qr-code": { href: "/tools/facebook-qr-code", title: "Facebook QR Code", description: "Link to your Facebook Page or Group with a single scan." },
|
||||
"youtube-qr-code": { href: "/tools/youtube-qr-code", title: "YouTube QR Code", description: "Point visitors to a video, product demo, tutorial, or playlist." },
|
||||
"video-qr-code": { href: "/tools/youtube-qr-code", title: "Video QR Code", description: "Use a video-focused QR workflow for demos, walkthroughs, and visual proof." },
|
||||
"event-qr-code": { href: "/tools/event-qr-code", title: "Event QR Code", description: "Let visitors save event details directly to their phone calendar." },
|
||||
"app-store-qr-code": { href: "/tools/url-qr-code", title: "App Download QR Code", description: "Use a URL QR code to send scans to your App Store or Play Store listing." },
|
||||
"geolocation-qr-code": { href: "/tools/geolocation-qr-code", title: "Location QR Code", description: "Open Google Maps navigation to your store, venue, or office address." },
|
||||
"call-qr-code-generator": { href: "/tools/call-qr-code-generator", title: "Phone Call QR Code", description: "Open the dialer with your number pre-filled for instant contact." },
|
||||
"paypal-qr-code": { href: "/tools/paypal-qr-code", title: "PayPal QR Code", description: "Link directly to a PayPal payment, invoice, or donation page." },
|
||||
"pdf-qr-code": { href: "/tools/url-qr-code", title: "PDF QR Code", description: "Use a URL QR code to open a hosted PDF like a menu, brochure, or operating guide." },
|
||||
"whatsapp-qr-code": { href: "/tools/whatsapp-qr-code", title: "WhatsApp QR Code", description: "Open a WhatsApp chat with your number pre-loaded for faster support." },
|
||||
};
|
||||
|
||||
const industryPrimaryCtas: Record<string, Cta> = {
|
||||
restaurants: { href: "/dynamic-qr-code-generator", label: "Create a Dynamic Menu QR Code" },
|
||||
cafes: { href: "/tools/url-qr-code", label: "Create a Cafe QR Code" },
|
||||
hotels: { href: "/tools/wifi-qr-code", label: "Create a Hotel WiFi QR Code" },
|
||||
"real-estate": { href: "/qr-code-tracking", label: "Track Real Estate QR Scans" },
|
||||
retail: { href: "/bulk-qr-code-generator", label: "Create Bulk Retail QR Codes" },
|
||||
events: { href: "/tools/event-qr-code", label: "Create an Event QR Code" },
|
||||
"doctors-dentists": { href: "/tools/url-qr-code", label: "Create an Intake Form QR Code" },
|
||||
dentists: { href: "/tools/url-qr-code", label: "Create a Dental QR Code" },
|
||||
"trade-shows": { href: "/qr-code-tracking", label: "Track Trade Show QR Leads" },
|
||||
pharmacies: { href: "/tools/email-qr-code", label: "Create a Pharmacy Follow-Up QR Code" },
|
||||
"car-dealerships": { href: "/qr-code-tracking", label: "Track Dealership QR Scans" },
|
||||
"pet-grooming": { href: "/tools/url-qr-code", label: "Create a Grooming Booking QR Code" },
|
||||
veterinarians: { href: "/tools/url-qr-code", label: "Create a Veterinary QR Code" },
|
||||
};
|
||||
|
||||
const industrySecondaryCtas: Record<string, Cta> = {
|
||||
restaurants: { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
cafes: { href: "/dynamic-qr-code-generator", label: "Try Dynamic QR Codes" },
|
||||
hotels: { href: "/dynamic-qr-code-generator", label: "Try Dynamic QR Codes" },
|
||||
"real-estate": { href: "/dynamic-qr-code-generator", label: "Try Dynamic QR Codes" },
|
||||
retail: { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
events: { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
"doctors-dentists": { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
dentists: { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
"trade-shows": { href: "/bulk-qr-code-generator", label: "Create Bulk QR Codes" },
|
||||
};
|
||||
|
||||
export function generateStaticParams() {
|
||||
return industryPages.map((page) => ({ industry: page.slug }));
|
||||
}
|
||||
|
||||
export function generateMetadata({ params }: { params: { industry: string } }) {
|
||||
const page = industryPages.find((entry) => entry.slug === params.industry);
|
||||
if (!page) return {};
|
||||
|
||||
return buildIndustryMetadata({
|
||||
title: page.metaTitle || page.title,
|
||||
fallbackTitle: page.title,
|
||||
description: page.metaDescription,
|
||||
canonicalPath: `/qr-code-for/${page.slug}`,
|
||||
});
|
||||
}
|
||||
|
||||
function getToolCta(toolSlug?: string): Cta | null {
|
||||
if (!toolSlug) return null;
|
||||
const tool = toolsMap[toolSlug];
|
||||
if (!tool) return null;
|
||||
|
||||
if (toolSlug === "url-qr-code") {
|
||||
return { href: tool.href, label: "Create a QR Code" };
|
||||
}
|
||||
|
||||
return { href: tool.href, label: `Create a ${tool.title}` };
|
||||
}
|
||||
|
||||
function getPrimaryCta(page: (typeof industryPages)[number]): Cta {
|
||||
return (
|
||||
industryPrimaryCtas[page.slug] ??
|
||||
getToolCta(page.tools[0]) ?? {
|
||||
href: "/dynamic-qr-code-generator",
|
||||
label: "Create a Dynamic QR Code",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getSecondaryCta(page: (typeof industryPages)[number]): Cta {
|
||||
return (
|
||||
industrySecondaryCtas[page.slug] ?? {
|
||||
href: "/pricing",
|
||||
label: "View Plans",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getHeroImageAlt(page: (typeof industryPages)[number]) {
|
||||
return `${page.name} QR code example showing a real-world workflow for ${page.useCases[0]?.toLowerCase() ?? "customer engagement"}.`;
|
||||
}
|
||||
|
||||
export default function IndustryPage({ params }: { params: { industry: string } }) {
|
||||
const page = industryPages.find((entry) => entry.slug === params.industry);
|
||||
if (!page) notFound();
|
||||
|
||||
const primaryCta = getPrimaryCta(page);
|
||||
const secondaryCta = getSecondaryCta(page);
|
||||
const supportLinks = page.tools.map(
|
||||
(slug) =>
|
||||
toolsMap[slug] ?? {
|
||||
href: "/tools/url-qr-code",
|
||||
title: "QR Code Generator",
|
||||
description: "Create a QR code for your business.",
|
||||
}
|
||||
);
|
||||
const useCaseStrings = Array.isArray(page.useCases) ? page.useCases : [];
|
||||
|
||||
return (
|
||||
<IndustryPageTemplate
|
||||
title={page.title}
|
||||
description={page.metaDescription}
|
||||
eyebrow={page.name}
|
||||
intro={page.subheadline || page.headline}
|
||||
pageType="commercial"
|
||||
cluster="industry"
|
||||
useCase={page.slug}
|
||||
breadcrumbs={[
|
||||
{ name: "Home", url: "/" },
|
||||
{ name: "QR Codes by Industry", url: "/qr-code-for" },
|
||||
{ name: page.title, url: `/qr-code-for/${page.slug}` },
|
||||
]}
|
||||
answer={page.headline}
|
||||
whenToUse={useCaseStrings.slice(0, 3)}
|
||||
comparisonItems={[
|
||||
{ label: "Update destination after printing", value: true, text: "Dynamic QR codes" },
|
||||
{ label: "Track scans by date, device & location", value: true, text: "Built-in analytics" },
|
||||
{ label: "No app needed to scan", value: true, text: "Works with native camera" },
|
||||
]}
|
||||
howToSteps={page.placementTips.slice(0, 3)}
|
||||
primaryCta={primaryCta}
|
||||
secondaryCta={secondaryCta}
|
||||
workflowTitle={`How ${page.name} Use QR Codes`}
|
||||
workflowIntro={`Practical QR code workflows built around how ${page.name.toLowerCase()} actually operate.`}
|
||||
workflowCards={useCaseStrings.slice(0, 3).map((useCase, index) => ({
|
||||
title: `Workflow ${index + 1}`,
|
||||
description: useCase,
|
||||
}))}
|
||||
checklistTitle={`${page.name} QR Code Checklist`}
|
||||
checklist={page.placementTips}
|
||||
supportLinks={supportLinks}
|
||||
faq={page.faq}
|
||||
heroImage={page.heroImage}
|
||||
heroImageAlt={getHeroImageAlt(page)}
|
||||
statistics={page.statistics}
|
||||
benefits={page.benefits}
|
||||
/>
|
||||
);
|
||||
}
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
import {
|
||||
buildIndustryMetadata,
|
||||
IndustryPageTemplate,
|
||||
} from "@/components/marketing/IndustryPageTemplate";
|
||||
import { industryPages } from "@/lib/industry-pages";
|
||||
|
||||
type Cta = {
|
||||
href: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
const toolsMap: Record<string, { href: string; title: string; description: string }> = {
|
||||
"url-qr-code": { href: "/tools/url-qr-code", title: "URL QR Code Generator", description: "Create a scannable link to any webpage and update the destination any time." },
|
||||
"wifi-qr-code": { href: "/tools/wifi-qr-code", title: "WiFi QR Code Generator", description: "Print once, let guests scan to connect, and remove the friction of sharing passwords." },
|
||||
"vcard-qr-code": { href: "/tools/vcard-qr-code", title: "vCard QR Code", description: "Share contact details with a single scan so prospects can save your team instantly." },
|
||||
"email-qr-code": { href: "/tools/email-qr-code", title: "Email QR Code", description: "Open a pre-addressed email draft so customers can contact you faster." },
|
||||
"sms-qr-code": { href: "/tools/sms-qr-code", title: "SMS QR Code", description: "Pre-fill a text message to support bookings, follow-ups, and reminder flows." },
|
||||
"instagram-qr-code": { href: "/tools/instagram-qr-code", title: "Instagram QR Code", description: "Send visitors directly to your Instagram profile, gallery, or creator page." },
|
||||
"facebook-qr-code": { href: "/tools/facebook-qr-code", title: "Facebook QR Code", description: "Link to your Facebook Page or Group with a single scan." },
|
||||
"youtube-qr-code": { href: "/tools/youtube-qr-code", title: "YouTube QR Code", description: "Point visitors to a video, product demo, tutorial, or playlist." },
|
||||
"video-qr-code": { href: "/tools/youtube-qr-code", title: "Video QR Code", description: "Use a video-focused QR workflow for demos, walkthroughs, and visual proof." },
|
||||
"event-qr-code": { href: "/tools/event-qr-code", title: "Event QR Code", description: "Let visitors save event details directly to their phone calendar." },
|
||||
"app-store-qr-code": { href: "/tools/url-qr-code", title: "App Download QR Code", description: "Use a URL QR code to send scans to your App Store or Play Store listing." },
|
||||
"geolocation-qr-code": { href: "/tools/geolocation-qr-code", title: "Location QR Code", description: "Open Google Maps navigation to your store, venue, or office address." },
|
||||
"call-qr-code-generator": { href: "/tools/call-qr-code-generator", title: "Phone Call QR Code", description: "Open the dialer with your number pre-filled for instant contact." },
|
||||
"paypal-qr-code": { href: "/tools/paypal-qr-code", title: "PayPal QR Code", description: "Link directly to a PayPal payment, invoice, or donation page." },
|
||||
"pdf-qr-code": { href: "/tools/url-qr-code", title: "PDF QR Code", description: "Use a URL QR code to open a hosted PDF like a menu, brochure, or operating guide." },
|
||||
"whatsapp-qr-code": { href: "/tools/whatsapp-qr-code", title: "WhatsApp QR Code", description: "Open a WhatsApp chat with your number pre-loaded for faster support." },
|
||||
};
|
||||
|
||||
const industryPrimaryCtas: Record<string, Cta> = {
|
||||
restaurants: { href: "/dynamic-qr-code-generator", label: "Create a Dynamic Menu QR Code" },
|
||||
cafes: { href: "/tools/url-qr-code", label: "Create a Cafe QR Code" },
|
||||
hotels: { href: "/tools/wifi-qr-code", label: "Create a Hotel WiFi QR Code" },
|
||||
"real-estate": { href: "/qr-code-tracking", label: "Track Real Estate QR Scans" },
|
||||
retail: { href: "/bulk-qr-code-generator", label: "Create Bulk Retail QR Codes" },
|
||||
events: { href: "/tools/event-qr-code", label: "Create an Event QR Code" },
|
||||
"doctors-dentists": { href: "/tools/url-qr-code", label: "Create an Intake Form QR Code" },
|
||||
dentists: { href: "/tools/url-qr-code", label: "Create a Dental QR Code" },
|
||||
"trade-shows": { href: "/qr-code-tracking", label: "Track Trade Show QR Leads" },
|
||||
pharmacies: { href: "/tools/email-qr-code", label: "Create a Pharmacy Follow-Up QR Code" },
|
||||
"car-dealerships": { href: "/qr-code-tracking", label: "Track Dealership QR Scans" },
|
||||
"pet-grooming": { href: "/tools/url-qr-code", label: "Create a Grooming Booking QR Code" },
|
||||
veterinarians: { href: "/tools/url-qr-code", label: "Create a Veterinary QR Code" },
|
||||
};
|
||||
|
||||
const industrySecondaryCtas: Record<string, Cta> = {
|
||||
restaurants: { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
cafes: { href: "/dynamic-qr-code-generator", label: "Try Dynamic QR Codes" },
|
||||
hotels: { href: "/dynamic-qr-code-generator", label: "Try Dynamic QR Codes" },
|
||||
"real-estate": { href: "/dynamic-qr-code-generator", label: "Try Dynamic QR Codes" },
|
||||
retail: { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
events: { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
"doctors-dentists": { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
dentists: { href: "/qr-code-tracking", label: "See QR Tracking Features" },
|
||||
"trade-shows": { href: "/bulk-qr-code-generator", label: "Create Bulk QR Codes" },
|
||||
};
|
||||
|
||||
export function generateStaticParams() {
|
||||
return industryPages.map((page) => ({ industry: page.slug }));
|
||||
}
|
||||
|
||||
export function generateMetadata({ params }: { params: { industry: string } }) {
|
||||
const page = industryPages.find((entry) => entry.slug === params.industry);
|
||||
if (!page) return {};
|
||||
|
||||
return buildIndustryMetadata({
|
||||
title: page.metaTitle || page.title,
|
||||
fallbackTitle: page.title,
|
||||
description: page.metaDescription,
|
||||
canonicalPath: `/qr-code-for/${page.slug}`,
|
||||
});
|
||||
}
|
||||
|
||||
function getToolCta(toolSlug?: string): Cta | null {
|
||||
if (!toolSlug) return null;
|
||||
const tool = toolsMap[toolSlug];
|
||||
if (!tool) return null;
|
||||
|
||||
if (toolSlug === "url-qr-code") {
|
||||
return { href: tool.href, label: "Create a QR Code" };
|
||||
}
|
||||
|
||||
return { href: tool.href, label: `Create a ${tool.title}` };
|
||||
}
|
||||
|
||||
function getPrimaryCta(page: (typeof industryPages)[number]): Cta {
|
||||
return (
|
||||
industryPrimaryCtas[page.slug] ??
|
||||
getToolCta(page.tools[0]) ?? {
|
||||
href: "/dynamic-qr-code-generator",
|
||||
label: "Create a Dynamic QR Code",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getSecondaryCta(page: (typeof industryPages)[number]): Cta {
|
||||
return (
|
||||
industrySecondaryCtas[page.slug] ?? {
|
||||
href: "/pricing",
|
||||
label: "View Plans",
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getHeroImageAlt(page: (typeof industryPages)[number]) {
|
||||
return `${page.name} QR code example showing a real-world workflow for ${page.useCases[0]?.toLowerCase() ?? "customer engagement"}.`;
|
||||
}
|
||||
|
||||
export default function IndustryPage({ params }: { params: { industry: string } }) {
|
||||
const page = industryPages.find((entry) => entry.slug === params.industry);
|
||||
if (!page) notFound();
|
||||
|
||||
const primaryCta = getPrimaryCta(page);
|
||||
const secondaryCta = getSecondaryCta(page);
|
||||
const supportLinks = page.tools.map(
|
||||
(slug) =>
|
||||
toolsMap[slug] ?? {
|
||||
href: "/tools/url-qr-code",
|
||||
title: "QR Code Generator",
|
||||
description: "Create a QR code for your business.",
|
||||
}
|
||||
);
|
||||
const useCaseStrings = Array.isArray(page.useCases) ? page.useCases : [];
|
||||
|
||||
return (
|
||||
<IndustryPageTemplate
|
||||
title={page.title}
|
||||
description={page.metaDescription}
|
||||
eyebrow={page.name}
|
||||
intro={page.subheadline || page.headline}
|
||||
pageType="commercial"
|
||||
cluster="industry"
|
||||
useCase={page.slug}
|
||||
breadcrumbs={[
|
||||
{ name: "Home", url: "/" },
|
||||
{ name: "QR Codes by Industry", url: "/qr-code-for" },
|
||||
{ name: page.title, url: `/qr-code-for/${page.slug}` },
|
||||
]}
|
||||
answer={page.headline}
|
||||
whenToUse={useCaseStrings.slice(0, 3)}
|
||||
comparisonItems={[
|
||||
{ label: "Update destination after printing", value: true, text: "Dynamic QR codes" },
|
||||
{ label: "Track scans by date, device & location", value: true, text: "Built-in analytics" },
|
||||
{ label: "No app needed to scan", value: true, text: "Works with native camera" },
|
||||
]}
|
||||
howToSteps={page.placementTips.slice(0, 3)}
|
||||
primaryCta={primaryCta}
|
||||
secondaryCta={secondaryCta}
|
||||
workflowTitle={`How ${page.name} Use QR Codes`}
|
||||
workflowIntro={`Practical QR code workflows built around how ${page.name.toLowerCase()} actually operate.`}
|
||||
workflowCards={useCaseStrings.slice(0, 3).map((useCase, index) => ({
|
||||
title: `Workflow ${index + 1}`,
|
||||
description: useCase,
|
||||
}))}
|
||||
checklistTitle={`${page.name} QR Code Checklist`}
|
||||
checklist={page.placementTips}
|
||||
supportLinks={supportLinks}
|
||||
faq={page.faq}
|
||||
heroImage={page.heroImage}
|
||||
heroImageAlt={getHeroImageAlt(page)}
|
||||
statistics={page.statistics}
|
||||
benefits={page.benefits}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,335 +1,335 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { ArrowRight, Building2, CheckCircle2 } from "lucide-react";
|
||||
|
||||
import { FAQSection } from "@/components/aeo/FAQSection";
|
||||
import SeoJsonLd from "@/components/SeoJsonLd";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { industryPages } from "@/lib/industry-pages";
|
||||
import { breadcrumbSchema, faqPageSchema } from "@/lib/schema";
|
||||
|
||||
type IndustryCategory = {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
slugs: string[];
|
||||
};
|
||||
|
||||
const categories: IndustryCategory[] = [
|
||||
{
|
||||
id: "food-hospitality",
|
||||
title: "Food, Hospitality, and Guest Experience",
|
||||
description: "Use QR codes to replace printed menus, simplify guest WiFi, speed up bookings, and keep in-venue information current without reprinting.",
|
||||
slugs: [
|
||||
"restaurants",
|
||||
"cafes",
|
||||
"hotels",
|
||||
"bars",
|
||||
"food-trucks",
|
||||
"bakeries",
|
||||
"breweries",
|
||||
"nightclubs",
|
||||
"catering",
|
||||
"wineries",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "health-lifestyle",
|
||||
title: "Health, Wellness, and Personal Services",
|
||||
description: "Support appointment booking, aftercare, digital treatment menus, and high-intent follow-up flows across health and lifestyle businesses.",
|
||||
slugs: [
|
||||
"gyms",
|
||||
"doctors-dentists",
|
||||
"dentists",
|
||||
"yoga-studios",
|
||||
"spas",
|
||||
"beauty-salons",
|
||||
"barbershops",
|
||||
"nail-salons",
|
||||
"tattoo-studios",
|
||||
"pharmacies",
|
||||
"pet-grooming",
|
||||
"veterinarians",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "retail-commerce",
|
||||
title: "Retail, Packaging, and Product Discovery",
|
||||
description: "Bridge shelf, packaging, and in-store discovery with QR codes for demos, manuals, size guides, reviews, and product detail pages.",
|
||||
slugs: [
|
||||
"retail",
|
||||
"clothing-stores",
|
||||
"car-dealerships",
|
||||
"florists",
|
||||
"pet-stores",
|
||||
"electronics-stores",
|
||||
"jewelry-stores",
|
||||
"hardware-stores",
|
||||
"bookstores",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "education-culture-public",
|
||||
title: "Education, Culture, and Public Spaces",
|
||||
description: "Improve access to maps, resources, ticketing, audio guides, and visitor information across campuses, venues, and cultural institutions.",
|
||||
slugs: [
|
||||
"universities",
|
||||
"schools",
|
||||
"museums",
|
||||
"libraries",
|
||||
"theaters",
|
||||
"cinemas",
|
||||
"churches",
|
||||
"art-galleries",
|
||||
"stadiums",
|
||||
"airports",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "services-b2b-events",
|
||||
title: "Services, Real Estate, and Lead Capture",
|
||||
description: "Turn printed materials into measurable lead-gen assets for agencies, property businesses, events, and professional service firms.",
|
||||
slugs: [
|
||||
"real-estate",
|
||||
"events",
|
||||
"wedding-planners",
|
||||
"photographers",
|
||||
"trade-shows",
|
||||
"law-firms",
|
||||
"accountants",
|
||||
"insurance-agencies",
|
||||
"travel-agencies",
|
||||
"coworking-spaces",
|
||||
"property-management",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const hubFaq = [
|
||||
{
|
||||
question: "Which industries get the most value from dynamic QR codes?",
|
||||
answer:
|
||||
"Industries that print menus, flyers, labels, in-store signage, or operational materials usually benefit most because they can update destinations without reprinting every asset.",
|
||||
},
|
||||
{
|
||||
question: "Should industry QR code pages focus on tools or workflows?",
|
||||
answer:
|
||||
"Both matter, but workflow intent usually ranks better. Searchers often want a job-to-be-done answer first, then the right QR code tool to implement it.",
|
||||
},
|
||||
{
|
||||
question: "Are industry-specific QR code pages good for SEO?",
|
||||
answer:
|
||||
"Yes, when each page targets a real search intent, has unique examples, and connects to a relevant next step such as tracking, dynamic QR management, or the matching QR tool.",
|
||||
},
|
||||
{
|
||||
question: "What makes a QR code industry page convert well?",
|
||||
answer:
|
||||
"Clear use cases, realistic placement advice, trust-building FAQs, and a CTA that matches the industry workflow outperform generic sign-up prompts.",
|
||||
},
|
||||
];
|
||||
|
||||
const highlightedLinks = [
|
||||
{ href: "/dynamic-qr-code-generator", title: "Dynamic QR Code Generator", description: "Best next step for menus, signage, packaging, and any printed asset that may change later." },
|
||||
{ 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 = {
|
||||
title: "QR Codes by Industry: Use Cases and Examples",
|
||||
description:
|
||||
"Explore QR code ideas by industry, including restaurants, hotels, retail, healthcare, events, education, and professional services. Find use cases, examples, and the best QR workflow for your business.",
|
||||
alternates: {
|
||||
canonical: "https://www.qrmaster.net/qr-code-for",
|
||||
},
|
||||
openGraph: {
|
||||
title: "QR Codes by Industry | QR Master",
|
||||
description:
|
||||
"Find industry-specific QR code use cases, workflows, and examples for hospitality, retail, healthcare, events, education, and more.",
|
||||
url: "https://www.qrmaster.net/qr-code-for",
|
||||
type: "website",
|
||||
images: ["/og-image.png"],
|
||||
},
|
||||
twitter: {
|
||||
title: "QR Codes by Industry | QR Master",
|
||||
description:
|
||||
"Industry-specific QR code ideas and workflows for restaurants, hotels, retail, events, healthcare, and more.",
|
||||
},
|
||||
};
|
||||
|
||||
function getIndustryBySlug(slug: string) {
|
||||
return industryPages.find((industry) => industry.slug === slug);
|
||||
}
|
||||
|
||||
export default function IndustryOverviewPage() {
|
||||
const itemListSchema = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "CollectionPage",
|
||||
name: "QR Codes by Industry",
|
||||
url: "https://www.qrmaster.net/qr-code-for",
|
||||
mainEntity: {
|
||||
"@type": "ItemList",
|
||||
itemListElement: industryPages.map((industry, index) => ({
|
||||
"@type": "ListItem",
|
||||
position: index + 1,
|
||||
url: `https://www.qrmaster.net/qr-code-for/${industry.slug}`,
|
||||
name: industry.title,
|
||||
})),
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd
|
||||
data={[
|
||||
itemListSchema,
|
||||
breadcrumbSchema([
|
||||
{ name: "Home", url: "/" },
|
||||
{ name: "QR Codes by Industry", url: "/qr-code-for" },
|
||||
]),
|
||||
faqPageSchema(hubFaq),
|
||||
]}
|
||||
/>
|
||||
|
||||
<div className="min-h-screen bg-white text-slate-900 font-sans">
|
||||
<section className="relative overflow-hidden border-b border-slate-100 bg-slate-50/70 pt-24 pb-20 lg:pt-32 lg:pb-24">
|
||||
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,#cbd5e1_1px,transparent_1px),linear-gradient(to_bottom,#cbd5e1_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_85%_75%_at_50%_0%,#000_70%,transparent_110%)] opacity-25" />
|
||||
<div className="pointer-events-none absolute top-0 right-0 h-[28rem] w-[28rem] rounded-full bg-blue-200/40 blur-[110px]" />
|
||||
|
||||
<div className="relative z-10 container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mx-auto max-w-4xl text-center">
|
||||
<div className="mb-6 inline-flex items-center gap-2 rounded-full bg-blue-100 px-3 py-1.5 text-sm font-semibold text-blue-700">
|
||||
<Building2 className="h-4 w-4" />
|
||||
Industry Solutions
|
||||
</div>
|
||||
<h1 className="text-4xl font-extrabold tracking-tight text-slate-900 md:text-6xl">
|
||||
QR Codes by Industry
|
||||
</h1>
|
||||
<p className="mx-auto mt-6 max-w-3xl text-lg leading-relaxed text-slate-600 md:text-xl">
|
||||
Explore industry-specific QR code strategies for hospitality, retail, healthcare, events, education, and professional services. Each page is built around real workflows like menu updates, review collection, guest WiFi, bookings, packaging, and offline campaign tracking.
|
||||
</p>
|
||||
|
||||
<div className="mt-10 flex flex-col items-center justify-center gap-4 sm:flex-row">
|
||||
<Link href="/dynamic-qr-code-generator">
|
||||
<Button size="lg" className="rounded-full bg-blue-600 px-8 py-6 text-base font-bold text-white hover:bg-blue-700">
|
||||
Create a Dynamic QR Code
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/qr-code-tracking">
|
||||
<Button variant="outline" size="lg" className="rounded-full px-8 py-6 text-base font-bold">
|
||||
See QR Tracking Features
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="border-b border-slate-100 bg-white py-8">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{categories.map((category) => (
|
||||
<a
|
||||
key={category.id}
|
||||
href={`#${category.id}`}
|
||||
className="rounded-full border border-slate-200 bg-slate-50 px-4 py-2 text-sm font-semibold text-slate-700 transition-colors hover:border-blue-200 hover:bg-blue-50 hover:text-blue-700"
|
||||
>
|
||||
{category.title}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<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 md:grid-cols-2 lg:grid-cols-3">
|
||||
{highlightedLinks.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="group rounded-3xl border border-slate-200 bg-white p-6 shadow-sm transition-all hover:-translate-y-1 hover:border-blue-200 hover:shadow-lg"
|
||||
>
|
||||
<h2 className="text-lg font-bold text-slate-900 group-hover:text-blue-600">{item.title}</h2>
|
||||
<p className="mt-3 text-sm leading-relaxed text-slate-600">{item.description}</p>
|
||||
<div className="mt-4 inline-flex items-center text-sm font-semibold text-blue-600">
|
||||
Explore <ArrowRight className="ml-2 h-4 w-4" />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{categories.map((category) => {
|
||||
const entries = category.slugs
|
||||
.map(getIndustryBySlug)
|
||||
.filter((industry): industry is NonNullable<typeof industry> => Boolean(industry));
|
||||
|
||||
return (
|
||||
<section
|
||||
key={category.id}
|
||||
id={category.id}
|
||||
className="border-t border-slate-100 py-20 scroll-mt-28"
|
||||
>
|
||||
<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="text-3xl font-bold tracking-tight text-slate-900 sm:text-4xl">
|
||||
{category.title}
|
||||
</h2>
|
||||
<p className="mt-4 text-lg leading-relaxed text-slate-600">
|
||||
{category.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||
{entries.map((industry) => (
|
||||
<Link
|
||||
key={industry.slug}
|
||||
href={`/qr-code-for/${industry.slug}`}
|
||||
className="group flex flex-col rounded-3xl border border-slate-200 bg-white p-8 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:border-blue-200 hover:shadow-xl"
|
||||
>
|
||||
<h3 className="text-2xl font-bold text-slate-900 transition-colors group-hover:text-blue-600">
|
||||
{industry.name}
|
||||
</h3>
|
||||
<p className="mt-3 flex-grow text-slate-600">
|
||||
{industry.metaDescription}
|
||||
</p>
|
||||
<ul className="mt-6 space-y-2">
|
||||
{industry.useCases.slice(0, 2).map((useCase) => (
|
||||
<li key={useCase} className="flex items-start gap-2 text-sm text-slate-500">
|
||||
<CheckCircle2 className="mt-0.5 h-4 w-4 shrink-0 text-blue-600" />
|
||||
<span>{useCase}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="mt-8 flex items-center text-blue-600 font-semibold transition-transform group-hover:translate-x-1">
|
||||
Explore Solutions <ArrowRight className="ml-2 h-5 w-5" />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
})}
|
||||
|
||||
<section className="border-t border-slate-100 bg-slate-50 py-20">
|
||||
<div className="container mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-10 text-center">
|
||||
<h2 className="text-3xl font-bold tracking-tight text-slate-900 sm:text-4xl">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
</div>
|
||||
<div className="rounded-3xl border border-slate-200 bg-white p-6 shadow-sm sm:p-10">
|
||||
<FAQSection items={hubFaq} title="" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { ArrowRight, Building2, CheckCircle2 } from "lucide-react";
|
||||
|
||||
import { FAQSection } from "@/components/aeo/FAQSection";
|
||||
import SeoJsonLd from "@/components/SeoJsonLd";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { industryPages } from "@/lib/industry-pages";
|
||||
import { breadcrumbSchema, faqPageSchema } from "@/lib/schema";
|
||||
|
||||
type IndustryCategory = {
|
||||
id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
slugs: string[];
|
||||
};
|
||||
|
||||
const categories: IndustryCategory[] = [
|
||||
{
|
||||
id: "food-hospitality",
|
||||
title: "Food, Hospitality, and Guest Experience",
|
||||
description: "Use QR codes to replace printed menus, simplify guest WiFi, speed up bookings, and keep in-venue information current without reprinting.",
|
||||
slugs: [
|
||||
"restaurants",
|
||||
"cafes",
|
||||
"hotels",
|
||||
"bars",
|
||||
"food-trucks",
|
||||
"bakeries",
|
||||
"breweries",
|
||||
"nightclubs",
|
||||
"catering",
|
||||
"wineries",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "health-lifestyle",
|
||||
title: "Health, Wellness, and Personal Services",
|
||||
description: "Support appointment booking, aftercare, digital treatment menus, and high-intent follow-up flows across health and lifestyle businesses.",
|
||||
slugs: [
|
||||
"gyms",
|
||||
"doctors-dentists",
|
||||
"dentists",
|
||||
"yoga-studios",
|
||||
"spas",
|
||||
"beauty-salons",
|
||||
"barbershops",
|
||||
"nail-salons",
|
||||
"tattoo-studios",
|
||||
"pharmacies",
|
||||
"pet-grooming",
|
||||
"veterinarians",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "retail-commerce",
|
||||
title: "Retail, Packaging, and Product Discovery",
|
||||
description: "Bridge shelf, packaging, and in-store discovery with QR codes for demos, manuals, size guides, reviews, and product detail pages.",
|
||||
slugs: [
|
||||
"retail",
|
||||
"clothing-stores",
|
||||
"car-dealerships",
|
||||
"florists",
|
||||
"pet-stores",
|
||||
"electronics-stores",
|
||||
"jewelry-stores",
|
||||
"hardware-stores",
|
||||
"bookstores",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "education-culture-public",
|
||||
title: "Education, Culture, and Public Spaces",
|
||||
description: "Improve access to maps, resources, ticketing, audio guides, and visitor information across campuses, venues, and cultural institutions.",
|
||||
slugs: [
|
||||
"universities",
|
||||
"schools",
|
||||
"museums",
|
||||
"libraries",
|
||||
"theaters",
|
||||
"cinemas",
|
||||
"churches",
|
||||
"art-galleries",
|
||||
"stadiums",
|
||||
"airports",
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "services-b2b-events",
|
||||
title: "Services, Real Estate, and Lead Capture",
|
||||
description: "Turn printed materials into measurable lead-gen assets for agencies, property businesses, events, and professional service firms.",
|
||||
slugs: [
|
||||
"real-estate",
|
||||
"events",
|
||||
"wedding-planners",
|
||||
"photographers",
|
||||
"trade-shows",
|
||||
"law-firms",
|
||||
"accountants",
|
||||
"insurance-agencies",
|
||||
"travel-agencies",
|
||||
"coworking-spaces",
|
||||
"property-management",
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const hubFaq = [
|
||||
{
|
||||
question: "Which industries get the most value from dynamic QR codes?",
|
||||
answer:
|
||||
"Industries that print menus, flyers, labels, in-store signage, or operational materials usually benefit most because they can update destinations without reprinting every asset.",
|
||||
},
|
||||
{
|
||||
question: "Should industry QR code pages focus on tools or workflows?",
|
||||
answer:
|
||||
"Both matter, but workflow intent usually ranks better. Searchers often want a job-to-be-done answer first, then the right QR code tool to implement it.",
|
||||
},
|
||||
{
|
||||
question: "Are industry-specific QR code pages good for SEO?",
|
||||
answer:
|
||||
"Yes, when each page targets a real search intent, has unique examples, and connects to a relevant next step such as tracking, dynamic QR management, or the matching QR tool.",
|
||||
},
|
||||
{
|
||||
question: "What makes a QR code industry page convert well?",
|
||||
answer:
|
||||
"Clear use cases, realistic placement advice, trust-building FAQs, and a CTA that matches the industry workflow outperform generic sign-up prompts.",
|
||||
},
|
||||
];
|
||||
|
||||
const highlightedLinks = [
|
||||
{ href: "/dynamic-qr-code-generator", title: "Dynamic QR Code Generator", description: "Best next step for menus, signage, packaging, and any printed asset that may change later." },
|
||||
{ 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 = {
|
||||
title: "QR Codes by Industry: Use Cases and Examples",
|
||||
description:
|
||||
"Explore QR code ideas by industry, including restaurants, hotels, retail, healthcare, events, education, and professional services. Find use cases, examples, and the best QR workflow for your business.",
|
||||
alternates: {
|
||||
canonical: "https://www.qrmaster.net/qr-code-for",
|
||||
},
|
||||
openGraph: {
|
||||
title: "QR Codes by Industry | QR Master",
|
||||
description:
|
||||
"Find industry-specific QR code use cases, workflows, and examples for hospitality, retail, healthcare, events, education, and more.",
|
||||
url: "https://www.qrmaster.net/qr-code-for",
|
||||
type: "website",
|
||||
images: ["/og-image.png"],
|
||||
},
|
||||
twitter: {
|
||||
title: "QR Codes by Industry | QR Master",
|
||||
description:
|
||||
"Industry-specific QR code ideas and workflows for restaurants, hotels, retail, events, healthcare, and more.",
|
||||
},
|
||||
};
|
||||
|
||||
function getIndustryBySlug(slug: string) {
|
||||
return industryPages.find((industry) => industry.slug === slug);
|
||||
}
|
||||
|
||||
export default function IndustryOverviewPage() {
|
||||
const itemListSchema = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "CollectionPage",
|
||||
name: "QR Codes by Industry",
|
||||
url: "https://www.qrmaster.net/qr-code-for",
|
||||
mainEntity: {
|
||||
"@type": "ItemList",
|
||||
itemListElement: industryPages.map((industry, index) => ({
|
||||
"@type": "ListItem",
|
||||
position: index + 1,
|
||||
url: `https://www.qrmaster.net/qr-code-for/${industry.slug}`,
|
||||
name: industry.title,
|
||||
})),
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd
|
||||
data={[
|
||||
itemListSchema,
|
||||
breadcrumbSchema([
|
||||
{ name: "Home", url: "/" },
|
||||
{ name: "QR Codes by Industry", url: "/qr-code-for" },
|
||||
]),
|
||||
faqPageSchema(hubFaq),
|
||||
]}
|
||||
/>
|
||||
|
||||
<div className="min-h-screen bg-white text-slate-900 font-sans">
|
||||
<section className="relative overflow-hidden border-b border-slate-100 bg-slate-50/70 pt-24 pb-20 lg:pt-32 lg:pb-24">
|
||||
<div className="pointer-events-none absolute inset-0 bg-[linear-gradient(to_right,#cbd5e1_1px,transparent_1px),linear-gradient(to_bottom,#cbd5e1_1px,transparent_1px)] bg-[size:4rem_4rem] [mask-image:radial-gradient(ellipse_85%_75%_at_50%_0%,#000_70%,transparent_110%)] opacity-25" />
|
||||
<div className="pointer-events-none absolute top-0 right-0 h-[28rem] w-[28rem] rounded-full bg-blue-200/40 blur-[110px]" />
|
||||
|
||||
<div className="relative z-10 container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mx-auto max-w-4xl text-center">
|
||||
<div className="mb-6 inline-flex items-center gap-2 rounded-full bg-blue-100 px-3 py-1.5 text-sm font-semibold text-blue-700">
|
||||
<Building2 className="h-4 w-4" />
|
||||
Industry Solutions
|
||||
</div>
|
||||
<h1 className="text-4xl font-extrabold tracking-tight text-slate-900 md:text-6xl">
|
||||
QR Codes by Industry
|
||||
</h1>
|
||||
<p className="mx-auto mt-6 max-w-3xl text-lg leading-relaxed text-slate-600 md:text-xl">
|
||||
Explore industry-specific QR code strategies for hospitality, retail, healthcare, events, education, and professional services. Each page is built around real workflows like menu updates, review collection, guest WiFi, bookings, packaging, and offline campaign tracking.
|
||||
</p>
|
||||
|
||||
<div className="mt-10 flex flex-col items-center justify-center gap-4 sm:flex-row">
|
||||
<Link href="/dynamic-qr-code-generator">
|
||||
<Button size="lg" className="rounded-full bg-blue-600 px-8 py-6 text-base font-bold text-white hover:bg-blue-700">
|
||||
Create a Dynamic QR Code
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/qr-code-tracking">
|
||||
<Button variant="outline" size="lg" className="rounded-full px-8 py-6 text-base font-bold">
|
||||
See QR Tracking Features
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="border-b border-slate-100 bg-white py-8">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex flex-wrap gap-3">
|
||||
{categories.map((category) => (
|
||||
<a
|
||||
key={category.id}
|
||||
href={`#${category.id}`}
|
||||
className="rounded-full border border-slate-200 bg-slate-50 px-4 py-2 text-sm font-semibold text-slate-700 transition-colors hover:border-blue-200 hover:bg-blue-50 hover:text-blue-700"
|
||||
>
|
||||
{category.title}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<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 md:grid-cols-2 lg:grid-cols-3">
|
||||
{highlightedLinks.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
className="group rounded-3xl border border-slate-200 bg-white p-6 shadow-sm transition-all hover:-translate-y-1 hover:border-blue-200 hover:shadow-lg"
|
||||
>
|
||||
<h2 className="text-lg font-bold text-slate-900 group-hover:text-blue-600">{item.title}</h2>
|
||||
<p className="mt-3 text-sm leading-relaxed text-slate-600">{item.description}</p>
|
||||
<div className="mt-4 inline-flex items-center text-sm font-semibold text-blue-600">
|
||||
Explore <ArrowRight className="ml-2 h-4 w-4" />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{categories.map((category) => {
|
||||
const entries = category.slugs
|
||||
.map(getIndustryBySlug)
|
||||
.filter((industry): industry is NonNullable<typeof industry> => Boolean(industry));
|
||||
|
||||
return (
|
||||
<section
|
||||
key={category.id}
|
||||
id={category.id}
|
||||
className="border-t border-slate-100 py-20 scroll-mt-28"
|
||||
>
|
||||
<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="text-3xl font-bold tracking-tight text-slate-900 sm:text-4xl">
|
||||
{category.title}
|
||||
</h2>
|
||||
<p className="mt-4 text-lg leading-relaxed text-slate-600">
|
||||
{category.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 gap-8 md:grid-cols-2 lg:grid-cols-3">
|
||||
{entries.map((industry) => (
|
||||
<Link
|
||||
key={industry.slug}
|
||||
href={`/qr-code-for/${industry.slug}`}
|
||||
className="group flex flex-col rounded-3xl border border-slate-200 bg-white p-8 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:border-blue-200 hover:shadow-xl"
|
||||
>
|
||||
<h3 className="text-2xl font-bold text-slate-900 transition-colors group-hover:text-blue-600">
|
||||
{industry.name}
|
||||
</h3>
|
||||
<p className="mt-3 flex-grow text-slate-600">
|
||||
{industry.metaDescription}
|
||||
</p>
|
||||
<ul className="mt-6 space-y-2">
|
||||
{industry.useCases.slice(0, 2).map((useCase) => (
|
||||
<li key={useCase} className="flex items-start gap-2 text-sm text-slate-500">
|
||||
<CheckCircle2 className="mt-0.5 h-4 w-4 shrink-0 text-blue-600" />
|
||||
<span>{useCase}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="mt-8 flex items-center text-blue-600 font-semibold transition-transform group-hover:translate-x-1">
|
||||
Explore Solutions <ArrowRight className="ml-2 h-5 w-5" />
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
})}
|
||||
|
||||
<section className="border-t border-slate-100 bg-slate-50 py-20">
|
||||
<div className="container mx-auto max-w-4xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="mb-10 text-center">
|
||||
<h2 className="text-3xl font-bold tracking-tight text-slate-900 sm:text-4xl">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
</div>
|
||||
<div className="rounded-3xl border border-slate-200 bg-white p-6 shadow-sm sm:p-10">
|
||||
<FAQSection items={hubFaq} title="" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,321 +1,321 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import Breadcrumbs from '@/components/Breadcrumbs';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'QR Code Print Size Guide: Minimum Sizes for Every Surface | QR Master',
|
||||
description: 'The minimum QR code size for print depends on scan distance. This guide gives you exact dimensions for business cards, flyers, posters, and billboards.',
|
||||
keywords: ['minimum qr code size', 'qr code print size', 'qr code size for print', 'how big should a qr code be', 'qr code dimensions'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/qr-code-print-size-guide',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'QR Code Print Size Guide | QR Master',
|
||||
description: 'Exact QR code dimensions for every print surface — from business cards to billboards.',
|
||||
type: 'article',
|
||||
url: 'https://www.qrmaster.net/qr-code-print-size-guide',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
const breadcrumbs = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'QR Code Print Size Guide', url: '/qr-code-print-size-guide' },
|
||||
];
|
||||
|
||||
const articleSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Article',
|
||||
'@id': 'https://www.qrmaster.net/qr-code-print-size-guide#article',
|
||||
headline: 'QR Code Print Size Guide: Minimum Sizes for Every Surface',
|
||||
description: 'The minimum QR code size for print depends on scan distance. This guide gives you exact dimensions for business cards, flyers, posters, and billboards.',
|
||||
author: {
|
||||
'@type': 'Organization',
|
||||
name: 'QR Master',
|
||||
url: 'https://www.qrmaster.net',
|
||||
},
|
||||
publisher: {
|
||||
'@type': 'Organization',
|
||||
name: 'QR Master',
|
||||
url: 'https://www.qrmaster.net',
|
||||
},
|
||||
datePublished: '2026-04-07',
|
||||
dateModified: '2026-04-07',
|
||||
mainEntityOfPage: 'https://www.qrmaster.net/qr-code-print-size-guide',
|
||||
};
|
||||
|
||||
const faqSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'FAQPage',
|
||||
mainEntity: [
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'What is the minimum size for a QR code to be scannable?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'The minimum recommended size is 2 × 2 cm (0.8 × 0.8 in) for QR codes scanned at very close range (under 10 cm), such as on business cards. For most print materials scanned at arm\'s length (30–40 cm), use at least 3 × 3 cm.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'What DPI should I use for printing a QR code?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'For print, export your QR code at a minimum of 300 DPI. For large-format printing (posters, banners), use the vector SVG format instead of PNG — SVG scales to any size without quality loss.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'How big should a QR code be on a poster?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'For an A2 poster (420 × 594 mm) viewed at 1–2 metres, use a QR code that is at least 8 × 8 cm. Larger is always better — a 10 × 10 cm code scans reliably from 2–3 metres away.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'How big should a QR code be on a business card?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'On a standard business card (85 × 55 mm), a QR code of 2 × 2 cm to 2.5 × 2.5 cm works reliably when held at normal reading distance (15–20 cm).',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Does adding a logo to a QR code affect scannability?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'Only if the logo covers more than about 30% of the QR code area. QR codes have built-in error correction. At "Q" (25%) or "H" (30%) error correction level, a logo is fine. Always test scan after adding a logo.',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const sizeData = [
|
||||
{ surface: 'Business Card', scanDistance: '15–20 cm', minSize: '2 × 2 cm', recommended: '2.5 × 2.5 cm', dpi: '300 DPI PNG', format: 'PNG or SVG' },
|
||||
{ surface: 'Flyer / Leaflet', scanDistance: '20–30 cm', minSize: '3 × 3 cm', recommended: '4 × 4 cm', dpi: '300 DPI PNG', format: 'PNG or SVG' },
|
||||
{ surface: 'A4 Poster', scanDistance: '30–60 cm', minSize: '5 × 5 cm', recommended: '7 × 7 cm', dpi: '300 DPI PNG', format: 'SVG recommended' },
|
||||
{ surface: 'A2 / A1 Poster', scanDistance: '1–2 m', minSize: '8 × 8 cm', recommended: '10 × 10 cm', dpi: '300 DPI', format: 'SVG required' },
|
||||
{ surface: 'Window / Banner', scanDistance: '1–3 m', minSize: '10 × 10 cm', recommended: '15 × 15 cm', dpi: 'Vector only', format: 'SVG required' },
|
||||
{ surface: 'Billboard', scanDistance: '3–10 m', minSize: '20 × 20 cm', recommended: '30 × 30 cm', dpi: 'Vector only', format: 'SVG required' },
|
||||
];
|
||||
|
||||
export default function QRCodePrintSizeGuidePage() {
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[articleSchema, faqSchema, breadcrumbSchema(breadcrumbs)]} />
|
||||
|
||||
<div className="min-h-screen bg-white">
|
||||
|
||||
{/* HERO */}
|
||||
<section className="pt-20 pb-12 bg-gradient-to-br from-slate-900 to-slate-700 text-white">
|
||||
<div className="container mx-auto px-4 max-w-4xl">
|
||||
<Breadcrumbs items={breadcrumbs} className="[&_ol]:text-white/70 [&_span.font-semibold]:text-white [&_a]:text-white/70 [&_span]:text-white/70" />
|
||||
<div className="mt-6 inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/80 text-sm font-medium mb-6 border border-white/10">
|
||||
Print Guide
|
||||
</div>
|
||||
<h1 className="text-4xl lg:text-5xl font-black mb-6 leading-tight">
|
||||
QR Code Print Size Guide
|
||||
</h1>
|
||||
<p className="text-xl text-slate-300 max-w-2xl leading-relaxed mb-4">
|
||||
The right QR code size depends on one thing: how far away will the scanner be?
|
||||
This guide gives you exact minimum dimensions for every print surface.
|
||||
</p>
|
||||
<div className="bg-white/10 border border-white/20 rounded-xl p-4 mt-6 max-w-xl">
|
||||
<p className="text-sm font-semibold text-white mb-1">Quick Rule of Thumb</p>
|
||||
<p className="text-slate-300 text-sm">
|
||||
QR code width = scan distance ÷ 10. Example: scanning from 30 cm → minimum 3 cm wide.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* SIZE TABLE */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-8">
|
||||
Recommended Size by Print Surface and Scan Distance
|
||||
</h2>
|
||||
|
||||
<div className="overflow-x-auto rounded-2xl border border-slate-200 shadow-sm">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="bg-slate-900 text-white">
|
||||
<th className="px-5 py-4 text-left font-semibold">Surface</th>
|
||||
<th className="px-5 py-4 text-left font-semibold">Scan Distance</th>
|
||||
<th className="px-5 py-4 text-left font-semibold">Minimum Size</th>
|
||||
<th className="px-5 py-4 text-left font-semibold">Recommended</th>
|
||||
<th className="px-5 py-4 text-left font-semibold">Format</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sizeData.map((row, i) => (
|
||||
<tr key={row.surface} className={i % 2 === 0 ? 'bg-white' : 'bg-slate-50'}>
|
||||
<td className="px-5 py-4 font-semibold text-slate-900">{row.surface}</td>
|
||||
<td className="px-5 py-4 text-slate-600">{row.scanDistance}</td>
|
||||
<td className="px-5 py-4 text-red-700 font-semibold">{row.minSize}</td>
|
||||
<td className="px-5 py-4 text-green-700 font-semibold">{row.recommended}</td>
|
||||
<td className="px-5 py-4 text-slate-600">{row.format}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="mt-4 text-xs text-slate-500">
|
||||
Sizes are for QR codes with standard black-on-white contrast at error correction level Q or H. Reduce minimum sizes by 20% only in ideal lighting conditions.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* DPI & FORMAT GUIDE */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-slate-50 border-y border-slate-200">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-8">DPI and Format Requirements</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="bg-white p-6 rounded-2xl border border-slate-100 shadow-sm">
|
||||
<div className="w-10 h-10 rounded-xl bg-blue-100 flex items-center justify-center mb-4">
|
||||
<span className="font-bold text-blue-700 text-sm">PNG</span>
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">PNG for Small Print</h3>
|
||||
<p className="text-sm text-slate-600 leading-relaxed">
|
||||
Use PNG at <strong>300 DPI minimum</strong> for business cards, flyers, and small posters. Export at 10× your target print size in pixels (e.g. 3 cm at 300 DPI = 354 px).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-2xl border border-emerald-100 shadow-sm ring-1 ring-emerald-200">
|
||||
<div className="w-10 h-10 rounded-xl bg-emerald-100 flex items-center justify-center mb-4">
|
||||
<span className="font-bold text-emerald-700 text-sm">SVG</span>
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">SVG for Everything Larger</h3>
|
||||
<p className="text-sm text-slate-600 leading-relaxed">
|
||||
SVG is a vector format — it scales to any size without quality loss. Use SVG for all A2+ posters, banners, and billboards. QR Master exports SVG directly from the generator.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-2xl border border-slate-100 shadow-sm">
|
||||
<div className="w-10 h-10 rounded-xl bg-amber-100 flex items-center justify-center mb-4">
|
||||
<span className="font-bold text-amber-700 text-sm">ECL</span>
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">Error Correction Level</h3>
|
||||
<p className="text-sm text-slate-600 leading-relaxed">
|
||||
Use <strong>Level Q</strong> (25% recovery) or <strong>Level H</strong> (30% recovery) for print — especially if you add a logo. Higher error correction means more modules and a slightly larger minimum size.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* PRINT CHECKLIST */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-8">Print QR Code Checklist</h2>
|
||||
<ul className="space-y-3">
|
||||
{[
|
||||
'QR code is at least the minimum size for the intended scan distance',
|
||||
'High contrast between QR modules and background (black on white preferred)',
|
||||
'Quiet zone (white border) of at least 4 module widths on all sides',
|
||||
'Exported as SVG for large format, PNG at 300+ DPI for small format',
|
||||
'Scanned from target distance before sending to print',
|
||||
'Error correction set to Q or H if a logo is embedded',
|
||||
'Dynamic QR code used if the destination URL might change',
|
||||
].map((item) => (
|
||||
<li key={item} className="flex items-start gap-3">
|
||||
<span className="mt-0.5 w-5 h-5 rounded-full bg-green-100 flex items-center justify-center shrink-0">
|
||||
<svg className="w-3 h-3 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</span>
|
||||
<span className="text-slate-700 text-sm leading-relaxed">{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<GrowthLinksSection
|
||||
eyebrow="Ready to print?"
|
||||
title="Create your print-ready QR code"
|
||||
description="Generate, customize, and download QR codes in SVG or PNG at any size you need."
|
||||
links={[
|
||||
{
|
||||
href: '/reprint-calculator',
|
||||
title: 'Reprint Cost Calculator',
|
||||
description: 'Calculate how much static reprints are costing vs one dynamic QR subscription.',
|
||||
ctaLabel: 'Calculate reprint savings',
|
||||
},
|
||||
{
|
||||
href: '/dynamic-qr-code-generator',
|
||||
title: 'Dynamic QR Code Generator',
|
||||
description: 'Create QR codes you can update after printing. No reprint needed when links change.',
|
||||
ctaLabel: 'Create dynamic QR code',
|
||||
},
|
||||
{
|
||||
href: '/custom-qr-code-generator',
|
||||
title: 'Custom QR Code Generator',
|
||||
description: 'Add your logo, brand colors, and a frame to create print-ready branded QR codes.',
|
||||
ctaLabel: 'Create custom QR code',
|
||||
},
|
||||
]}
|
||||
pageType="commercial"
|
||||
cluster="print-size-guide"
|
||||
/>
|
||||
|
||||
{/* FAQ */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-slate-50">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-slate-900 text-center mb-10">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
{
|
||||
question: 'What is the minimum size for a QR code to be scannable?',
|
||||
answer: 'The absolute minimum is 2 × 2 cm for scanning at very close range (business cards, held 15 cm away). For most materials, use at least 3 × 3 cm. The general rule: minimum width = scan distance ÷ 10.',
|
||||
},
|
||||
{
|
||||
question: 'What DPI should I use for printing a QR code?',
|
||||
answer: 'Use 300 DPI minimum for all print. For large format (posters, banners, billboards), always use SVG — it is vector-based and scales to any size without quality loss.',
|
||||
},
|
||||
{
|
||||
question: 'How big should a QR code be on a poster?',
|
||||
answer: 'For an A2 poster viewed at 1–2 metres, use at least 8 × 8 cm. For A1 posters viewed from further away, 10 × 10 cm is recommended.',
|
||||
},
|
||||
{
|
||||
question: 'How big should a QR code be on a business card?',
|
||||
answer: 'On a standard business card (85 × 55 mm), a 2 × 2 cm to 2.5 × 2.5 cm QR code works reliably when scanned at normal reading distance.',
|
||||
},
|
||||
{
|
||||
question: 'Does adding a logo affect QR code scannability?',
|
||||
answer: 'Only if the logo covers more than ~30% of the QR area. Use error correction level Q or H when adding logos. Always test scan before printing at scale.',
|
||||
},
|
||||
].map((item) => (
|
||||
<details key={item.question} className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{item.question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{item.answer}
|
||||
</div>
|
||||
</details>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import Breadcrumbs from '@/components/Breadcrumbs';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'QR Code Print Size Guide: Minimum Sizes for Every Surface | QR Master',
|
||||
description: 'The minimum QR code size for print depends on scan distance. This guide gives you exact dimensions for business cards, flyers, posters, and billboards.',
|
||||
keywords: ['minimum qr code size', 'qr code print size', 'qr code size for print', 'how big should a qr code be', 'qr code dimensions'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/qr-code-print-size-guide',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'QR Code Print Size Guide | QR Master',
|
||||
description: 'Exact QR code dimensions for every print surface — from business cards to billboards.',
|
||||
type: 'article',
|
||||
url: 'https://www.qrmaster.net/qr-code-print-size-guide',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
const breadcrumbs = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'QR Code Print Size Guide', url: '/qr-code-print-size-guide' },
|
||||
];
|
||||
|
||||
const articleSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'Article',
|
||||
'@id': 'https://www.qrmaster.net/qr-code-print-size-guide#article',
|
||||
headline: 'QR Code Print Size Guide: Minimum Sizes for Every Surface',
|
||||
description: 'The minimum QR code size for print depends on scan distance. This guide gives you exact dimensions for business cards, flyers, posters, and billboards.',
|
||||
author: {
|
||||
'@type': 'Organization',
|
||||
name: 'QR Master',
|
||||
url: 'https://www.qrmaster.net',
|
||||
},
|
||||
publisher: {
|
||||
'@type': 'Organization',
|
||||
name: 'QR Master',
|
||||
url: 'https://www.qrmaster.net',
|
||||
},
|
||||
datePublished: '2026-04-07',
|
||||
dateModified: '2026-04-07',
|
||||
mainEntityOfPage: 'https://www.qrmaster.net/qr-code-print-size-guide',
|
||||
};
|
||||
|
||||
const faqSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'FAQPage',
|
||||
mainEntity: [
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'What is the minimum size for a QR code to be scannable?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'The minimum recommended size is 2 × 2 cm (0.8 × 0.8 in) for QR codes scanned at very close range (under 10 cm), such as on business cards. For most print materials scanned at arm\'s length (30–40 cm), use at least 3 × 3 cm.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'What DPI should I use for printing a QR code?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'For print, export your QR code at a minimum of 300 DPI. For large-format printing (posters, banners), use the vector SVG format instead of PNG — SVG scales to any size without quality loss.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'How big should a QR code be on a poster?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'For an A2 poster (420 × 594 mm) viewed at 1–2 metres, use a QR code that is at least 8 × 8 cm. Larger is always better — a 10 × 10 cm code scans reliably from 2–3 metres away.',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'How big should a QR code be on a business card?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'On a standard business card (85 × 55 mm), a QR code of 2 × 2 cm to 2.5 × 2.5 cm works reliably when held at normal reading distance (15–20 cm).',
|
||||
},
|
||||
},
|
||||
{
|
||||
'@type': 'Question',
|
||||
name: 'Does adding a logo to a QR code affect scannability?',
|
||||
acceptedAnswer: {
|
||||
'@type': 'Answer',
|
||||
text: 'Only if the logo covers more than about 30% of the QR code area. QR codes have built-in error correction. At "Q" (25%) or "H" (30%) error correction level, a logo is fine. Always test scan after adding a logo.',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const sizeData = [
|
||||
{ surface: 'Business Card', scanDistance: '15–20 cm', minSize: '2 × 2 cm', recommended: '2.5 × 2.5 cm', dpi: '300 DPI PNG', format: 'PNG or SVG' },
|
||||
{ surface: 'Flyer / Leaflet', scanDistance: '20–30 cm', minSize: '3 × 3 cm', recommended: '4 × 4 cm', dpi: '300 DPI PNG', format: 'PNG or SVG' },
|
||||
{ surface: 'A4 Poster', scanDistance: '30–60 cm', minSize: '5 × 5 cm', recommended: '7 × 7 cm', dpi: '300 DPI PNG', format: 'SVG recommended' },
|
||||
{ surface: 'A2 / A1 Poster', scanDistance: '1–2 m', minSize: '8 × 8 cm', recommended: '10 × 10 cm', dpi: '300 DPI', format: 'SVG required' },
|
||||
{ surface: 'Window / Banner', scanDistance: '1–3 m', minSize: '10 × 10 cm', recommended: '15 × 15 cm', dpi: 'Vector only', format: 'SVG required' },
|
||||
{ surface: 'Billboard', scanDistance: '3–10 m', minSize: '20 × 20 cm', recommended: '30 × 30 cm', dpi: 'Vector only', format: 'SVG required' },
|
||||
];
|
||||
|
||||
export default function QRCodePrintSizeGuidePage() {
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[articleSchema, faqSchema, breadcrumbSchema(breadcrumbs)]} />
|
||||
|
||||
<div className="min-h-screen bg-white">
|
||||
|
||||
{/* HERO */}
|
||||
<section className="pt-20 pb-12 bg-gradient-to-br from-slate-900 to-slate-700 text-white">
|
||||
<div className="container mx-auto px-4 max-w-4xl">
|
||||
<Breadcrumbs items={breadcrumbs} className="[&_ol]:text-white/70 [&_span.font-semibold]:text-white [&_a]:text-white/70 [&_span]:text-white/70" />
|
||||
<div className="mt-6 inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/80 text-sm font-medium mb-6 border border-white/10">
|
||||
Print Guide
|
||||
</div>
|
||||
<h1 className="text-4xl lg:text-5xl font-black mb-6 leading-tight">
|
||||
QR Code Print Size Guide
|
||||
</h1>
|
||||
<p className="text-xl text-slate-300 max-w-2xl leading-relaxed mb-4">
|
||||
The right QR code size depends on one thing: how far away will the scanner be?
|
||||
This guide gives you exact minimum dimensions for every print surface.
|
||||
</p>
|
||||
<div className="bg-white/10 border border-white/20 rounded-xl p-4 mt-6 max-w-xl">
|
||||
<p className="text-sm font-semibold text-white mb-1">Quick Rule of Thumb</p>
|
||||
<p className="text-slate-300 text-sm">
|
||||
QR code width = scan distance ÷ 10. Example: scanning from 30 cm → minimum 3 cm wide.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* SIZE TABLE */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-8">
|
||||
Recommended Size by Print Surface and Scan Distance
|
||||
</h2>
|
||||
|
||||
<div className="overflow-x-auto rounded-2xl border border-slate-200 shadow-sm">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="bg-slate-900 text-white">
|
||||
<th className="px-5 py-4 text-left font-semibold">Surface</th>
|
||||
<th className="px-5 py-4 text-left font-semibold">Scan Distance</th>
|
||||
<th className="px-5 py-4 text-left font-semibold">Minimum Size</th>
|
||||
<th className="px-5 py-4 text-left font-semibold">Recommended</th>
|
||||
<th className="px-5 py-4 text-left font-semibold">Format</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{sizeData.map((row, i) => (
|
||||
<tr key={row.surface} className={i % 2 === 0 ? 'bg-white' : 'bg-slate-50'}>
|
||||
<td className="px-5 py-4 font-semibold text-slate-900">{row.surface}</td>
|
||||
<td className="px-5 py-4 text-slate-600">{row.scanDistance}</td>
|
||||
<td className="px-5 py-4 text-red-700 font-semibold">{row.minSize}</td>
|
||||
<td className="px-5 py-4 text-green-700 font-semibold">{row.recommended}</td>
|
||||
<td className="px-5 py-4 text-slate-600">{row.format}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p className="mt-4 text-xs text-slate-500">
|
||||
Sizes are for QR codes with standard black-on-white contrast at error correction level Q or H. Reduce minimum sizes by 20% only in ideal lighting conditions.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* DPI & FORMAT GUIDE */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-slate-50 border-y border-slate-200">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-8">DPI and Format Requirements</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<div className="bg-white p-6 rounded-2xl border border-slate-100 shadow-sm">
|
||||
<div className="w-10 h-10 rounded-xl bg-blue-100 flex items-center justify-center mb-4">
|
||||
<span className="font-bold text-blue-700 text-sm">PNG</span>
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">PNG for Small Print</h3>
|
||||
<p className="text-sm text-slate-600 leading-relaxed">
|
||||
Use PNG at <strong>300 DPI minimum</strong> for business cards, flyers, and small posters. Export at 10× your target print size in pixels (e.g. 3 cm at 300 DPI = 354 px).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-2xl border border-emerald-100 shadow-sm ring-1 ring-emerald-200">
|
||||
<div className="w-10 h-10 rounded-xl bg-emerald-100 flex items-center justify-center mb-4">
|
||||
<span className="font-bold text-emerald-700 text-sm">SVG</span>
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">SVG for Everything Larger</h3>
|
||||
<p className="text-sm text-slate-600 leading-relaxed">
|
||||
SVG is a vector format — it scales to any size without quality loss. Use SVG for all A2+ posters, banners, and billboards. QR Master exports SVG directly from the generator.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-white p-6 rounded-2xl border border-slate-100 shadow-sm">
|
||||
<div className="w-10 h-10 rounded-xl bg-amber-100 flex items-center justify-center mb-4">
|
||||
<span className="font-bold text-amber-700 text-sm">ECL</span>
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">Error Correction Level</h3>
|
||||
<p className="text-sm text-slate-600 leading-relaxed">
|
||||
Use <strong>Level Q</strong> (25% recovery) or <strong>Level H</strong> (30% recovery) for print — especially if you add a logo. Higher error correction means more modules and a slightly larger minimum size.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* PRINT CHECKLIST */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-8">Print QR Code Checklist</h2>
|
||||
<ul className="space-y-3">
|
||||
{[
|
||||
'QR code is at least the minimum size for the intended scan distance',
|
||||
'High contrast between QR modules and background (black on white preferred)',
|
||||
'Quiet zone (white border) of at least 4 module widths on all sides',
|
||||
'Exported as SVG for large format, PNG at 300+ DPI for small format',
|
||||
'Scanned from target distance before sending to print',
|
||||
'Error correction set to Q or H if a logo is embedded',
|
||||
'Dynamic QR code used if the destination URL might change',
|
||||
].map((item) => (
|
||||
<li key={item} className="flex items-start gap-3">
|
||||
<span className="mt-0.5 w-5 h-5 rounded-full bg-green-100 flex items-center justify-center shrink-0">
|
||||
<svg className="w-3 h-3 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={3}>
|
||||
<path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</span>
|
||||
<span className="text-slate-700 text-sm leading-relaxed">{item}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<GrowthLinksSection
|
||||
eyebrow="Ready to print?"
|
||||
title="Create your print-ready QR code"
|
||||
description="Generate, customize, and download QR codes in SVG or PNG at any size you need."
|
||||
links={[
|
||||
{
|
||||
href: '/reprint-calculator',
|
||||
title: 'Reprint Cost Calculator',
|
||||
description: 'Calculate how much static reprints are costing vs one dynamic QR subscription.',
|
||||
ctaLabel: 'Calculate reprint savings',
|
||||
},
|
||||
{
|
||||
href: '/dynamic-qr-code-generator',
|
||||
title: 'Dynamic QR Code Generator',
|
||||
description: 'Create QR codes you can update after printing. No reprint needed when links change.',
|
||||
ctaLabel: 'Create dynamic QR code',
|
||||
},
|
||||
{
|
||||
href: '/custom-qr-code-generator',
|
||||
title: 'Custom QR Code Generator',
|
||||
description: 'Add your logo, brand colors, and a frame to create print-ready branded QR codes.',
|
||||
ctaLabel: 'Create custom QR code',
|
||||
},
|
||||
]}
|
||||
pageType="commercial"
|
||||
cluster="print-size-guide"
|
||||
/>
|
||||
|
||||
{/* FAQ */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-slate-50">
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-2xl font-bold text-slate-900 text-center mb-10">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
|
||||
<div className="space-y-4">
|
||||
{[
|
||||
{
|
||||
question: 'What is the minimum size for a QR code to be scannable?',
|
||||
answer: 'The absolute minimum is 2 × 2 cm for scanning at very close range (business cards, held 15 cm away). For most materials, use at least 3 × 3 cm. The general rule: minimum width = scan distance ÷ 10.',
|
||||
},
|
||||
{
|
||||
question: 'What DPI should I use for printing a QR code?',
|
||||
answer: 'Use 300 DPI minimum for all print. For large format (posters, banners, billboards), always use SVG — it is vector-based and scales to any size without quality loss.',
|
||||
},
|
||||
{
|
||||
question: 'How big should a QR code be on a poster?',
|
||||
answer: 'For an A2 poster viewed at 1–2 metres, use at least 8 × 8 cm. For A1 posters viewed from further away, 10 × 10 cm is recommended.',
|
||||
},
|
||||
{
|
||||
question: 'How big should a QR code be on a business card?',
|
||||
answer: 'On a standard business card (85 × 55 mm), a 2 × 2 cm to 2.5 × 2.5 cm QR code works reliably when scanned at normal reading distance.',
|
||||
},
|
||||
{
|
||||
question: 'Does adding a logo affect QR code scannability?',
|
||||
answer: 'Only if the logo covers more than ~30% of the QR area. Use error correction level Q or H when adding logos. Always test scan before printing at scale.',
|
||||
},
|
||||
].map((item) => (
|
||||
<details key={item.question} className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{item.question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{item.answer}
|
||||
</div>
|
||||
</details>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,219 +1,219 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { toPng } from 'html-to-image';
|
||||
import { Star, Download, AlertCircle } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup';
|
||||
|
||||
const QR_COLORS = [
|
||||
{ name: 'Google Blue', value: '#1A73E8' },
|
||||
{ name: 'Classic Black', value: '#000000' },
|
||||
{ name: 'Indigo', value: '#4F46E5' },
|
||||
{ name: 'Emerald', value: '#10B981' },
|
||||
{ name: 'Rose', value: '#F43F5E' },
|
||||
{ name: 'Violet', value: '#7C3AED' },
|
||||
];
|
||||
|
||||
const FRAME_OPTIONS = [
|
||||
{ id: 'none', label: 'No Frame' },
|
||||
{ id: 'review', label: 'Leave a Review' },
|
||||
{ id: 'scanme', label: 'Scan Me' },
|
||||
{ id: 'feedback', label: 'Share Feedback' },
|
||||
];
|
||||
|
||||
function isValidGoogleReviewLink(url: string): boolean {
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
return (
|
||||
parsed.hostname.includes('google.com') ||
|
||||
parsed.hostname.includes('g.page') ||
|
||||
parsed.hostname.includes('maps.app.goo.gl')
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default function GoogleReviewGenerator() {
|
||||
const [reviewUrl, setReviewUrl] = useState('');
|
||||
const [qrColor, setQrColor] = useState('#1A73E8');
|
||||
const [frameType, setFrameType] = useState('review');
|
||||
const [error, setError] = useState('');
|
||||
const [showPopup, setShowPopup] = useState(false);
|
||||
|
||||
const qrRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleUrlChange = (value: string) => {
|
||||
setReviewUrl(value);
|
||||
if (value && !isValidGoogleReviewLink(value)) {
|
||||
setError('Please enter a valid Google Review link (google.com, g.page, or maps.app.goo.gl)');
|
||||
} else {
|
||||
setError('');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownload = async (format: 'png' | 'svg') => {
|
||||
if (!qrRef.current) return;
|
||||
try {
|
||||
if (format === 'png') {
|
||||
const dataUrl = await toPng(qrRef.current, { cacheBust: true, pixelRatio: 3 });
|
||||
const link = document.createElement('a');
|
||||
link.download = 'google-review-qr-code.png';
|
||||
link.href = dataUrl;
|
||||
link.click();
|
||||
} else {
|
||||
const svgData = qrRef.current.querySelector('svg')?.outerHTML;
|
||||
if (svgData) {
|
||||
const blob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = 'google-review-qr-code.svg';
|
||||
link.click();
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Download failed', err);
|
||||
}
|
||||
if (shouldShowDownloadPopup()) setShowPopup(true);
|
||||
};
|
||||
|
||||
const frameLabel = FRAME_OPTIONS.find(f => f.id === frameType && f.id !== 'none')?.label ?? null;
|
||||
const isReady = reviewUrl && !error && isValidGoogleReviewLink(reviewUrl);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PostDownloadPopup open={showPopup} onClose={() => setShowPopup(false)} />
|
||||
<div className="w-full max-w-5xl mx-auto px-4 md:px-6">
|
||||
<div className="bg-white rounded-3xl shadow-2xl shadow-slate-900/10 overflow-hidden border border-slate-100">
|
||||
<div className="grid lg:grid-cols-2">
|
||||
|
||||
{/* LEFT: Input */}
|
||||
<div className="p-6 md:p-8 lg:p-10 space-y-8 border-r border-slate-100">
|
||||
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-lg font-bold text-slate-900 flex items-center gap-2">
|
||||
<Star className="w-5 h-5 text-yellow-500" />
|
||||
Your Google Review Link
|
||||
</h2>
|
||||
|
||||
<div>
|
||||
<Input
|
||||
type="url"
|
||||
placeholder="https://g.page/r/YOUR_ID/review"
|
||||
value={reviewUrl}
|
||||
onChange={(e) => handleUrlChange(e.target.value)}
|
||||
className="w-full font-mono text-sm"
|
||||
/>
|
||||
{error && (
|
||||
<div className="mt-2 flex items-center gap-2 text-sm text-red-600">
|
||||
<AlertCircle className="w-4 h-4 shrink-0" />
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
{!reviewUrl && (
|
||||
<p className="mt-2 text-xs text-slate-500">
|
||||
Go to Google Maps → find your business → Share → Copy link
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Color Picker */}
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-sm font-semibold text-slate-700">QR Color</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{QR_COLORS.map((color) => (
|
||||
<button
|
||||
key={color.value}
|
||||
onClick={() => setQrColor(color.value)}
|
||||
className={`w-8 h-8 rounded-full border-2 transition-all ${
|
||||
qrColor === color.value
|
||||
? 'border-slate-900 scale-110'
|
||||
: 'border-transparent hover:border-slate-300'
|
||||
}`}
|
||||
style={{ backgroundColor: color.value }}
|
||||
title={color.name}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Frame */}
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-sm font-semibold text-slate-700">Frame Label</h3>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{FRAME_OPTIONS.map((frame) => (
|
||||
<button
|
||||
key={frame.id}
|
||||
onClick={() => setFrameType(frame.id)}
|
||||
className={`px-3 py-2 rounded-xl text-sm font-medium border transition-all ${
|
||||
frameType === frame.id
|
||||
? 'border-blue-600 bg-blue-50 text-blue-700'
|
||||
: 'border-slate-200 text-slate-600 hover:border-slate-300'
|
||||
}`}
|
||||
>
|
||||
{frame.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Download Buttons */}
|
||||
<div className="space-y-3">
|
||||
<Button
|
||||
onClick={() => handleDownload('png')}
|
||||
disabled={!isReady}
|
||||
className="w-full flex items-center justify-center gap-2"
|
||||
>
|
||||
<Download className="w-4 h-4" />
|
||||
Download PNG
|
||||
</Button>
|
||||
<button
|
||||
onClick={() => handleDownload('svg')}
|
||||
disabled={!isReady}
|
||||
className="w-full px-4 py-2.5 rounded-xl border border-slate-200 text-slate-700 text-sm font-medium hover:border-slate-300 hover:bg-slate-50 transition-all disabled:opacity-40 disabled:cursor-not-allowed flex items-center justify-center gap-2"
|
||||
>
|
||||
<Download className="w-4 h-4" />
|
||||
Download SVG
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT: Preview */}
|
||||
<div className="p-6 md:p-8 lg:p-10 flex flex-col items-center justify-center bg-slate-50">
|
||||
<h3 className="text-sm font-semibold text-slate-500 uppercase tracking-wider mb-6">Preview</h3>
|
||||
|
||||
<div ref={qrRef} className="flex flex-col items-center bg-white p-6 rounded-2xl shadow-sm border border-slate-100">
|
||||
<QRCodeSVG
|
||||
value={isReady ? reviewUrl : 'https://www.qrmaster.net/tools/google-review-qr-code'}
|
||||
size={200}
|
||||
fgColor={qrColor}
|
||||
level="Q"
|
||||
includeMargin={true}
|
||||
/>
|
||||
{frameLabel && (
|
||||
<div
|
||||
className="mt-3 px-4 py-1.5 rounded-full text-sm font-semibold text-white"
|
||||
style={{ backgroundColor: qrColor }}
|
||||
>
|
||||
{frameLabel}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!isReady && (
|
||||
<p className="mt-4 text-xs text-slate-400 text-center max-w-[200px]">
|
||||
Enter your Google Review link to generate your QR code
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
'use client';
|
||||
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { toPng } from 'html-to-image';
|
||||
import { Star, Download, AlertCircle } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import PostDownloadPopup, { shouldShowDownloadPopup } from '@/components/marketing/PostDownloadPopup';
|
||||
|
||||
const QR_COLORS = [
|
||||
{ name: 'Google Blue', value: '#1A73E8' },
|
||||
{ name: 'Classic Black', value: '#000000' },
|
||||
{ name: 'Indigo', value: '#4F46E5' },
|
||||
{ name: 'Emerald', value: '#10B981' },
|
||||
{ name: 'Rose', value: '#F43F5E' },
|
||||
{ name: 'Violet', value: '#7C3AED' },
|
||||
];
|
||||
|
||||
const FRAME_OPTIONS = [
|
||||
{ id: 'none', label: 'No Frame' },
|
||||
{ id: 'review', label: 'Leave a Review' },
|
||||
{ id: 'scanme', label: 'Scan Me' },
|
||||
{ id: 'feedback', label: 'Share Feedback' },
|
||||
];
|
||||
|
||||
function isValidGoogleReviewLink(url: string): boolean {
|
||||
try {
|
||||
const parsed = new URL(url);
|
||||
return (
|
||||
parsed.hostname.includes('google.com') ||
|
||||
parsed.hostname.includes('g.page') ||
|
||||
parsed.hostname.includes('maps.app.goo.gl')
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export default function GoogleReviewGenerator() {
|
||||
const [reviewUrl, setReviewUrl] = useState('');
|
||||
const [qrColor, setQrColor] = useState('#1A73E8');
|
||||
const [frameType, setFrameType] = useState('review');
|
||||
const [error, setError] = useState('');
|
||||
const [showPopup, setShowPopup] = useState(false);
|
||||
|
||||
const qrRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const handleUrlChange = (value: string) => {
|
||||
setReviewUrl(value);
|
||||
if (value && !isValidGoogleReviewLink(value)) {
|
||||
setError('Please enter a valid Google Review link (google.com, g.page, or maps.app.goo.gl)');
|
||||
} else {
|
||||
setError('');
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownload = async (format: 'png' | 'svg') => {
|
||||
if (!qrRef.current) return;
|
||||
try {
|
||||
if (format === 'png') {
|
||||
const dataUrl = await toPng(qrRef.current, { cacheBust: true, pixelRatio: 3 });
|
||||
const link = document.createElement('a');
|
||||
link.download = 'google-review-qr-code.png';
|
||||
link.href = dataUrl;
|
||||
link.click();
|
||||
} else {
|
||||
const svgData = qrRef.current.querySelector('svg')?.outerHTML;
|
||||
if (svgData) {
|
||||
const blob = new Blob([svgData], { type: 'image/svg+xml;charset=utf-8' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = 'google-review-qr-code.svg';
|
||||
link.click();
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Download failed', err);
|
||||
}
|
||||
if (shouldShowDownloadPopup()) setShowPopup(true);
|
||||
};
|
||||
|
||||
const frameLabel = FRAME_OPTIONS.find(f => f.id === frameType && f.id !== 'none')?.label ?? null;
|
||||
const isReady = reviewUrl && !error && isValidGoogleReviewLink(reviewUrl);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PostDownloadPopup open={showPopup} onClose={() => setShowPopup(false)} />
|
||||
<div className="w-full max-w-5xl mx-auto px-4 md:px-6">
|
||||
<div className="bg-white rounded-3xl shadow-2xl shadow-slate-900/10 overflow-hidden border border-slate-100">
|
||||
<div className="grid lg:grid-cols-2">
|
||||
|
||||
{/* LEFT: Input */}
|
||||
<div className="p-6 md:p-8 lg:p-10 space-y-8 border-r border-slate-100">
|
||||
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-lg font-bold text-slate-900 flex items-center gap-2">
|
||||
<Star className="w-5 h-5 text-yellow-500" />
|
||||
Your Google Review Link
|
||||
</h2>
|
||||
|
||||
<div>
|
||||
<Input
|
||||
type="url"
|
||||
placeholder="https://g.page/r/YOUR_ID/review"
|
||||
value={reviewUrl}
|
||||
onChange={(e) => handleUrlChange(e.target.value)}
|
||||
className="w-full font-mono text-sm"
|
||||
/>
|
||||
{error && (
|
||||
<div className="mt-2 flex items-center gap-2 text-sm text-red-600">
|
||||
<AlertCircle className="w-4 h-4 shrink-0" />
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
{!reviewUrl && (
|
||||
<p className="mt-2 text-xs text-slate-500">
|
||||
Go to Google Maps → find your business → Share → Copy link
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Color Picker */}
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-sm font-semibold text-slate-700">QR Color</h3>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{QR_COLORS.map((color) => (
|
||||
<button
|
||||
key={color.value}
|
||||
onClick={() => setQrColor(color.value)}
|
||||
className={`w-8 h-8 rounded-full border-2 transition-all ${
|
||||
qrColor === color.value
|
||||
? 'border-slate-900 scale-110'
|
||||
: 'border-transparent hover:border-slate-300'
|
||||
}`}
|
||||
style={{ backgroundColor: color.value }}
|
||||
title={color.name}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Frame */}
|
||||
<div className="space-y-3">
|
||||
<h3 className="text-sm font-semibold text-slate-700">Frame Label</h3>
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{FRAME_OPTIONS.map((frame) => (
|
||||
<button
|
||||
key={frame.id}
|
||||
onClick={() => setFrameType(frame.id)}
|
||||
className={`px-3 py-2 rounded-xl text-sm font-medium border transition-all ${
|
||||
frameType === frame.id
|
||||
? 'border-blue-600 bg-blue-50 text-blue-700'
|
||||
: 'border-slate-200 text-slate-600 hover:border-slate-300'
|
||||
}`}
|
||||
>
|
||||
{frame.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Download Buttons */}
|
||||
<div className="space-y-3">
|
||||
<Button
|
||||
onClick={() => handleDownload('png')}
|
||||
disabled={!isReady}
|
||||
className="w-full flex items-center justify-center gap-2"
|
||||
>
|
||||
<Download className="w-4 h-4" />
|
||||
Download PNG
|
||||
</Button>
|
||||
<button
|
||||
onClick={() => handleDownload('svg')}
|
||||
disabled={!isReady}
|
||||
className="w-full px-4 py-2.5 rounded-xl border border-slate-200 text-slate-700 text-sm font-medium hover:border-slate-300 hover:bg-slate-50 transition-all disabled:opacity-40 disabled:cursor-not-allowed flex items-center justify-center gap-2"
|
||||
>
|
||||
<Download className="w-4 h-4" />
|
||||
Download SVG
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* RIGHT: Preview */}
|
||||
<div className="p-6 md:p-8 lg:p-10 flex flex-col items-center justify-center bg-slate-50">
|
||||
<h3 className="text-sm font-semibold text-slate-500 uppercase tracking-wider mb-6">Preview</h3>
|
||||
|
||||
<div ref={qrRef} className="flex flex-col items-center bg-white p-6 rounded-2xl shadow-sm border border-slate-100">
|
||||
<QRCodeSVG
|
||||
value={isReady ? reviewUrl : 'https://www.qrmaster.net/tools/google-review-qr-code'}
|
||||
size={200}
|
||||
fgColor={qrColor}
|
||||
level="Q"
|
||||
includeMargin={true}
|
||||
/>
|
||||
{frameLabel && (
|
||||
<div
|
||||
className="mt-3 px-4 py-1.5 rounded-full text-sm font-semibold text-white"
|
||||
style={{ backgroundColor: qrColor }}
|
||||
>
|
||||
{frameLabel}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!isReady && (
|
||||
<p className="mt-4 text-xs text-slate-400 text-center max-w-[200px]">
|
||||
Enter your Google Review link to generate your QR code
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,397 +1,397 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import InstagramGenerator from './InstagramGenerator';
|
||||
import { Instagram, Shield, Zap, Smartphone, Camera, Heart, Download, Share2, TrendingUp } from 'lucide-react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
import { RelatedTools } from '@/components/marketing/RelatedTools';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { generateSoftwareAppSchema, generateFaqSchema } from '@/lib/schema-utils';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free Instagram QR Code Generator | Get More Followers | QR Master',
|
||||
},
|
||||
description: 'Create a free Instagram QR code for your profile. Scanners follow you instantly — no app login required. Customizable & downloadable in seconds.',
|
||||
keywords: ['instagram qr code', 'insta qr generator', 'ig nametag generator', 'instagram follow qr', 'social media qr code', 'qr code for instagram', 'instagram profile qr code', 'insta qr code', 'instagram nametag generator'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/instagram-qr-code',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/instagram-qr-code',
|
||||
en: 'https://www.qrmaster.net/tools/instagram-qr-code',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free Instagram QR Code Generator | QR Master',
|
||||
description: 'Generate QR codes to grow your Instagram following. Instant app redirect.',
|
||||
type: 'website',
|
||||
url: 'https://www.qrmaster.net/tools/instagram-qr-code',
|
||||
images: [{ url: '/og-instagram-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free Instagram QR Code Generator',
|
||||
description: 'Create QR codes for Instagram. Boost your followers.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
generateSoftwareAppSchema(
|
||||
'Instagram QR Code Generator',
|
||||
'Generate QR codes that direct users to an Instagram profile or post.',
|
||||
'/og-instagram-generator.png'
|
||||
),
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create an Instagram QR Code',
|
||||
description: 'Create a QR code that opens an Instagram profile.',
|
||||
datePublished: '2024-01-01',
|
||||
dateModified: '2026-04-27',
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: 'Timo Knuth',
|
||||
url: 'https://www.qrmaster.net/authors/timo',
|
||||
},
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Enter Username',
|
||||
text: 'Type your Instagram handle (e.g. @yourbrand) or paste your profile link.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Customize',
|
||||
text: 'Choose a gradient color that matches the Instagram vibe or your own brand.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Download',
|
||||
text: 'Save the QR code image.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 4,
|
||||
name: 'Test',
|
||||
text: 'Scan the code to ensure it opens the correct profile.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 5,
|
||||
name: 'Share',
|
||||
text: 'Put it on your packaging, business cards, or storefront.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT30S',
|
||||
},
|
||||
generateFaqSchema({
|
||||
'Is this an Instagram Nametag?': {
|
||||
question: 'Is this an Instagram Nametag?',
|
||||
answer: 'It works similarly! While Instagram has its own internal "Nametag" or "QR Code" feature, our generator allows you to create a standard QR code that is more customizable and can be tracked with our Dynamic plans.',
|
||||
},
|
||||
'Does it open the Instagram app?': {
|
||||
question: 'Does it open the Instagram app?',
|
||||
answer: 'Yes. When scanned on a mobile device with Instagram installed, it will deep-link directly to the profile in the app.',
|
||||
},
|
||||
'Can I link to a specific photo or reel?': {
|
||||
question: 'Can I link to a specific photo or reel?',
|
||||
answer: 'Yes! Instead of your username, just paste the full link to the specific post or reel.',
|
||||
},
|
||||
'Is it free?': {
|
||||
question: 'Is it free?',
|
||||
answer: 'Yes, generating this QR code is 100% free.',
|
||||
},
|
||||
'Can I track scans?': {
|
||||
question: 'Can I track scans?',
|
||||
answer: 'Not with this static tool. If you need scan analytics, consider using our Dynamic QR Code solution.',
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default function InstagramQRCodePage() {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="Instagram QR Code Generator" toolSlug="instagram-qr-code" />
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden bg-gradient-to-br from-[#833AB4] via-[#FD1D1D] to-[#FCA145]">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<circle cx="0" cy="0" r="40" fill="white" fillOpacity="0.1" />
|
||||
<circle cx="100" cy="100" r="50" fill="white" fillOpacity="0.1" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
<div className="text-center lg:text-left">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-pink-300 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-pink-300"></span>
|
||||
</span>
|
||||
Free Tool — No Signup Required
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
Instagram QR Code Generator<br className="hidden lg:block" />
|
||||
<span className="text-white drop-shadow-md">— Boost Your Following</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-pink-50 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Connect physically to digitally. Let customers scan to follow your Instagram profile instantly.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> Grow your brand effortlessly.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/10 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Heart className="w-4 h-4 text-pink-200" />
|
||||
More Likes
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/10 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Zap className="w-4 h-4 text-yellow-200" />
|
||||
Instant Follow
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/10 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Smartphone className="w-4 h-4 text-white" />
|
||||
App Deep Link
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Visual Abstract */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
<div className="absolute w-[500px] h-[500px] bg-white/10 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
<div className="relative w-80 h-96 bg-white/5 backdrop-blur-xl border border-white/20 rounded-3xl shadow-2xl flex flex-col items-center justify-center p-8 transform -rotate-3 hover:rotate-0 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/10 to-transparent rounded-3xl" />
|
||||
|
||||
<div className="w-full bg-white rounded-xl shadow-lg p-4 mb-6 relative overflow-hidden flex flex-col items-center">
|
||||
<div className="w-16 h-16 rounded-full p-[2px] bg-gradient-to-tr from-[#FCA145] via-[#FD1D1D] to-[#833AB4] mb-2">
|
||||
<div className="w-full h-full rounded-full bg-white p-1">
|
||||
<div className="w-full h-full rounded-full bg-slate-200" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm font-bold text-slate-900">@yourbrand</div>
|
||||
</div>
|
||||
|
||||
<div className="w-48 h-48 bg-white rounded-xl p-2 shadow-inner relative overflow-hidden flex items-center justify-center">
|
||||
<QRCodeSVG value="https://www.qrmaster.net" size={170} fgColor="#E1306C" level="Q" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-6 -left-6 bg-white py-3 px-5 rounded-xl shadow-xl flex items-center gap-3 transform transition-transform hover:scale-105 duration-300">
|
||||
<div className="bg-gradient-to-tr from-[#FCA145] to-[#E1306C] p-2 rounded-full text-white">
|
||||
<Camera className="w-5 h-5" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="text-[10px] text-slate-400 font-bold uppercase tracking-wider">Profile</div>
|
||||
<div className="text-sm font-bold text-slate-900">Following</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<InstagramGenerator />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How Instagram QR Codes Work
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Instagram className="w-7 h-7 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Username</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Enter your Instagram handle. No need to login or connect your account.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-7 h-7 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Print</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Add the QR code to your packaging, business cards, or table tents.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Download className="w-6 h-6 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Download</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Save your custom QR code.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Heart className="w-6 h-6 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">4. Scan</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Fans scan to instantly visit your profile.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Share2 className="w-6 h-6 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">5. Grow</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Convert offline traffic into followers.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* STATS SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-[#833AB4]/5 via-[#FD1D1D]/5 to-[#FCA145]/5">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="text-center mb-10">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-[#E1306C]/10 text-[#E1306C] text-sm font-semibold mb-4">
|
||||
<TrendingUp className="w-4 h-4" />
|
||||
Why Instagram QR Codes Work
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-slate-900 mb-3">The Numbers Behind the Strategy</h2>
|
||||
<p className="text-slate-500 text-sm max-w-xl mx-auto">Independent research on Instagram reach and QR code effectiveness.</p>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
<div className="bg-white rounded-2xl p-7 shadow-sm border border-slate-100">
|
||||
<div className="text-4xl font-extrabold text-[#E1306C] mb-2">2 Billion</div>
|
||||
<div className="font-semibold text-slate-800 mb-1">Monthly Active Users on Instagram</div>
|
||||
<p className="text-slate-500 text-sm">Instagram has over 2 billion monthly active users globally, making it one of the largest social platforms for brand discovery. A single well-placed QR code taps directly into that audience.</p>
|
||||
<div className="mt-4 text-xs text-slate-400">Source: Meta, Instagram Press (2023)</div>
|
||||
</div>
|
||||
<div className="bg-white rounded-2xl p-7 shadow-sm border border-slate-100">
|
||||
<div className="text-4xl font-extrabold text-[#833AB4] mb-2">83%</div>
|
||||
<div className="font-semibold text-slate-800 mb-1">of Instagram Users Discover New Brands There</div>
|
||||
<p className="text-slate-500 text-sm">83% of Instagram users say they discover new products and brands on the platform. An Instagram QR code on your packaging or storefront converts that discovery moment offline → online.</p>
|
||||
<div className="mt-4 text-xs text-slate-400">Source: Facebook for Business / Instagram Business (2019)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<RelatedTools />
|
||||
|
||||
<GrowthLinksSection
|
||||
eyebrow="Grow Your Social Presence"
|
||||
title="More Tools to Build Your Brand Online"
|
||||
description="Combine your Instagram QR code with other social and marketing tools from QR Master."
|
||||
pageType="use_case"
|
||||
cluster="social-media"
|
||||
useCase="instagram-qr-code"
|
||||
links={[
|
||||
{
|
||||
href: '/tools/whatsapp-qr-code',
|
||||
title: 'WhatsApp QR Code',
|
||||
description: 'Let customers message you instantly — no number sharing required.',
|
||||
ctaLabel: 'Create WhatsApp QR',
|
||||
},
|
||||
{
|
||||
href: '/tools/vcard-qr-code',
|
||||
title: 'Digital Business Card',
|
||||
description: 'Turn your vCard into a scannable QR code with all your contact details.',
|
||||
ctaLabel: 'Create vCard QR',
|
||||
},
|
||||
{
|
||||
href: '/dynamic-qr-code-generator',
|
||||
title: 'Dynamic QR Codes',
|
||||
description: 'Track how many people scan your Instagram QR code — by day, device, and city.',
|
||||
ctaLabel: 'Try Dynamic QR',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* FAQ SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<p className="text-center text-xs text-slate-400 mb-8">
|
||||
By <a href="/authors/timo" className="underline hover:text-slate-600">Timo Knuth</a> · Last updated: June 2025
|
||||
</p>
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Common questions about Instagram QR codes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="Does this work for private accounts?"
|
||||
answer="Yes, the link will take users to your profile. If your account is private, they will still have to request to follow you."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I link to a Story?"
|
||||
answer="Yes, but Stories expire after 24 hours (unless saved as a Highlight). Linking to a Highlight or your main Profile is usually better for printed materials."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I customize the frame?"
|
||||
answer="Yes, we offer several frame options like 'Follow Us' or 'Scan Me' to encourage action."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Does it expire?"
|
||||
answer="No. The QR code will work as long as your Instagram username remains the same."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I track scans?"
|
||||
answer="Not with this static tool. If you need scan analytics, consider using our Dynamic QR Code solution."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import InstagramGenerator from './InstagramGenerator';
|
||||
import { Instagram, Shield, Zap, Smartphone, Camera, Heart, Download, Share2, TrendingUp } from 'lucide-react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
import { RelatedTools } from '@/components/marketing/RelatedTools';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { generateSoftwareAppSchema, generateFaqSchema } from '@/lib/schema-utils';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free Instagram QR Code Generator | Get More Followers | QR Master',
|
||||
},
|
||||
description: 'Create a free Instagram QR code for your profile. Scanners follow you instantly — no app login required. Customizable & downloadable in seconds.',
|
||||
keywords: ['instagram qr code', 'insta qr generator', 'ig nametag generator', 'instagram follow qr', 'social media qr code', 'qr code for instagram', 'instagram profile qr code', 'insta qr code', 'instagram nametag generator'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/instagram-qr-code',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/instagram-qr-code',
|
||||
en: 'https://www.qrmaster.net/tools/instagram-qr-code',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free Instagram QR Code Generator | QR Master',
|
||||
description: 'Generate QR codes to grow your Instagram following. Instant app redirect.',
|
||||
type: 'website',
|
||||
url: 'https://www.qrmaster.net/tools/instagram-qr-code',
|
||||
images: [{ url: '/og-instagram-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free Instagram QR Code Generator',
|
||||
description: 'Create QR codes for Instagram. Boost your followers.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
generateSoftwareAppSchema(
|
||||
'Instagram QR Code Generator',
|
||||
'Generate QR codes that direct users to an Instagram profile or post.',
|
||||
'/og-instagram-generator.png'
|
||||
),
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create an Instagram QR Code',
|
||||
description: 'Create a QR code that opens an Instagram profile.',
|
||||
datePublished: '2024-01-01',
|
||||
dateModified: '2026-04-27',
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: 'Timo Knuth',
|
||||
url: 'https://www.qrmaster.net/authors/timo',
|
||||
},
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Enter Username',
|
||||
text: 'Type your Instagram handle (e.g. @yourbrand) or paste your profile link.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Customize',
|
||||
text: 'Choose a gradient color that matches the Instagram vibe or your own brand.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Download',
|
||||
text: 'Save the QR code image.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 4,
|
||||
name: 'Test',
|
||||
text: 'Scan the code to ensure it opens the correct profile.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 5,
|
||||
name: 'Share',
|
||||
text: 'Put it on your packaging, business cards, or storefront.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT30S',
|
||||
},
|
||||
generateFaqSchema({
|
||||
'Is this an Instagram Nametag?': {
|
||||
question: 'Is this an Instagram Nametag?',
|
||||
answer: 'It works similarly! While Instagram has its own internal "Nametag" or "QR Code" feature, our generator allows you to create a standard QR code that is more customizable and can be tracked with our Dynamic plans.',
|
||||
},
|
||||
'Does it open the Instagram app?': {
|
||||
question: 'Does it open the Instagram app?',
|
||||
answer: 'Yes. When scanned on a mobile device with Instagram installed, it will deep-link directly to the profile in the app.',
|
||||
},
|
||||
'Can I link to a specific photo or reel?': {
|
||||
question: 'Can I link to a specific photo or reel?',
|
||||
answer: 'Yes! Instead of your username, just paste the full link to the specific post or reel.',
|
||||
},
|
||||
'Is it free?': {
|
||||
question: 'Is it free?',
|
||||
answer: 'Yes, generating this QR code is 100% free.',
|
||||
},
|
||||
'Can I track scans?': {
|
||||
question: 'Can I track scans?',
|
||||
answer: 'Not with this static tool. If you need scan analytics, consider using our Dynamic QR Code solution.',
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default function InstagramQRCodePage() {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="Instagram QR Code Generator" toolSlug="instagram-qr-code" />
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden bg-gradient-to-br from-[#833AB4] via-[#FD1D1D] to-[#FCA145]">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<circle cx="0" cy="0" r="40" fill="white" fillOpacity="0.1" />
|
||||
<circle cx="100" cy="100" r="50" fill="white" fillOpacity="0.1" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
<div className="text-center lg:text-left">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-pink-300 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-pink-300"></span>
|
||||
</span>
|
||||
Free Tool — No Signup Required
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
Instagram QR Code Generator<br className="hidden lg:block" />
|
||||
<span className="text-white drop-shadow-md">— Boost Your Following</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-pink-50 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Connect physically to digitally. Let customers scan to follow your Instagram profile instantly.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> Grow your brand effortlessly.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/10 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Heart className="w-4 h-4 text-pink-200" />
|
||||
More Likes
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/10 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Zap className="w-4 h-4 text-yellow-200" />
|
||||
Instant Follow
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/10 px-4 py-2.5 rounded-xl border border-white/10 backdrop-blur-sm">
|
||||
<Smartphone className="w-4 h-4 text-white" />
|
||||
App Deep Link
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Visual Abstract */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
<div className="absolute w-[500px] h-[500px] bg-white/10 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
<div className="relative w-80 h-96 bg-white/5 backdrop-blur-xl border border-white/20 rounded-3xl shadow-2xl flex flex-col items-center justify-center p-8 transform -rotate-3 hover:rotate-0 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/10 to-transparent rounded-3xl" />
|
||||
|
||||
<div className="w-full bg-white rounded-xl shadow-lg p-4 mb-6 relative overflow-hidden flex flex-col items-center">
|
||||
<div className="w-16 h-16 rounded-full p-[2px] bg-gradient-to-tr from-[#FCA145] via-[#FD1D1D] to-[#833AB4] mb-2">
|
||||
<div className="w-full h-full rounded-full bg-white p-1">
|
||||
<div className="w-full h-full rounded-full bg-slate-200" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm font-bold text-slate-900">@yourbrand</div>
|
||||
</div>
|
||||
|
||||
<div className="w-48 h-48 bg-white rounded-xl p-2 shadow-inner relative overflow-hidden flex items-center justify-center">
|
||||
<QRCodeSVG value="https://www.qrmaster.net" size={170} fgColor="#E1306C" level="Q" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-6 -left-6 bg-white py-3 px-5 rounded-xl shadow-xl flex items-center gap-3 transform transition-transform hover:scale-105 duration-300">
|
||||
<div className="bg-gradient-to-tr from-[#FCA145] to-[#E1306C] p-2 rounded-full text-white">
|
||||
<Camera className="w-5 h-5" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="text-[10px] text-slate-400 font-bold uppercase tracking-wider">Profile</div>
|
||||
<div className="text-sm font-bold text-slate-900">Following</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<InstagramGenerator />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How Instagram QR Codes Work
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Instagram className="w-7 h-7 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Username</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Enter your Instagram handle. No need to login or connect your account.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-7 h-7 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Print</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Add the QR code to your packaging, business cards, or table tents.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Download className="w-6 h-6 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Download</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Save your custom QR code.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Heart className="w-6 h-6 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">4. Scan</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Fans scan to instantly visit your profile.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#E1306C]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Share2 className="w-6 h-6 text-[#E1306C]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">5. Grow</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Convert offline traffic into followers.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* STATS SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-gradient-to-br from-[#833AB4]/5 via-[#FD1D1D]/5 to-[#FCA145]/5">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="text-center mb-10">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-[#E1306C]/10 text-[#E1306C] text-sm font-semibold mb-4">
|
||||
<TrendingUp className="w-4 h-4" />
|
||||
Why Instagram QR Codes Work
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-slate-900 mb-3">The Numbers Behind the Strategy</h2>
|
||||
<p className="text-slate-500 text-sm max-w-xl mx-auto">Independent research on Instagram reach and QR code effectiveness.</p>
|
||||
</div>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
<div className="bg-white rounded-2xl p-7 shadow-sm border border-slate-100">
|
||||
<div className="text-4xl font-extrabold text-[#E1306C] mb-2">2 Billion</div>
|
||||
<div className="font-semibold text-slate-800 mb-1">Monthly Active Users on Instagram</div>
|
||||
<p className="text-slate-500 text-sm">Instagram has over 2 billion monthly active users globally, making it one of the largest social platforms for brand discovery. A single well-placed QR code taps directly into that audience.</p>
|
||||
<div className="mt-4 text-xs text-slate-400">Source: Meta, Instagram Press (2023)</div>
|
||||
</div>
|
||||
<div className="bg-white rounded-2xl p-7 shadow-sm border border-slate-100">
|
||||
<div className="text-4xl font-extrabold text-[#833AB4] mb-2">83%</div>
|
||||
<div className="font-semibold text-slate-800 mb-1">of Instagram Users Discover New Brands There</div>
|
||||
<p className="text-slate-500 text-sm">83% of Instagram users say they discover new products and brands on the platform. An Instagram QR code on your packaging or storefront converts that discovery moment offline → online.</p>
|
||||
<div className="mt-4 text-xs text-slate-400">Source: Facebook for Business / Instagram Business (2019)</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<RelatedTools />
|
||||
|
||||
<GrowthLinksSection
|
||||
eyebrow="Grow Your Social Presence"
|
||||
title="More Tools to Build Your Brand Online"
|
||||
description="Combine your Instagram QR code with other social and marketing tools from QR Master."
|
||||
pageType="use_case"
|
||||
cluster="social-media"
|
||||
useCase="instagram-qr-code"
|
||||
links={[
|
||||
{
|
||||
href: '/tools/whatsapp-qr-code',
|
||||
title: 'WhatsApp QR Code',
|
||||
description: 'Let customers message you instantly — no number sharing required.',
|
||||
ctaLabel: 'Create WhatsApp QR',
|
||||
},
|
||||
{
|
||||
href: '/tools/vcard-qr-code',
|
||||
title: 'Digital Business Card',
|
||||
description: 'Turn your vCard into a scannable QR code with all your contact details.',
|
||||
ctaLabel: 'Create vCard QR',
|
||||
},
|
||||
{
|
||||
href: '/dynamic-qr-code-generator',
|
||||
title: 'Dynamic QR Codes',
|
||||
description: 'Track how many people scan your Instagram QR code — by day, device, and city.',
|
||||
ctaLabel: 'Try Dynamic QR',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* FAQ SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<p className="text-center text-xs text-slate-400 mb-8">
|
||||
By <a href="/authors/timo" className="underline hover:text-slate-600">Timo Knuth</a> · Last updated: June 2025
|
||||
</p>
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Common questions about Instagram QR codes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="Does this work for private accounts?"
|
||||
answer="Yes, the link will take users to your profile. If your account is private, they will still have to request to follow you."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I link to a Story?"
|
||||
answer="Yes, but Stories expire after 24 hours (unless saved as a Highlight). Linking to a Highlight or your main Profile is usually better for printed materials."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I customize the frame?"
|
||||
answer="Yes, we offer several frame options like 'Follow Us' or 'Scan Me' to encourage action."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Does it expire?"
|
||||
answer="No. The QR code will work as long as your Instagram username remains the same."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I track scans?"
|
||||
answer="Not with this static tool. If you need scan analytics, consider using our Dynamic QR Code solution."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,373 +1,373 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import VCardGenerator from './VCardGenerator';
|
||||
import { User, Shield, Zap, Smartphone, Contact, Share2, Check, UserPlus, TrendingUp } from 'lucide-react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
import { RelatedTools } from '@/components/marketing/RelatedTools';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { generateSoftwareAppSchema, generateFaqSchema } from '@/lib/schema-utils';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free vCard QR Code Generator | QR Master',
|
||||
},
|
||||
description: 'Create a vCard QR code for your business card. Share contact details instantly — customers scan and save with one tap. Free, no signup required.',
|
||||
keywords: ['vcard qr code', 'business card qr code', 'contact qr generator', 'digital business card', 'add to contacts qr', 'visitenkarte qr code', 'digitale visitenkarte erstellen', 'kontakt qr code', 'elektronische visitenkarte', 'vcard erstellen kostenlos'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/vcard-qr-code',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/vcard-qr-code',
|
||||
en: 'https://www.qrmaster.net/tools/vcard-qr-code',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free vCard QR Code Generator | QR Master',
|
||||
description: 'Turn your contact info into a QR code. The modern way to share your business card.',
|
||||
type: 'website',
|
||||
url: 'https://www.qrmaster.net/tools/vcard-qr-code',
|
||||
images: [{ url: '/og-vcard-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free vCard QR Code Generator',
|
||||
description: 'Create QR codes for contact sharing. Instant and free.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
generateSoftwareAppSchema(
|
||||
'vCard QR Code Generator',
|
||||
'Generate vCard (VCF) QR codes for business cards. Scanners can save contact info instantly.',
|
||||
'/og-vcard-generator.png'
|
||||
),
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create a vCard QR Code',
|
||||
datePublished: '2024-01-01',
|
||||
dateModified: '2026-04-27',
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: 'Timo Knuth',
|
||||
url: 'https://www.qrmaster.net/authors/timo',
|
||||
},
|
||||
description: 'Create a QR code that saves your contact details.',
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Enter Details',
|
||||
text: 'Fill in your Name, Phone, Email, Company, and Address.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Customize',
|
||||
text: 'Select a color that matches your brand and add a frame.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Download',
|
||||
text: 'Download the QR code image and place it on your physical business card.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT1M',
|
||||
},
|
||||
generateFaqSchema({
|
||||
'How does a vCard QR code work?': {
|
||||
question: 'How does a vCard QR code work?',
|
||||
answer: 'A vCard QR code contains your contact information in a standardized format (VCF). When scanned, the phone recognizes it as a contact card and prompts the user to "Save Contact" to their address book.',
|
||||
},
|
||||
'Is there a limit to how much info I can add?': {
|
||||
question: 'Is there a limit to how much info I can add?',
|
||||
answer: 'Static QR codes hold data directly in the pattern. The more data you add (long addresses, bio), the denser and harder to scan the QR code becomes. We recommend sticking to essential contact info for static codes.',
|
||||
},
|
||||
'Can I update my info later?': {
|
||||
question: 'Can I update my info later?',
|
||||
answer: 'No. This is a static vCard QR code. Once created, the info cannot be changed. If you move jobs or change numbers, you must print a new code. For editable cards, use our Dynamic vCard Plus.',
|
||||
},
|
||||
'Does it work on iPhone and Android?': {
|
||||
question: 'Does it work on iPhone and Android?',
|
||||
answer: 'Yes. Both iOS (Camera app) and Android (Camera or Google Lens) natively support vCard QR codes and correctly import the contact data.',
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default function VCardQRCodePage() {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="vCard QR Code Generator" toolSlug="vcard-qr-code" />
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden" style={{ backgroundColor: '#9F1239' }}>
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<path d="M0 100 C 20 0 50 0 100 100 Z" fill="url(#grad1)" />
|
||||
<defs>
|
||||
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style={{ stopColor: 'white', stopOpacity: 1 }} />
|
||||
<stop offset="100%" style={{ stopColor: 'white', stopOpacity: 0 }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
<div className="text-center lg:text-left">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-rose-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-rose-400"></span>
|
||||
</span>
|
||||
Free Tool — No Signup Required
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
The Modern Way to <br className="hidden lg:block" />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-rose-300 to-pink-300">Share Your Contact</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-indigo-100 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Create a scannable Digital Business Card. One scan saves your name, phone, email, and address instantly.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> Free & Professional.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<UserPlus className="w-4 h-4 text-rose-300" />
|
||||
Instant Save
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Share2 className="w-4 h-4 text-amber-400" />
|
||||
Easy Share
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Shield className="w-4 h-4 text-purple-400" />
|
||||
No Data Stored
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Visual Abstract */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
<div className="absolute w-[500px] h-[500px] bg-indigo-500/30 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
<div className="relative w-96 h-60 bg-white/10 backdrop-blur-2xl border border-white/30 rounded-2xl shadow-2xl p-6 transform rotate-6 hover:rotate-3 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/10 to-transparent" />
|
||||
|
||||
<div className="flex justify-between items-start relative z-10">
|
||||
<div className="space-y-4">
|
||||
<div className="w-16 h-16 rounded-full bg-white/20 border-2 border-white/30 flex items-center justify-center">
|
||||
<Contact className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<div className="h-4 w-32 bg-white/90 rounded-sm" />
|
||||
<div className="h-3 w-20 bg-emerald-400/90 rounded-sm" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-24 h-24 bg-white rounded-lg p-1.5 shadow-lg">
|
||||
<QRCodeSVG value="https://www.qrmaster.net" size={84} fgColor="#1A1265" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-6 left-6 space-y-2 z-10">
|
||||
<div className="h-2 w-48 bg-white/40 rounded-full" />
|
||||
<div className="h-2 w-40 bg-white/30 rounded-full" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-4 -left-4 bg-white py-2 px-4 rounded-lg shadow-xl flex items-center gap-2 transform scale-90">
|
||||
<div className="bg-emerald-100 p-1.5 rounded-full">
|
||||
<Check className="w-3 h-3 text-emerald-600" />
|
||||
</div>
|
||||
<span className="text-xs font-bold text-slate-900">Saved to Contacts</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<VCardGenerator />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How vCard QR Codes Work
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Contact className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Enter Details</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Fill in your professional contact information. Only add what you want to share.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Scan</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
A potential client or partner scans your card with their phone camera.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<UserPlus className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Save</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
They tap "Create New Contact" to save your details instantly. No typing errors.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* WHY DIGITAL BUSINESS CARDS — STATISTICS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<TrendingUp className="w-5 h-5 text-rose-500" />
|
||||
<span className="text-sm font-semibold text-rose-600 uppercase tracking-wider">Research-backed</span>
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-slate-900 mb-4">
|
||||
Why Digital Contact Sharing Outperforms Paper Cards
|
||||
</h2>
|
||||
<p className="text-slate-600 mb-10 max-w-2xl">
|
||||
A <strong>vCard QR code</strong> solves the single biggest problem with traditional business cards: they get discarded before anyone saves your details.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-6 mb-8">
|
||||
<div className="bg-rose-50 border border-rose-100 rounded-2xl p-6">
|
||||
<div className="text-4xl font-extrabold text-rose-600 mb-2">88%</div>
|
||||
<p className="text-slate-700 text-sm leading-relaxed mb-3">
|
||||
of traditional paper business cards are thrown away within a week of being handed out. A vCard QR code on your card saves contact details instantly — no manual typing, no lost connections.
|
||||
</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
Source: <a href="https://www.adobe.com/express/learn/blog/business-card-statistics" target="_blank" rel="noopener noreferrer" className="underline hover:text-slate-700">Adobe Business Research</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-orange-50 border border-orange-100 rounded-2xl p-6">
|
||||
<div className="text-4xl font-extrabold text-orange-600 mb-2">1-tap save</div>
|
||||
<p className="text-slate-700 text-sm leading-relaxed mb-3">
|
||||
Instead of asking someone to manually type your name, phone, and email — a vCard QR code transfers all contact fields (name, phone, email, company, URL) directly into their phone's address book with a single scan.
|
||||
</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
vCard 3.0 / VCF format — supported natively by iOS and Android
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-slate-400 italic">
|
||||
By Timo Knuth, QR Master · Last updated: June 2025 · Based on independent academic and industry research
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GROWTH LINKS */}
|
||||
<GrowthLinksSection
|
||||
eyebrow="Level up your QR strategy"
|
||||
title="More ways to use QR codes for your brand"
|
||||
description="A vCard QR code is a great start. Add custom design, tracking, and dynamic destinations to get the most out of every print."
|
||||
links={[
|
||||
{
|
||||
href: '/custom-qr-code-generator',
|
||||
title: 'Custom QR Code Generator',
|
||||
description: 'Add your logo, brand colors, and a custom frame to your QR codes.',
|
||||
ctaLabel: 'Custom QR with logo',
|
||||
},
|
||||
{
|
||||
href: '/dynamic-qr-code-generator',
|
||||
title: 'Dynamic QR Code Generator',
|
||||
description: 'Update your contact destination after printing. No new QR code needed.',
|
||||
ctaLabel: 'Dynamic QR with tracking',
|
||||
},
|
||||
]}
|
||||
pageType="commercial"
|
||||
cluster="vcard-qr"
|
||||
/>
|
||||
|
||||
{/* RELATED TOOLS */}
|
||||
<RelatedTools />
|
||||
|
||||
{/* FAQ SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Common questions about vCard QR codes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="Can I add a profile picture?"
|
||||
answer="Not on a static vCard QR code. Static codes store data in the pixels, so adding an image would make the code too complex to scan. For profile pictures, social links, and rich media, use our Dynamic vCard Plus solution."
|
||||
/>
|
||||
<FaqItem
|
||||
question="How long does the QR code last?"
|
||||
answer="Forever. Static vCard QR codes do not expire because the data is embedded directly in the image."
|
||||
/>
|
||||
<FaqItem
|
||||
question="What information is required?"
|
||||
answer="Nothing is strictly required, but we recommend at least a First Name and either a Phone Number or Email so the contact is useful."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Is my data safe?"
|
||||
answer="Yes. This tool operates 100% in your browser. We do not store, see, or optimize your contact data. It goes directly from your input to the QR code."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import VCardGenerator from './VCardGenerator';
|
||||
import { User, Shield, Zap, Smartphone, Contact, Share2, Check, UserPlus, TrendingUp } from 'lucide-react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
import { RelatedTools } from '@/components/marketing/RelatedTools';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { generateSoftwareAppSchema, generateFaqSchema } from '@/lib/schema-utils';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free vCard QR Code Generator | QR Master',
|
||||
},
|
||||
description: 'Create a vCard QR code for your business card. Share contact details instantly — customers scan and save with one tap. Free, no signup required.',
|
||||
keywords: ['vcard qr code', 'business card qr code', 'contact qr generator', 'digital business card', 'add to contacts qr', 'visitenkarte qr code', 'digitale visitenkarte erstellen', 'kontakt qr code', 'elektronische visitenkarte', 'vcard erstellen kostenlos'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/vcard-qr-code',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/vcard-qr-code',
|
||||
en: 'https://www.qrmaster.net/tools/vcard-qr-code',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free vCard QR Code Generator | QR Master',
|
||||
description: 'Turn your contact info into a QR code. The modern way to share your business card.',
|
||||
type: 'website',
|
||||
url: 'https://www.qrmaster.net/tools/vcard-qr-code',
|
||||
images: [{ url: '/og-vcard-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free vCard QR Code Generator',
|
||||
description: 'Create QR codes for contact sharing. Instant and free.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
generateSoftwareAppSchema(
|
||||
'vCard QR Code Generator',
|
||||
'Generate vCard (VCF) QR codes for business cards. Scanners can save contact info instantly.',
|
||||
'/og-vcard-generator.png'
|
||||
),
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create a vCard QR Code',
|
||||
datePublished: '2024-01-01',
|
||||
dateModified: '2026-04-27',
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: 'Timo Knuth',
|
||||
url: 'https://www.qrmaster.net/authors/timo',
|
||||
},
|
||||
description: 'Create a QR code that saves your contact details.',
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Enter Details',
|
||||
text: 'Fill in your Name, Phone, Email, Company, and Address.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Customize',
|
||||
text: 'Select a color that matches your brand and add a frame.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Download',
|
||||
text: 'Download the QR code image and place it on your physical business card.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT1M',
|
||||
},
|
||||
generateFaqSchema({
|
||||
'How does a vCard QR code work?': {
|
||||
question: 'How does a vCard QR code work?',
|
||||
answer: 'A vCard QR code contains your contact information in a standardized format (VCF). When scanned, the phone recognizes it as a contact card and prompts the user to "Save Contact" to their address book.',
|
||||
},
|
||||
'Is there a limit to how much info I can add?': {
|
||||
question: 'Is there a limit to how much info I can add?',
|
||||
answer: 'Static QR codes hold data directly in the pattern. The more data you add (long addresses, bio), the denser and harder to scan the QR code becomes. We recommend sticking to essential contact info for static codes.',
|
||||
},
|
||||
'Can I update my info later?': {
|
||||
question: 'Can I update my info later?',
|
||||
answer: 'No. This is a static vCard QR code. Once created, the info cannot be changed. If you move jobs or change numbers, you must print a new code. For editable cards, use our Dynamic vCard Plus.',
|
||||
},
|
||||
'Does it work on iPhone and Android?': {
|
||||
question: 'Does it work on iPhone and Android?',
|
||||
answer: 'Yes. Both iOS (Camera app) and Android (Camera or Google Lens) natively support vCard QR codes and correctly import the contact data.',
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default function VCardQRCodePage() {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="vCard QR Code Generator" toolSlug="vcard-qr-code" />
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden" style={{ backgroundColor: '#9F1239' }}>
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<path d="M0 100 C 20 0 50 0 100 100 Z" fill="url(#grad1)" />
|
||||
<defs>
|
||||
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style={{ stopColor: 'white', stopOpacity: 1 }} />
|
||||
<stop offset="100%" style={{ stopColor: 'white', stopOpacity: 0 }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
<div className="text-center lg:text-left">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-rose-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-rose-400"></span>
|
||||
</span>
|
||||
Free Tool — No Signup Required
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
The Modern Way to <br className="hidden lg:block" />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-rose-300 to-pink-300">Share Your Contact</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-indigo-100 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Create a scannable Digital Business Card. One scan saves your name, phone, email, and address instantly.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> Free & Professional.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<UserPlus className="w-4 h-4 text-rose-300" />
|
||||
Instant Save
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Share2 className="w-4 h-4 text-amber-400" />
|
||||
Easy Share
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Shield className="w-4 h-4 text-purple-400" />
|
||||
No Data Stored
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Visual Abstract */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
<div className="absolute w-[500px] h-[500px] bg-indigo-500/30 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
<div className="relative w-96 h-60 bg-white/10 backdrop-blur-2xl border border-white/30 rounded-2xl shadow-2xl p-6 transform rotate-6 hover:rotate-3 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/10 to-transparent" />
|
||||
|
||||
<div className="flex justify-between items-start relative z-10">
|
||||
<div className="space-y-4">
|
||||
<div className="w-16 h-16 rounded-full bg-white/20 border-2 border-white/30 flex items-center justify-center">
|
||||
<Contact className="w-8 h-8 text-white" />
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
<div className="h-4 w-32 bg-white/90 rounded-sm" />
|
||||
<div className="h-3 w-20 bg-emerald-400/90 rounded-sm" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-24 h-24 bg-white rounded-lg p-1.5 shadow-lg">
|
||||
<QRCodeSVG value="https://www.qrmaster.net" size={84} fgColor="#1A1265" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-6 left-6 space-y-2 z-10">
|
||||
<div className="h-2 w-48 bg-white/40 rounded-full" />
|
||||
<div className="h-2 w-40 bg-white/30 rounded-full" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-4 -left-4 bg-white py-2 px-4 rounded-lg shadow-xl flex items-center gap-2 transform scale-90">
|
||||
<div className="bg-emerald-100 p-1.5 rounded-full">
|
||||
<Check className="w-3 h-3 text-emerald-600" />
|
||||
</div>
|
||||
<span className="text-xs font-bold text-slate-900">Saved to Contacts</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<VCardGenerator />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How vCard QR Codes Work
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Contact className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Enter Details</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
Fill in your professional contact information. Only add what you want to share.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Scan</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
A potential client or partner scans your card with their phone camera.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-14 h-14 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<UserPlus className="w-7 h-7 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Save</h3>
|
||||
<p className="text-slate-600 text-sm">
|
||||
They tap "Create New Contact" to save your details instantly. No typing errors.
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* WHY DIGITAL BUSINESS CARDS — STATISTICS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<TrendingUp className="w-5 h-5 text-rose-500" />
|
||||
<span className="text-sm font-semibold text-rose-600 uppercase tracking-wider">Research-backed</span>
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-slate-900 mb-4">
|
||||
Why Digital Contact Sharing Outperforms Paper Cards
|
||||
</h2>
|
||||
<p className="text-slate-600 mb-10 max-w-2xl">
|
||||
A <strong>vCard QR code</strong> solves the single biggest problem with traditional business cards: they get discarded before anyone saves your details.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-6 mb-8">
|
||||
<div className="bg-rose-50 border border-rose-100 rounded-2xl p-6">
|
||||
<div className="text-4xl font-extrabold text-rose-600 mb-2">88%</div>
|
||||
<p className="text-slate-700 text-sm leading-relaxed mb-3">
|
||||
of traditional paper business cards are thrown away within a week of being handed out. A vCard QR code on your card saves contact details instantly — no manual typing, no lost connections.
|
||||
</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
Source: <a href="https://www.adobe.com/express/learn/blog/business-card-statistics" target="_blank" rel="noopener noreferrer" className="underline hover:text-slate-700">Adobe Business Research</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-orange-50 border border-orange-100 rounded-2xl p-6">
|
||||
<div className="text-4xl font-extrabold text-orange-600 mb-2">1-tap save</div>
|
||||
<p className="text-slate-700 text-sm leading-relaxed mb-3">
|
||||
Instead of asking someone to manually type your name, phone, and email — a vCard QR code transfers all contact fields (name, phone, email, company, URL) directly into their phone's address book with a single scan.
|
||||
</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
vCard 3.0 / VCF format — supported natively by iOS and Android
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-slate-400 italic">
|
||||
By Timo Knuth, QR Master · Last updated: June 2025 · Based on independent academic and industry research
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GROWTH LINKS */}
|
||||
<GrowthLinksSection
|
||||
eyebrow="Level up your QR strategy"
|
||||
title="More ways to use QR codes for your brand"
|
||||
description="A vCard QR code is a great start. Add custom design, tracking, and dynamic destinations to get the most out of every print."
|
||||
links={[
|
||||
{
|
||||
href: '/custom-qr-code-generator',
|
||||
title: 'Custom QR Code Generator',
|
||||
description: 'Add your logo, brand colors, and a custom frame to your QR codes.',
|
||||
ctaLabel: 'Custom QR with logo',
|
||||
},
|
||||
{
|
||||
href: '/dynamic-qr-code-generator',
|
||||
title: 'Dynamic QR Code Generator',
|
||||
description: 'Update your contact destination after printing. No new QR code needed.',
|
||||
ctaLabel: 'Dynamic QR with tracking',
|
||||
},
|
||||
]}
|
||||
pageType="commercial"
|
||||
cluster="vcard-qr"
|
||||
/>
|
||||
|
||||
{/* RELATED TOOLS */}
|
||||
<RelatedTools />
|
||||
|
||||
{/* FAQ SECTION */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Common questions about vCard QR codes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="Can I add a profile picture?"
|
||||
answer="Not on a static vCard QR code. Static codes store data in the pixels, so adding an image would make the code too complex to scan. For profile pictures, social links, and rich media, use our Dynamic vCard Plus solution."
|
||||
/>
|
||||
<FaqItem
|
||||
question="How long does the QR code last?"
|
||||
answer="Forever. Static vCard QR codes do not expire because the data is embedded directly in the image."
|
||||
/>
|
||||
<FaqItem
|
||||
question="What information is required?"
|
||||
answer="Nothing is strictly required, but we recommend at least a First Name and either a Phone Number or Email so the contact is useful."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Is my data safe?"
|
||||
answer="Yes. This tool operates 100% in your browser. We do not store, see, or optimize your contact data. It goes directly from your input to the QR code."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,394 +1,394 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import WiFiGenerator from './WiFiGenerator';
|
||||
import { Wifi, Shield, Zap, Smartphone, Lock, QrCode, Download, Share2, TrendingUp } from 'lucide-react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
import { RelatedTools } from '@/components/marketing/RelatedTools';
|
||||
import { generateSoftwareAppSchema, generateFaqSchema } from '@/lib/schema-utils';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free WiFi QR Code Generator | WLAN QR Code | QR Master',
|
||||
},
|
||||
description: 'Create a WiFi QR code in seconds. Erstelle kostenlos deinen WLAN QR Code ohne Passwort-Eingabe. Guests scan to connect instantly. 100% Secure & Free.',
|
||||
keywords: ['wifi qr code', 'qr code generator', 'wifi qr code generator', 'share wifi', 'wifi password qr', 'guest wifi', 'wlan qr code', 'wlan qr code erstellen', 'wifi passwort qr code', 'wlan zugang teilen', 'wifi qr code kostenlos'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/wifi-qr-code',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/wifi-qr-code',
|
||||
en: 'https://www.qrmaster.net/tools/wifi-qr-code',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free WiFi QR Code Generator | QR Master',
|
||||
description: 'Share your WiFi without sharing your password. Guests scan the QR code to connect instantly.',
|
||||
type: 'website',
|
||||
url: 'https://www.qrmaster.net/tools/wifi-qr-code',
|
||||
images: [{ url: '/og-wifi-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free WiFi QR Code Generator',
|
||||
description: 'Share WiFi instantly with a QR code. No typing passwords.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
// SoftwareApplication Schema
|
||||
generateSoftwareAppSchema(
|
||||
'WiFi QR Code Generator',
|
||||
'Generate QR codes for WiFi networks. Guests scan to connect without typing passwords.',
|
||||
'/og-wifi-generator.png'
|
||||
),
|
||||
// HowTo Schema for Featured Snippets
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create a WiFi QR Code',
|
||||
datePublished: '2024-01-01',
|
||||
dateModified: '2026-04-27',
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: 'Timo Knuth',
|
||||
url: 'https://www.qrmaster.net/authors/timo',
|
||||
},
|
||||
description: 'Create a QR code that connects devices to your WiFi network automatically.',
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Enter Network Name',
|
||||
text: 'Type your WiFi network name (SSID) in the Network Name field.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Enter Password',
|
||||
text: 'Enter your WiFi password. This is processed locally and never sent to any server.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Select Security Type',
|
||||
text: 'Choose WPA/WPA2 (most common), WEP, or No Password for open networks.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 4,
|
||||
name: 'Download QR Code',
|
||||
text: 'Click Download PNG or SVG to save your QR code. Print it or share digitally.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 5,
|
||||
name: 'Connect',
|
||||
text: 'Print the code. Guests can scan it to join your network instantly.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT1M',
|
||||
},
|
||||
// FAQPage Schema
|
||||
generateFaqSchema({
|
||||
'Is it safe to enter my WiFi password?': {
|
||||
question: 'Is it safe to enter my WiFi password?',
|
||||
answer: 'Yes, completely safe. This tool processes everything in your browser (client-side). Your password never leaves your device and is not sent to any server.',
|
||||
},
|
||||
'Do WiFi QR codes work on iPhone and Android?': {
|
||||
question: 'Do WiFi QR codes work on iPhone and Android?',
|
||||
answer: 'Yes. Both iOS (11+) and Android devices can scan WiFi QR codes using their built-in camera app. No additional apps required.',
|
||||
},
|
||||
'What happens if I change my WiFi password?': {
|
||||
question: 'What happens if I change my WiFi password?',
|
||||
answer: 'If you change your WiFi password, the old QR code will stop working. You\'ll need to generate a new QR code with the updated credentials.For frequently changing passwords, consider using dynamic QR codes.',
|
||||
},
|
||||
'Can I customize the QR code design?': {
|
||||
question: 'Can I customize the QR code design?',
|
||||
answer: 'Yes. You can change the QR code color and add frame labels like "Scan Me" or "WiFi" to make it more recognizable and user-friendly.',
|
||||
},
|
||||
'Does it work for hidden networks?': {
|
||||
question: 'Does it work for hidden networks?',
|
||||
answer: 'Yes, just check the "Hidden Network" box if your SSID is hidden. The QR code contains the standard WiFi string configuration.',
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default function WiFiQRCodePage() {
|
||||
return (
|
||||
<>
|
||||
{/* JSON-LD Script */}
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="WiFi QR Code Generator" toolSlug="wifi-qr-code" />
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden" style={{ backgroundColor: '#1A1265' }}>
|
||||
{/* Background Pattern */}
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<path d="M0 100 C 20 0 50 0 100 100 Z" fill="url(#grad1)" />
|
||||
<defs>
|
||||
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style={{ stopColor: 'white', stopOpacity: 1 }} />
|
||||
<stop offset="100%" style={{ stopColor: 'white', stopOpacity: 0 }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
|
||||
{/* Left: Text Content */}
|
||||
<div className="text-center lg:text-left">
|
||||
{/* Badge */}
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-emerald-400"></span>
|
||||
</span>
|
||||
Free Tool — No Signup Required
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
The Safest Way to <br className="hidden lg:block" />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 to-cyan-400">Share Your WiFi</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-indigo-100 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Generate a secure QR code in seconds. No more spelling out complicated passwords.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> 100% Client-Side & Private.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Lock className="w-4 h-4 text-emerald-400" />
|
||||
No Server Uploads
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Zap className="w-4 h-4 text-amber-400" />
|
||||
Instant Connect
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Smartphone className="w-4 h-4 text-purple-400" />
|
||||
iOS & Android
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: Visual Abstract Composition */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
{/* Decorative Glow */}
|
||||
<div className="absolute w-[500px] h-[500px] bg-indigo-500/30 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
{/* Floating Glass Card */}
|
||||
<div className="relative w-80 h-96 bg-white/5 backdrop-blur-xl border border-white/20 rounded-3xl shadow-2xl flex flex-col items-center justify-center p-8 transform rotate-6 hover:rotate-3 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/10 to-transparent rounded-3xl" />
|
||||
|
||||
{/* Mock QR */}
|
||||
<div className="w-48 h-48 bg-white rounded-xl p-2 shadow-inner mb-6 relative overflow-hidden flex items-center justify-center">
|
||||
<QRCodeSVG value="https://www.qrmaster.net" size={170} fgColor="#0f172a" level="Q" />
|
||||
{/* Scan Line */}
|
||||
<div className="absolute top-1/2 left-0 w-full h-1 bg-emerald-500 shadow-[0_0_20px_rgba(16,185,129,1)] animate-pulse" />
|
||||
</div>
|
||||
|
||||
<div className="w-full space-y-3">
|
||||
<div className="h-2 w-32 bg-white/20 rounded-full mx-auto" />
|
||||
<div className="h-2 w-20 bg-white/10 rounded-full mx-auto" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-6 -left-6 bg-white py-3 px-5 rounded-xl shadow-xl flex items-center gap-3 transform transition-transform hover:scale-105 duration-300">
|
||||
<div className="bg-emerald-100 p-2 rounded-full">
|
||||
<Wifi className="w-5 h-5 text-emerald-600" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="text-[10px] text-slate-400 font-bold uppercase tracking-wider">Status</div>
|
||||
<div className="text-sm font-bold text-slate-900">Connected</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<WiFiGenerator />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS - AEO/GEO Content */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How WiFi QR Codes Work
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Wifi className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Network</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Enter your WiFi SSID and password.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Shield className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Security</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Select WPA/WPA2 encryption.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Zap className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Style</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Customize colors and add a frame.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Download className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">4. Download</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Get your high-quality QR image.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">5. Connect</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Print it out. Guests scan to join!
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* WHY WIFI QR CODES MATTER — STATISTICS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<TrendingUp className="w-5 h-5 text-emerald-500" />
|
||||
<span className="text-sm font-semibold text-emerald-600 uppercase tracking-wider">Research-backed</span>
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-slate-900 mb-4">
|
||||
Why WiFi QR Codes Improve Customer Experience
|
||||
</h2>
|
||||
<p className="text-slate-600 mb-10 max-w-2xl">
|
||||
A <strong>WiFi QR code</strong> eliminates the single biggest friction point between your guest and your network — manual password entry.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-6 mb-8">
|
||||
<div className="bg-emerald-50 border border-emerald-100 rounded-2xl p-6">
|
||||
<div className="text-3xl font-extrabold text-emerald-600 mb-2">#1 Amenity</div>
|
||||
<p className="text-slate-700 text-sm leading-relaxed mb-3">
|
||||
Free WiFi is rated the most important hotel amenity by guests — ahead of breakfast, parking, and loyalty points. Instant, frictionless access directly impacts satisfaction scores and repeat bookings.
|
||||
</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
Source: <a href="https://www.jdpower.com/business/travel-hospitality/hotel-guest-satisfaction-study" target="_blank" rel="noopener noreferrer" className="underline hover:text-slate-700">J.D. Power Hotel Guest Satisfaction Study</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-blue-50 border border-blue-100 rounded-2xl p-6">
|
||||
<div className="text-3xl font-extrabold text-blue-600 mb-2">Effort = Loyalty</div>
|
||||
<p className="text-slate-700 text-sm leading-relaxed mb-3">
|
||||
Reducing customer effort — like eliminating manual password entry — is the single strongest predictor of customer loyalty. The lower the effort, the higher the repeat visit rate and positive word-of-mouth.
|
||||
</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
Source: <a href="https://hbr.org/2010/07/stop-trying-to-delight-your-customers" target="_blank" rel="noopener noreferrer" className="underline hover:text-slate-700">Harvard Business Review — "Stop Trying to Delight Your Customers"</a> (Customer Effort Score research)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-slate-400 italic">
|
||||
By Timo Knuth, QR Master · Last updated: June 2025 · Based on independent academic and industry research
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* RELATED TOOLS */}
|
||||
<RelatedTools />
|
||||
|
||||
{/* FAQ SECTION - Featured Snippet Optimized */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Everything you need to know about WiFi QR codes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="Is it safe to enter my WiFi password here?"
|
||||
answer="Yes, completely safe. This tool uses client-side processing, meaning your WiFi password never leaves your device. It's processed locally in your browser to generate the QR code—no data is sent to any server."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Do WiFi QR codes work on iPhone and Android?"
|
||||
answer="Yes. iOS 11 and later, as well as all modern Android devices, can scan WiFi QR codes using the built-in camera app. Simply point the camera at the QR code and tap the notification to connect."
|
||||
/>
|
||||
<FaqItem
|
||||
question="What happens if I change my WiFi password?"
|
||||
answer="If you change your WiFi password, the old QR code will stop working. You'll need to generate a new QR code with the updated credentials. For frequently changing passwords, consider using dynamic QR codes."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I customize the QR code design?"
|
||||
answer="Yes. You can change the foreground color of the QR code and add frame labels such as 'Scan Me', 'WiFi', or 'Connect' to make your QR code more recognizable and user-friendly."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Does it work for hidden networks?"
|
||||
answer="Yes, just check the 'Hidden Network' box if your SSID is hidden. The QR code contains the standard WiFi string configuration."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// FAQ Item Component
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import WiFiGenerator from './WiFiGenerator';
|
||||
import { Wifi, Shield, Zap, Smartphone, Lock, QrCode, Download, Share2, TrendingUp } from 'lucide-react';
|
||||
import { QRCodeSVG } from 'qrcode.react';
|
||||
import { ToolBreadcrumb } from '@/components/seo/BreadcrumbSchema';
|
||||
import { RelatedTools } from '@/components/marketing/RelatedTools';
|
||||
import { generateSoftwareAppSchema, generateFaqSchema } from '@/lib/schema-utils';
|
||||
|
||||
// SEO Optimized Metadata
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Free WiFi QR Code Generator | WLAN QR Code | QR Master',
|
||||
},
|
||||
description: 'Create a WiFi QR code in seconds. Erstelle kostenlos deinen WLAN QR Code ohne Passwort-Eingabe. Guests scan to connect instantly. 100% Secure & Free.',
|
||||
keywords: ['wifi qr code', 'qr code generator', 'wifi qr code generator', 'share wifi', 'wifi password qr', 'guest wifi', 'wlan qr code', 'wlan qr code erstellen', 'wifi passwort qr code', 'wlan zugang teilen', 'wifi qr code kostenlos'],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/wifi-qr-code',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/wifi-qr-code',
|
||||
en: 'https://www.qrmaster.net/tools/wifi-qr-code',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free WiFi QR Code Generator | QR Master',
|
||||
description: 'Share your WiFi without sharing your password. Guests scan the QR code to connect instantly.',
|
||||
type: 'website',
|
||||
url: 'https://www.qrmaster.net/tools/wifi-qr-code',
|
||||
images: [{ url: '/og-wifi-generator.png', width: 1200, height: 630 }],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Free WiFi QR Code Generator',
|
||||
description: 'Share WiFi instantly with a QR code. No typing passwords.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
// JSON-LD Structured Data
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
// SoftwareApplication Schema
|
||||
generateSoftwareAppSchema(
|
||||
'WiFi QR Code Generator',
|
||||
'Generate QR codes for WiFi networks. Guests scan to connect without typing passwords.',
|
||||
'/og-wifi-generator.png'
|
||||
),
|
||||
// HowTo Schema for Featured Snippets
|
||||
{
|
||||
'@type': 'HowTo',
|
||||
name: 'How to Create a WiFi QR Code',
|
||||
datePublished: '2024-01-01',
|
||||
dateModified: '2026-04-27',
|
||||
author: {
|
||||
'@type': 'Person',
|
||||
name: 'Timo Knuth',
|
||||
url: 'https://www.qrmaster.net/authors/timo',
|
||||
},
|
||||
description: 'Create a QR code that connects devices to your WiFi network automatically.',
|
||||
step: [
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 1,
|
||||
name: 'Enter Network Name',
|
||||
text: 'Type your WiFi network name (SSID) in the Network Name field.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 2,
|
||||
name: 'Enter Password',
|
||||
text: 'Enter your WiFi password. This is processed locally and never sent to any server.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 3,
|
||||
name: 'Select Security Type',
|
||||
text: 'Choose WPA/WPA2 (most common), WEP, or No Password for open networks.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 4,
|
||||
name: 'Download QR Code',
|
||||
text: 'Click Download PNG or SVG to save your QR code. Print it or share digitally.',
|
||||
},
|
||||
{
|
||||
'@type': 'HowToStep',
|
||||
position: 5,
|
||||
name: 'Connect',
|
||||
text: 'Print the code. Guests can scan it to join your network instantly.',
|
||||
},
|
||||
],
|
||||
totalTime: 'PT1M',
|
||||
},
|
||||
// FAQPage Schema
|
||||
generateFaqSchema({
|
||||
'Is it safe to enter my WiFi password?': {
|
||||
question: 'Is it safe to enter my WiFi password?',
|
||||
answer: 'Yes, completely safe. This tool processes everything in your browser (client-side). Your password never leaves your device and is not sent to any server.',
|
||||
},
|
||||
'Do WiFi QR codes work on iPhone and Android?': {
|
||||
question: 'Do WiFi QR codes work on iPhone and Android?',
|
||||
answer: 'Yes. Both iOS (11+) and Android devices can scan WiFi QR codes using their built-in camera app. No additional apps required.',
|
||||
},
|
||||
'What happens if I change my WiFi password?': {
|
||||
question: 'What happens if I change my WiFi password?',
|
||||
answer: 'If you change your WiFi password, the old QR code will stop working. You\'ll need to generate a new QR code with the updated credentials.For frequently changing passwords, consider using dynamic QR codes.',
|
||||
},
|
||||
'Can I customize the QR code design?': {
|
||||
question: 'Can I customize the QR code design?',
|
||||
answer: 'Yes. You can change the QR code color and add frame labels like "Scan Me" or "WiFi" to make it more recognizable and user-friendly.',
|
||||
},
|
||||
'Does it work for hidden networks?': {
|
||||
question: 'Does it work for hidden networks?',
|
||||
answer: 'Yes, just check the "Hidden Network" box if your SSID is hidden. The QR code contains the standard WiFi string configuration.',
|
||||
},
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
export default function WiFiQRCodePage() {
|
||||
return (
|
||||
<>
|
||||
{/* JSON-LD Script */}
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ToolBreadcrumb toolName="WiFi QR Code Generator" toolSlug="wifi-qr-code" />
|
||||
|
||||
<div className="min-h-screen" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
|
||||
{/* HERO SECTION */}
|
||||
<section className="relative pt-20 pb-20 lg:pt-32 lg:pb-32 px-4 sm:px-6 lg:px-8 overflow-hidden" style={{ backgroundColor: '#1A1265' }}>
|
||||
{/* Background Pattern */}
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||
<path d="M0 100 C 20 0 50 0 100 100 Z" fill="url(#grad1)" />
|
||||
<defs>
|
||||
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style={{ stopColor: 'white', stopOpacity: 1 }} />
|
||||
<stop offset="100%" style={{ stopColor: 'white', stopOpacity: 0 }} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto grid lg:grid-cols-2 gap-12 items-center relative z-10">
|
||||
|
||||
{/* Left: Text Content */}
|
||||
<div className="text-center lg:text-left">
|
||||
{/* Badge */}
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10 hover:bg-white/20 transition-colors cursor-default">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-emerald-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-emerald-400"></span>
|
||||
</span>
|
||||
Free Tool — No Signup Required
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-white tracking-tight leading-tight mb-6">
|
||||
The Safest Way to <br className="hidden lg:block" />
|
||||
<span className="text-transparent bg-clip-text bg-gradient-to-r from-emerald-400 to-cyan-400">Share Your WiFi</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-indigo-100 max-w-2xl mx-auto lg:mx-0 mb-8 leading-relaxed">
|
||||
Generate a secure QR code in seconds. No more spelling out complicated passwords.
|
||||
<strong className="text-white block sm:inline mt-2 sm:mt-0"> 100% Client-Side & Private.</strong>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center lg:justify-start gap-4 text-sm font-medium text-white/80">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Lock className="w-4 h-4 text-emerald-400" />
|
||||
No Server Uploads
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Zap className="w-4 h-4 text-amber-400" />
|
||||
Instant Connect
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/5 backdrop-blur-sm">
|
||||
<Smartphone className="w-4 h-4 text-purple-400" />
|
||||
iOS & Android
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right: Visual Abstract Composition */}
|
||||
<div className="hidden lg:flex relative items-center justify-center min-h-[400px]">
|
||||
{/* Decorative Glow */}
|
||||
<div className="absolute w-[500px] h-[500px] bg-indigo-500/30 rounded-full blur-[100px] -top-20 -right-20 animate-pulse" />
|
||||
|
||||
{/* Floating Glass Card */}
|
||||
<div className="relative w-80 h-96 bg-white/5 backdrop-blur-xl border border-white/20 rounded-3xl shadow-2xl flex flex-col items-center justify-center p-8 transform rotate-6 hover:rotate-3 transition-all duration-700 group">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-white/10 to-transparent rounded-3xl" />
|
||||
|
||||
{/* Mock QR */}
|
||||
<div className="w-48 h-48 bg-white rounded-xl p-2 shadow-inner mb-6 relative overflow-hidden flex items-center justify-center">
|
||||
<QRCodeSVG value="https://www.qrmaster.net" size={170} fgColor="#0f172a" level="Q" />
|
||||
{/* Scan Line */}
|
||||
<div className="absolute top-1/2 left-0 w-full h-1 bg-emerald-500 shadow-[0_0_20px_rgba(16,185,129,1)] animate-pulse" />
|
||||
</div>
|
||||
|
||||
<div className="w-full space-y-3">
|
||||
<div className="h-2 w-32 bg-white/20 rounded-full mx-auto" />
|
||||
<div className="h-2 w-20 bg-white/10 rounded-full mx-auto" />
|
||||
</div>
|
||||
|
||||
{/* Floating Badge */}
|
||||
<div className="absolute -bottom-6 -left-6 bg-white py-3 px-5 rounded-xl shadow-xl flex items-center gap-3 transform transition-transform hover:scale-105 duration-300">
|
||||
<div className="bg-emerald-100 p-2 rounded-full">
|
||||
<Wifi className="w-5 h-5 text-emerald-600" />
|
||||
</div>
|
||||
<div className="text-left">
|
||||
<div className="text-[10px] text-slate-400 font-bold uppercase tracking-wider">Status</div>
|
||||
<div className="text-sm font-bold text-slate-900">Connected</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* GENERATOR SECTION */}
|
||||
<section className="py-12 px-4 sm:px-6 lg:px-8 -mt-8">
|
||||
<WiFiGenerator />
|
||||
</section>
|
||||
|
||||
{/* HOW IT WORKS - AEO/GEO Content */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-12">
|
||||
How WiFi QR Codes Work
|
||||
</h2>
|
||||
|
||||
<div className="grid md:grid-cols-3 lg:grid-cols-5 gap-8">
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Wifi className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">1. Network</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Enter your WiFi SSID and password.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Shield className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">2. Security</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Select WPA/WPA2 encryption.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Zap className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">3. Style</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Customize colors and add a frame.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Download className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">4. Download</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Get your high-quality QR image.
|
||||
</p>
|
||||
</article>
|
||||
|
||||
<article className="text-center">
|
||||
<div className="w-12 h-12 rounded-2xl bg-[#1A1265]/10 flex items-center justify-center mx-auto mb-4">
|
||||
<Smartphone className="w-6 h-6 text-[#1A1265]" />
|
||||
</div>
|
||||
<h3 className="font-bold text-slate-900 mb-2">5. Connect</h3>
|
||||
<p className="text-slate-600 text-xs leading-relaxed">
|
||||
Print it out. Guests scan to join!
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* WHY WIFI QR CODES MATTER — STATISTICS */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-white">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<div className="flex items-center gap-2 mb-3">
|
||||
<TrendingUp className="w-5 h-5 text-emerald-500" />
|
||||
<span className="text-sm font-semibold text-emerald-600 uppercase tracking-wider">Research-backed</span>
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-slate-900 mb-4">
|
||||
Why WiFi QR Codes Improve Customer Experience
|
||||
</h2>
|
||||
<p className="text-slate-600 mb-10 max-w-2xl">
|
||||
A <strong>WiFi QR code</strong> eliminates the single biggest friction point between your guest and your network — manual password entry.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-6 mb-8">
|
||||
<div className="bg-emerald-50 border border-emerald-100 rounded-2xl p-6">
|
||||
<div className="text-3xl font-extrabold text-emerald-600 mb-2">#1 Amenity</div>
|
||||
<p className="text-slate-700 text-sm leading-relaxed mb-3">
|
||||
Free WiFi is rated the most important hotel amenity by guests — ahead of breakfast, parking, and loyalty points. Instant, frictionless access directly impacts satisfaction scores and repeat bookings.
|
||||
</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
Source: <a href="https://www.jdpower.com/business/travel-hospitality/hotel-guest-satisfaction-study" target="_blank" rel="noopener noreferrer" className="underline hover:text-slate-700">J.D. Power Hotel Guest Satisfaction Study</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-blue-50 border border-blue-100 rounded-2xl p-6">
|
||||
<div className="text-3xl font-extrabold text-blue-600 mb-2">Effort = Loyalty</div>
|
||||
<p className="text-slate-700 text-sm leading-relaxed mb-3">
|
||||
Reducing customer effort — like eliminating manual password entry — is the single strongest predictor of customer loyalty. The lower the effort, the higher the repeat visit rate and positive word-of-mouth.
|
||||
</p>
|
||||
<p className="text-xs text-slate-500">
|
||||
Source: <a href="https://hbr.org/2010/07/stop-trying-to-delight-your-customers" target="_blank" rel="noopener noreferrer" className="underline hover:text-slate-700">Harvard Business Review — "Stop Trying to Delight Your Customers"</a> (Customer Effort Score research)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-slate-400 italic">
|
||||
By Timo Knuth, QR Master · Last updated: June 2025 · Based on independent academic and industry research
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* RELATED TOOLS */}
|
||||
<RelatedTools />
|
||||
|
||||
{/* FAQ SECTION - Featured Snippet Optimized */}
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8" style={{ backgroundColor: '#EBEBDF' }}>
|
||||
<div className="max-w-3xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-slate-900 text-center mb-4">
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
<p className="text-slate-600 text-center mb-10">
|
||||
Everything you need to know about WiFi QR codes.
|
||||
</p>
|
||||
|
||||
<div className="space-y-4">
|
||||
<FaqItem
|
||||
question="Is it safe to enter my WiFi password here?"
|
||||
answer="Yes, completely safe. This tool uses client-side processing, meaning your WiFi password never leaves your device. It's processed locally in your browser to generate the QR code—no data is sent to any server."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Do WiFi QR codes work on iPhone and Android?"
|
||||
answer="Yes. iOS 11 and later, as well as all modern Android devices, can scan WiFi QR codes using the built-in camera app. Simply point the camera at the QR code and tap the notification to connect."
|
||||
/>
|
||||
<FaqItem
|
||||
question="What happens if I change my WiFi password?"
|
||||
answer="If you change your WiFi password, the old QR code will stop working. You'll need to generate a new QR code with the updated credentials. For frequently changing passwords, consider using dynamic QR codes."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Can I customize the QR code design?"
|
||||
answer="Yes. You can change the foreground color of the QR code and add frame labels such as 'Scan Me', 'WiFi', or 'Connect' to make your QR code more recognizable and user-friendly."
|
||||
/>
|
||||
<FaqItem
|
||||
question="Does it work for hidden networks?"
|
||||
answer="Yes, just check the 'Hidden Network' box if your SSID is hidden. The QR code contains the standard WiFi string configuration."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// FAQ Item Component
|
||||
function FaqItem({ question, answer }: { question: string; answer: string }) {
|
||||
return (
|
||||
<details className="group bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden">
|
||||
<summary className="flex items-center justify-between p-5 cursor-pointer list-none text-slate-900 font-semibold hover:bg-slate-50 transition-colors">
|
||||
{question}
|
||||
<span className="transition group-open:rotate-180 text-slate-400">
|
||||
<svg fill="none" height="20" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" width="20">
|
||||
<path d="M6 9l6 6 6-6" />
|
||||
</svg>
|
||||
</span>
|
||||
</summary>
|
||||
<div className="text-slate-600 px-5 pb-5 pt-0 leading-relaxed text-sm">
|
||||
{answer}
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,77 +1,79 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
|
||||
import {
|
||||
buildUseCaseMetadata,
|
||||
UseCasePageTemplate,
|
||||
} from '@/components/marketing/UseCasePageTemplate';
|
||||
import { allUseCases, getUseCasePage } from '@/lib/growth-pages';
|
||||
|
||||
export function generateStaticParams() {
|
||||
return allUseCases.map((item) => ({
|
||||
slug: item.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
export function generateMetadata({ params }: { params: { slug: string } }) {
|
||||
const page = getUseCasePage(params.slug);
|
||||
|
||||
if (!page) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return buildUseCaseMetadata({
|
||||
title: page.title,
|
||||
description: page.metaDescription,
|
||||
canonicalPath: page.href,
|
||||
});
|
||||
}
|
||||
|
||||
export default function UseCaseDetailPage({
|
||||
params,
|
||||
}: {
|
||||
params: { slug: string };
|
||||
}) {
|
||||
const page = getUseCasePage(params.slug);
|
||||
|
||||
if (!page) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<UseCasePageTemplate
|
||||
title={page.title}
|
||||
description={page.metaDescription}
|
||||
eyebrow={page.eyebrow}
|
||||
intro={page.intro}
|
||||
pageType="use_case"
|
||||
cluster={page.cluster}
|
||||
useCase={page.slug}
|
||||
breadcrumbs={[
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Use Cases', url: '/use-cases' },
|
||||
{ name: page.title, url: page.href },
|
||||
]}
|
||||
answer={page.answer}
|
||||
whenToUse={page.whenToUse}
|
||||
comparisonItems={page.comparisonItems}
|
||||
howToSteps={page.howToSteps}
|
||||
primaryCta={{
|
||||
href: page.parentHref,
|
||||
label: page.ctaLabel,
|
||||
}}
|
||||
secondaryCta={{
|
||||
href: '/use-cases',
|
||||
label: 'Explore more use cases',
|
||||
}}
|
||||
workflowTitle={page.workflowTitle}
|
||||
workflowIntro={page.workflowIntro}
|
||||
workflowCards={page.workflowCards}
|
||||
checklistTitle={page.checklistTitle}
|
||||
checklist={page.checklist}
|
||||
supportLinks={page.supportLinks}
|
||||
faq={page.faq}
|
||||
heroImage={page.heroImage}
|
||||
heroImageAlt={page.heroImageAlt}
|
||||
/>
|
||||
);
|
||||
}
|
||||
import { notFound } from 'next/navigation';
|
||||
|
||||
import {
|
||||
buildUseCaseMetadata,
|
||||
UseCasePageTemplate,
|
||||
} from '@/components/marketing/UseCasePageTemplate';
|
||||
import { allUseCases, getUseCasePage } from '@/lib/growth-pages';
|
||||
|
||||
export function generateStaticParams() {
|
||||
return allUseCases.map((item) => ({
|
||||
slug: item.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
export function generateMetadata({ params }: { params: { slug: string } }) {
|
||||
const page = getUseCasePage(params.slug);
|
||||
|
||||
if (!page) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return buildUseCaseMetadata({
|
||||
title: page.title,
|
||||
description: page.metaDescription,
|
||||
canonicalPath: page.href,
|
||||
});
|
||||
}
|
||||
|
||||
export default function UseCaseDetailPage({
|
||||
params,
|
||||
}: {
|
||||
params: { slug: string };
|
||||
}) {
|
||||
const page = getUseCasePage(params.slug);
|
||||
|
||||
if (!page) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<UseCasePageTemplate
|
||||
title={page.title}
|
||||
description={page.metaDescription}
|
||||
eyebrow={page.eyebrow}
|
||||
intro={page.intro}
|
||||
pageType="use_case"
|
||||
cluster={page.cluster}
|
||||
useCase={page.slug}
|
||||
breadcrumbs={[
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Use Cases', url: '/use-cases' },
|
||||
{ name: page.title, url: page.href },
|
||||
]}
|
||||
answer={page.answer}
|
||||
whenToUse={page.whenToUse}
|
||||
comparisonItems={page.comparisonItems}
|
||||
howToSteps={page.howToSteps}
|
||||
primaryCta={{
|
||||
href: page.parentHref,
|
||||
label: page.ctaLabel,
|
||||
}}
|
||||
secondaryCta={{
|
||||
href: '/use-cases',
|
||||
label: 'Explore more use cases',
|
||||
}}
|
||||
workflowTitle={page.workflowTitle}
|
||||
workflowIntro={page.workflowIntro}
|
||||
workflowCards={page.workflowCards}
|
||||
checklistTitle={page.checklistTitle}
|
||||
checklist={page.checklist}
|
||||
supportLinks={page.supportLinks}
|
||||
faq={page.faq}
|
||||
heroImage={page.heroImage}
|
||||
heroImageAlt={page.heroImageAlt}
|
||||
authoritySignals={page.authoritySignals}
|
||||
directAnswer={page.directAnswer}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,158 +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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { ATTRIBUTION_COOKIE_NAME } from '@/lib/revops';
|
||||
|
||||
export async function POST() {
|
||||
const response = NextResponse.json({ success: true });
|
||||
|
||||
response.cookies.set('userId', '', {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 0,
|
||||
});
|
||||
response.cookies.set('newsletter-admin', '', {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 0,
|
||||
});
|
||||
response.cookies.set(ATTRIBUTION_COOKIE_NAME, '', {
|
||||
httpOnly: false,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 0,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
import { NextResponse } from 'next/server';
|
||||
import { ATTRIBUTION_COOKIE_NAME } from '@/lib/revops';
|
||||
|
||||
export async function POST() {
|
||||
const response = NextResponse.json({ success: true });
|
||||
|
||||
response.cookies.set('userId', '', {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 0,
|
||||
});
|
||||
response.cookies.set('newsletter-admin', '', {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 0,
|
||||
});
|
||||
response.cookies.set(ATTRIBUTION_COOKIE_NAME, '', {
|
||||
httpOnly: false,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
path: '/',
|
||||
maxAge: 0,
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -1,113 +1,113 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { sendActivationNudgeEmail, sendUpgradeNudgeEmail, sendThirtyDayNudgeEmail } from '@/lib/email';
|
||||
|
||||
// Protect with a shared secret — set CRON_SECRET in Vercel env vars
|
||||
function isAuthorized(request: NextRequest): boolean {
|
||||
const authHeader = request.headers.get('authorization');
|
||||
const cronSecret = process.env.CRON_SECRET;
|
||||
if (!cronSecret) return false;
|
||||
return authHeader === `Bearer ${cronSecret}`;
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
if (!isAuthorized(request)) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const threeDaysAgo = new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000);
|
||||
const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
||||
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
||||
|
||||
let activationSent = 0;
|
||||
let upgradeSent = 0;
|
||||
let thirtyDaySent = 0;
|
||||
|
||||
// Day-3: signed up > 3 days ago, never created a QR code, hasn't received this email yet
|
||||
const activationCandidates = await db.user.findMany({
|
||||
where: {
|
||||
createdAt: { lt: threeDaysAgo },
|
||||
activationNudgeSentAt: null,
|
||||
},
|
||||
include: {
|
||||
_count: { select: { qrCodes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
for (const user of activationCandidates) {
|
||||
if (user._count.qrCodes === 0 && user.email) {
|
||||
try {
|
||||
await sendActivationNudgeEmail(user.email, user.name ?? 'there');
|
||||
await db.user.update({
|
||||
where: { id: user.id },
|
||||
data: { activationNudgeSentAt: now },
|
||||
});
|
||||
activationSent++;
|
||||
} catch (err) {
|
||||
console.error(`Activation nudge failed for ${user.email}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Day-7: signed up > 7 days ago, has ≥1 QR code, still FREE, hasn't received this email yet
|
||||
const upgradeCandidates = await db.user.findMany({
|
||||
where: {
|
||||
createdAt: { lt: sevenDaysAgo },
|
||||
upgradeNudgeSentAt: null,
|
||||
plan: 'FREE',
|
||||
},
|
||||
include: {
|
||||
_count: { select: { qrCodes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
for (const user of upgradeCandidates) {
|
||||
if (user._count.qrCodes > 0 && user.email) {
|
||||
try {
|
||||
await sendUpgradeNudgeEmail(user.email, user.name ?? 'there', user._count.qrCodes);
|
||||
await db.user.update({
|
||||
where: { id: user.id },
|
||||
data: { upgradeNudgeSentAt: now },
|
||||
});
|
||||
upgradeSent++;
|
||||
} catch (err) {
|
||||
console.error(`Upgrade nudge failed for ${user.email}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Day-30: signed up > 30 days ago, has ≥1 QR code, still FREE, hasn't received this email yet
|
||||
const thirtyDayCandidates = await db.user.findMany({
|
||||
where: {
|
||||
createdAt: { lt: thirtyDaysAgo },
|
||||
thirtyDayNudgeSentAt: null,
|
||||
plan: 'FREE',
|
||||
},
|
||||
include: {
|
||||
_count: { select: { qrCodes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
for (const user of thirtyDayCandidates) {
|
||||
if (user._count.qrCodes > 0 && user.email) {
|
||||
try {
|
||||
await sendThirtyDayNudgeEmail(user.email, user.name ?? 'there', user._count.qrCodes);
|
||||
await db.user.update({
|
||||
where: { id: user.id },
|
||||
data: { thirtyDayNudgeSentAt: now },
|
||||
});
|
||||
thirtyDaySent++;
|
||||
} catch (err) {
|
||||
console.error(`30-day nudge failed for ${user.email}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
ok: true,
|
||||
activationNudgesSent: activationSent,
|
||||
upgradeNudgesSent: upgradeSent,
|
||||
thirtyDayNudgesSent: thirtyDaySent,
|
||||
});
|
||||
}
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { sendActivationNudgeEmail, sendUpgradeNudgeEmail, sendThirtyDayNudgeEmail } from '@/lib/email';
|
||||
|
||||
// Protect with a shared secret — set CRON_SECRET in Vercel env vars
|
||||
function isAuthorized(request: NextRequest): boolean {
|
||||
const authHeader = request.headers.get('authorization');
|
||||
const cronSecret = process.env.CRON_SECRET;
|
||||
if (!cronSecret) return false;
|
||||
return authHeader === `Bearer ${cronSecret}`;
|
||||
}
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
if (!isAuthorized(request)) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const now = new Date();
|
||||
const threeDaysAgo = new Date(now.getTime() - 3 * 24 * 60 * 60 * 1000);
|
||||
const sevenDaysAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
|
||||
const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
|
||||
|
||||
let activationSent = 0;
|
||||
let upgradeSent = 0;
|
||||
let thirtyDaySent = 0;
|
||||
|
||||
// Day-3: signed up > 3 days ago, never created a QR code, hasn't received this email yet
|
||||
const activationCandidates = await db.user.findMany({
|
||||
where: {
|
||||
createdAt: { lt: threeDaysAgo },
|
||||
activationNudgeSentAt: null,
|
||||
},
|
||||
include: {
|
||||
_count: { select: { qrCodes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
for (const user of activationCandidates) {
|
||||
if (user._count.qrCodes === 0 && user.email) {
|
||||
try {
|
||||
await sendActivationNudgeEmail(user.email, user.name ?? 'there');
|
||||
await db.user.update({
|
||||
where: { id: user.id },
|
||||
data: { activationNudgeSentAt: now },
|
||||
});
|
||||
activationSent++;
|
||||
} catch (err) {
|
||||
console.error(`Activation nudge failed for ${user.email}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Day-7: signed up > 7 days ago, has ≥1 QR code, still FREE, hasn't received this email yet
|
||||
const upgradeCandidates = await db.user.findMany({
|
||||
where: {
|
||||
createdAt: { lt: sevenDaysAgo },
|
||||
upgradeNudgeSentAt: null,
|
||||
plan: 'FREE',
|
||||
},
|
||||
include: {
|
||||
_count: { select: { qrCodes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
for (const user of upgradeCandidates) {
|
||||
if (user._count.qrCodes > 0 && user.email) {
|
||||
try {
|
||||
await sendUpgradeNudgeEmail(user.email, user.name ?? 'there', user._count.qrCodes);
|
||||
await db.user.update({
|
||||
where: { id: user.id },
|
||||
data: { upgradeNudgeSentAt: now },
|
||||
});
|
||||
upgradeSent++;
|
||||
} catch (err) {
|
||||
console.error(`Upgrade nudge failed for ${user.email}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Day-30: signed up > 30 days ago, has ≥1 QR code, still FREE, hasn't received this email yet
|
||||
const thirtyDayCandidates = await db.user.findMany({
|
||||
where: {
|
||||
createdAt: { lt: thirtyDaysAgo },
|
||||
thirtyDayNudgeSentAt: null,
|
||||
plan: 'FREE',
|
||||
},
|
||||
include: {
|
||||
_count: { select: { qrCodes: true } },
|
||||
},
|
||||
});
|
||||
|
||||
for (const user of thirtyDayCandidates) {
|
||||
if (user._count.qrCodes > 0 && user.email) {
|
||||
try {
|
||||
await sendThirtyDayNudgeEmail(user.email, user.name ?? 'there', user._count.qrCodes);
|
||||
await db.user.update({
|
||||
where: { id: user.id },
|
||||
data: { thirtyDayNudgeSentAt: now },
|
||||
});
|
||||
thirtyDaySent++;
|
||||
} catch (err) {
|
||||
console.error(`30-day nudge failed for ${user.email}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
ok: true,
|
||||
activationNudgesSent: activationSent,
|
||||
upgradeNudgesSent: upgradeSent,
|
||||
thirtyDayNudgesSent: thirtyDaySent,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,119 +1,119 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { db } from '@/lib/db';
|
||||
import { csrfProtection } from '@/lib/csrf';
|
||||
import { getClientIdentifier, rateLimit, RateLimits } from '@/lib/rateLimit';
|
||||
import { onboardingUpdateSchema, validateRequest } from '@/lib/validationSchemas';
|
||||
import { getOnboardingState, triggerLifecycleScoring } from '@/lib/revops-server';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const userId = cookies().get('userId')?.value;
|
||||
|
||||
if (!userId) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const state = await getOnboardingState(userId);
|
||||
|
||||
if (!state) {
|
||||
return NextResponse.json({ error: 'User not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
return NextResponse.json(state);
|
||||
} catch (error) {
|
||||
console.error('Error fetching onboarding state:', error);
|
||||
return NextResponse.json({ error: 'Failed to fetch onboarding state' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PATCH(request: NextRequest) {
|
||||
try {
|
||||
const csrfCheck = csrfProtection(request);
|
||||
if (!csrfCheck.valid) {
|
||||
return NextResponse.json({ error: csrfCheck.error }, { status: 403 });
|
||||
}
|
||||
|
||||
const userId = cookies().get('userId')?.value;
|
||||
const clientId = userId || getClientIdentifier(request);
|
||||
const rateLimitResult = rateLimit(clientId, RateLimits.PROFILE_UPDATE);
|
||||
|
||||
if (!rateLimitResult.success) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Too many requests. Please try again later.',
|
||||
retryAfter: Math.ceil((rateLimitResult.reset - Date.now()) / 1000),
|
||||
},
|
||||
{ status: 429 }
|
||||
);
|
||||
}
|
||||
|
||||
if (!userId) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const validation = await validateRequest(onboardingUpdateSchema, body);
|
||||
|
||||
if (!validation.success) {
|
||||
return NextResponse.json(validation.error, { status: 400 });
|
||||
}
|
||||
|
||||
const data = validation.data;
|
||||
const now = new Date();
|
||||
const existingUser = await db.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
onboardingStartedAt: true,
|
||||
sourceConfirmedAt: true,
|
||||
useCaseSelectedAt: true,
|
||||
goalSelectedAt: true,
|
||||
profileCompletedAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!existingUser) {
|
||||
return NextResponse.json({ error: 'User not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
await db.user.update({
|
||||
where: { id: userId },
|
||||
data: {
|
||||
onboardingStartedAt: existingUser.onboardingStartedAt ?? now,
|
||||
signupSourceSelfReported: data.signupSourceSelfReported,
|
||||
primaryUseCase: data.primaryUseCase,
|
||||
primaryGoal: data.primaryGoal,
|
||||
jobRole: data.jobRole,
|
||||
companyName: data.companyName,
|
||||
companyWebsite: data.companyWebsite,
|
||||
teamSizeBucket: data.teamSizeBucket,
|
||||
sourceConfirmedAt:
|
||||
data.signupSourceSelfReported && !existingUser.sourceConfirmedAt
|
||||
? now
|
||||
: undefined,
|
||||
useCaseSelectedAt:
|
||||
data.primaryUseCase && !existingUser.useCaseSelectedAt
|
||||
? now
|
||||
: undefined,
|
||||
goalSelectedAt:
|
||||
data.primaryGoal && !existingUser.goalSelectedAt
|
||||
? now
|
||||
: undefined,
|
||||
profileCompletedAt:
|
||||
data.markProfileComplete && !existingUser.profileCompletedAt
|
||||
? now
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
triggerLifecycleScoring(userId, 'onboarding_update');
|
||||
const state = await getOnboardingState(userId);
|
||||
|
||||
return NextResponse.json({ success: true, state });
|
||||
} catch (error) {
|
||||
console.error('Error updating onboarding state:', error);
|
||||
return NextResponse.json({ error: 'Failed to update onboarding state' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { db } from '@/lib/db';
|
||||
import { csrfProtection } from '@/lib/csrf';
|
||||
import { getClientIdentifier, rateLimit, RateLimits } from '@/lib/rateLimit';
|
||||
import { onboardingUpdateSchema, validateRequest } from '@/lib/validationSchemas';
|
||||
import { getOnboardingState, triggerLifecycleScoring } from '@/lib/revops-server';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const userId = cookies().get('userId')?.value;
|
||||
|
||||
if (!userId) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const state = await getOnboardingState(userId);
|
||||
|
||||
if (!state) {
|
||||
return NextResponse.json({ error: 'User not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
return NextResponse.json(state);
|
||||
} catch (error) {
|
||||
console.error('Error fetching onboarding state:', error);
|
||||
return NextResponse.json({ error: 'Failed to fetch onboarding state' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PATCH(request: NextRequest) {
|
||||
try {
|
||||
const csrfCheck = csrfProtection(request);
|
||||
if (!csrfCheck.valid) {
|
||||
return NextResponse.json({ error: csrfCheck.error }, { status: 403 });
|
||||
}
|
||||
|
||||
const userId = cookies().get('userId')?.value;
|
||||
const clientId = userId || getClientIdentifier(request);
|
||||
const rateLimitResult = rateLimit(clientId, RateLimits.PROFILE_UPDATE);
|
||||
|
||||
if (!rateLimitResult.success) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: 'Too many requests. Please try again later.',
|
||||
retryAfter: Math.ceil((rateLimitResult.reset - Date.now()) / 1000),
|
||||
},
|
||||
{ status: 429 }
|
||||
);
|
||||
}
|
||||
|
||||
if (!userId) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
const body = await request.json();
|
||||
const validation = await validateRequest(onboardingUpdateSchema, body);
|
||||
|
||||
if (!validation.success) {
|
||||
return NextResponse.json(validation.error, { status: 400 });
|
||||
}
|
||||
|
||||
const data = validation.data;
|
||||
const now = new Date();
|
||||
const existingUser = await db.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
onboardingStartedAt: true,
|
||||
sourceConfirmedAt: true,
|
||||
useCaseSelectedAt: true,
|
||||
goalSelectedAt: true,
|
||||
profileCompletedAt: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!existingUser) {
|
||||
return NextResponse.json({ error: 'User not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
await db.user.update({
|
||||
where: { id: userId },
|
||||
data: {
|
||||
onboardingStartedAt: existingUser.onboardingStartedAt ?? now,
|
||||
signupSourceSelfReported: data.signupSourceSelfReported,
|
||||
primaryUseCase: data.primaryUseCase,
|
||||
primaryGoal: data.primaryGoal,
|
||||
jobRole: data.jobRole,
|
||||
companyName: data.companyName,
|
||||
companyWebsite: data.companyWebsite,
|
||||
teamSizeBucket: data.teamSizeBucket,
|
||||
sourceConfirmedAt:
|
||||
data.signupSourceSelfReported && !existingUser.sourceConfirmedAt
|
||||
? now
|
||||
: undefined,
|
||||
useCaseSelectedAt:
|
||||
data.primaryUseCase && !existingUser.useCaseSelectedAt
|
||||
? now
|
||||
: undefined,
|
||||
goalSelectedAt:
|
||||
data.primaryGoal && !existingUser.goalSelectedAt
|
||||
? now
|
||||
: undefined,
|
||||
profileCompletedAt:
|
||||
data.markProfileComplete && !existingUser.profileCompletedAt
|
||||
? now
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
|
||||
triggerLifecycleScoring(userId, 'onboarding_update');
|
||||
const state = await getOnboardingState(userId);
|
||||
|
||||
return NextResponse.json({ success: true, state });
|
||||
} catch (error) {
|
||||
console.error('Error updating onboarding state:', error);
|
||||
return NextResponse.json({ error: 'Failed to update onboarding state' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,64 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { db } from '@/lib/db';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const userId = cookies().get('userId')?.value;
|
||||
if (!userId) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
// Get user with plan info
|
||||
const user = await db.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
plan: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'User not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Count dynamic QR codes
|
||||
const dynamicQRCount = await db.qRCode.count({
|
||||
where: {
|
||||
userId,
|
||||
type: 'DYNAMIC',
|
||||
},
|
||||
});
|
||||
|
||||
// Count static QR codes
|
||||
const staticQRCount = await db.qRCode.count({
|
||||
where: {
|
||||
userId,
|
||||
type: 'STATIC',
|
||||
},
|
||||
});
|
||||
|
||||
// Determine limits based on plan
|
||||
let dynamicLimit = 3; // FREE plan default
|
||||
if (user.plan === 'PRO') {
|
||||
dynamicLimit = 50;
|
||||
} else if (user.plan === 'BUSINESS') {
|
||||
dynamicLimit = 500;
|
||||
} else if ((user.plan as string) === 'ENTERPRISE') {
|
||||
dynamicLimit = 99999;
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
dynamicUsed: dynamicQRCount,
|
||||
dynamicLimit,
|
||||
staticUsed: staticQRCount,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching user stats:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Internal server error' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { cookies } from 'next/headers';
|
||||
import { db } from '@/lib/db';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const userId = cookies().get('userId')?.value;
|
||||
if (!userId) {
|
||||
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
|
||||
}
|
||||
|
||||
// Get user with plan info
|
||||
const user = await db.user.findUnique({
|
||||
where: { id: userId },
|
||||
select: {
|
||||
plan: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return NextResponse.json({ error: 'User not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
// Count dynamic QR codes
|
||||
const dynamicQRCount = await db.qRCode.count({
|
||||
where: {
|
||||
userId,
|
||||
type: 'DYNAMIC',
|
||||
},
|
||||
});
|
||||
|
||||
// Count static QR codes
|
||||
const staticQRCount = await db.qRCode.count({
|
||||
where: {
|
||||
userId,
|
||||
type: 'STATIC',
|
||||
},
|
||||
});
|
||||
|
||||
// Determine limits based on plan
|
||||
let dynamicLimit = 3; // FREE plan default
|
||||
if (user.plan === 'PRO') {
|
||||
dynamicLimit = 50;
|
||||
} else if (user.plan === 'BUSINESS') {
|
||||
dynamicLimit = 500;
|
||||
} else if ((user.plan as string) === 'ENTERPRISE') {
|
||||
dynamicLimit = 99999;
|
||||
}
|
||||
|
||||
return NextResponse.json({
|
||||
dynamicUsed: dynamicQRCount,
|
||||
dynamicLimit,
|
||||
staticUsed: staticQRCount,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error fetching user stats:', error);
|
||||
return NextResponse.json(
|
||||
{ error: 'Internal server error' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,15 @@
|
||||
import type { Metadata } from 'next';
|
||||
import OnboardingClient from './OnboardingClient';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Onboarding | QR Master',
|
||||
description: 'Set up your QR Master workspace and create your first QR code.',
|
||||
robots: {
|
||||
index: false,
|
||||
follow: false,
|
||||
},
|
||||
};
|
||||
|
||||
export default function OnboardingPage() {
|
||||
return <OnboardingClient />;
|
||||
}
|
||||
import type { Metadata } from 'next';
|
||||
import OnboardingClient from './OnboardingClient';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Onboarding | QR Master',
|
||||
description: 'Set up your QR Master workspace and create your first QR code.',
|
||||
robots: {
|
||||
index: false,
|
||||
follow: false,
|
||||
},
|
||||
};
|
||||
|
||||
export default function OnboardingPage() {
|
||||
return <OnboardingClient />;
|
||||
}
|
||||
|
||||
@@ -1,118 +1,118 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Free QR Code Tools | URL, vCard, WiFi & More | QR Master',
|
||||
description:
|
||||
'Access free QR code tools for URLs, WiFi, vCards, barcodes, and more. Use QR Master for static codes, dynamic QR codes, and QR code tracking.',
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free QR Code Tools Collection',
|
||||
description:
|
||||
'All your QR code needs in one place. Free forever static codes.',
|
||||
url: 'https://www.qrmaster.net/tools',
|
||||
siteName: 'QR Master',
|
||||
type: 'website',
|
||||
},
|
||||
};
|
||||
|
||||
export default function ToolsHubPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-50 pt-20">
|
||||
<section className="bg-white py-20 px-4 border-b border-slate-200">
|
||||
<div className="container mx-auto text-center max-w-4xl">
|
||||
<span className="inline-block px-4 py-1.5 rounded-full bg-indigo-50 text-indigo-700 font-semibold text-sm mb-6">
|
||||
100% Free Forever
|
||||
</span>
|
||||
<h1 className="text-4xl md:text-6xl font-extrabold text-slate-900 mb-6 tracking-tight">
|
||||
Free QR Code Tools
|
||||
</h1>
|
||||
<p className="text-xl text-slate-600 mb-8 leading-relaxed max-w-2xl mx-auto">
|
||||
Generate static QR codes for any purpose. No credit card, no
|
||||
expiration, no hidden fees.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="py-12">
|
||||
<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">
|
||||
Why are these tools free?
|
||||
</h2>
|
||||
<p className="text-slate-600 mb-8">
|
||||
We believe basic QR codes should be accessible to everyone. Our
|
||||
static QR codes encode your data directly into the image, meaning we
|
||||
don't need to host tracking servers for them. That's why they are
|
||||
free forever. If you need tracking and editability, use our{' '}
|
||||
<a
|
||||
href="/dynamic-qr-code-generator"
|
||||
className="font-semibold text-indigo-700 underline"
|
||||
>
|
||||
dynamic QR code generator
|
||||
</a>{' '}
|
||||
or learn how{' '}
|
||||
<a
|
||||
href="/qr-code-tracking"
|
||||
className="font-semibold text-indigo-700 underline"
|
||||
>
|
||||
QR code tracking
|
||||
</a>{' '}
|
||||
works.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'Free QR Code Tools | URL, vCard, WiFi & More | QR Master',
|
||||
description:
|
||||
'Access free QR code tools for URLs, WiFi, vCards, barcodes, and more. Use QR Master for static codes, dynamic QR codes, and QR code tracking.',
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools',
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Free QR Code Tools Collection',
|
||||
description:
|
||||
'All your QR code needs in one place. Free forever static codes.',
|
||||
url: 'https://www.qrmaster.net/tools',
|
||||
siteName: 'QR Master',
|
||||
type: 'website',
|
||||
},
|
||||
};
|
||||
|
||||
export default function ToolsHubPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-slate-50 pt-20">
|
||||
<section className="bg-white py-20 px-4 border-b border-slate-200">
|
||||
<div className="container mx-auto text-center max-w-4xl">
|
||||
<span className="inline-block px-4 py-1.5 rounded-full bg-indigo-50 text-indigo-700 font-semibold text-sm mb-6">
|
||||
100% Free Forever
|
||||
</span>
|
||||
<h1 className="text-4xl md:text-6xl font-extrabold text-slate-900 mb-6 tracking-tight">
|
||||
Free QR Code Tools
|
||||
</h1>
|
||||
<p className="text-xl text-slate-600 mb-8 leading-relaxed max-w-2xl mx-auto">
|
||||
Generate static QR codes for any purpose. No credit card, no
|
||||
expiration, no hidden fees.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="py-12">
|
||||
<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">
|
||||
Why are these tools free?
|
||||
</h2>
|
||||
<p className="text-slate-600 mb-8">
|
||||
We believe basic QR codes should be accessible to everyone. Our
|
||||
static QR codes encode your data directly into the image, meaning we
|
||||
don't need to host tracking servers for them. That's why they are
|
||||
free forever. If you need tracking and editability, use our{' '}
|
||||
<a
|
||||
href="/dynamic-qr-code-generator"
|
||||
className="font-semibold text-indigo-700 underline"
|
||||
>
|
||||
dynamic QR code generator
|
||||
</a>{' '}
|
||||
or learn how{' '}
|
||||
<a
|
||||
href="/qr-code-tracking"
|
||||
className="font-semibold text-indigo-700 underline"
|
||||
>
|
||||
QR code tracking
|
||||
</a>{' '}
|
||||
works.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,452 +1,452 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { organizationSchema, websiteSchema } from '@/lib/schema';
|
||||
import {
|
||||
generateFaqSchema,
|
||||
generateSoftwareAppSchema,
|
||||
} from '@/lib/schema-utils';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
import de from '@/i18n/de.json';
|
||||
import { FAQ } from '@/components/marketing/FAQ';
|
||||
import { ScrollToTop } from '@/components/ui/ScrollToTop';
|
||||
import {
|
||||
Barcode as BarcodeIcon,
|
||||
Check,
|
||||
Shield,
|
||||
Zap,
|
||||
Printer,
|
||||
Download,
|
||||
} from 'lucide-react';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Barcode Generator Kostenlos – EAN, UPC, Code 128 Online',
|
||||
},
|
||||
description:
|
||||
'Erstellen Sie Barcodes kostenlos online: EAN-13, UPC-A und Code 128. Sofort druckfertig. Für Einzelhandel, Lager und Logistik. Keine Anmeldung erforderlich.',
|
||||
keywords: [
|
||||
'barcode generator',
|
||||
'barcode generator kostenlos',
|
||||
'ean-13 generator',
|
||||
'upc-a generator',
|
||||
'code 128 generator',
|
||||
'barcode erstellen',
|
||||
'barcode online erstellen',
|
||||
'strichcode generator',
|
||||
'barcode für amazon erstellen',
|
||||
'ean barcode generator',
|
||||
'produktbarcode erstellen',
|
||||
'lagerverwaltung barcode',
|
||||
'barcode drucken',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
en: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
de: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Barcode Generator – Kostenlos EAN, UPC & Code 128 erstellen',
|
||||
description:
|
||||
'Barcode Generator: Erstellen Sie professionelle Barcodes für Einzelhandel, Lager und Logistik. Kostenlos, ohne Anmeldung. Sofort druckfertig.',
|
||||
url: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
locale: 'de_DE',
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url: 'https://www.qrmaster.net/barcode-generator-preview.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Barcode Generator – Kostenlos Online erstellen',
|
||||
description:
|
||||
'EAN-13, UPC-A und Code 128 Barcodes kostenlos erstellen. Sofort druckfertig.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
const faqQuestions = {
|
||||
'Was ist ein Barcode Generator?': {
|
||||
question: 'Was ist ein Barcode Generator?',
|
||||
answer:
|
||||
'Ein Barcode Generator ist ein Online-Tool, das Zahlen oder Texte in scannbare Barcode-Bilder umwandelt. Diese können für Produkte, Etiketten und Inventarsysteme verwendet werden.',
|
||||
},
|
||||
'Ist der Barcode Generator kostenlos?': {
|
||||
question: 'Ist der Barcode Generator kostenlos?',
|
||||
answer:
|
||||
'Ja, unser Barcode Generator ist vollständig kostenlos nutzbar. Sie können Barcodes ohne Anmeldung generieren, herunterladen und drucken.',
|
||||
},
|
||||
'Welches Barcode-Format brauche ich?': {
|
||||
question: 'Welches Barcode-Format brauche ich?',
|
||||
answer:
|
||||
'EAN-13 ist der Standard für Einzelhandel in Europa und weltweit. UPC-A wird hauptsächlich in den USA und Kanada verwendet. Code 128 eignet sich am besten für Logistik und interne Verfolgung, da er Buchstaben und Zahlen unterstützt.',
|
||||
},
|
||||
'Kann ich Barcodes als Vektorgrafik (SVG) herunterladen?': {
|
||||
question: 'Kann ich Barcodes als Vektorgrafik (SVG) herunterladen?',
|
||||
answer:
|
||||
'Ja! SVG-Dateien sind vektorbasiert und können ohne Qualitätsverlust auf jede Größe skaliert werden. Perfekt für professionelle Produktverpackungen und Etiketten.',
|
||||
},
|
||||
'Wie erstelle ich einen Barcode online?': {
|
||||
question: 'Wie erstelle ich einen Barcode online?',
|
||||
answer:
|
||||
'Geben Sie Ihre Produktnummer oder Ihren Text ein, wählen Sie das gewünschte Barcode-Format (z.B. EAN-13 oder Code 128) und der Barcode wird sofort erstellt. Dann können Sie ihn als PNG oder SVG herunterladen.',
|
||||
},
|
||||
'Sind die erstellten Barcodes scannbar?': {
|
||||
question: 'Sind die erstellten Barcodes scannbar?',
|
||||
answer:
|
||||
'Ja, wir generieren standardkonforme Barcodes, die von jedem handelsüblichen Barcode-Scanner gelesen werden können, einschließlich Smartphone-Kamera-Apps.',
|
||||
},
|
||||
'Kann ich diese Barcodes für Amazon verwenden?': {
|
||||
question: 'Kann ich diese Barcodes für Amazon verwenden?',
|
||||
answer:
|
||||
'Sie können hier das Barcode-Bild erstellen, wenn Sie bereits eine gültige EAN/UPC-Nummer haben. Offizielle GS1-Registrierungsnummern erhalten Sie jedoch nur direkt bei GS1, um Produkte auf Amazon oder in großen Einzelhandelssystemen zu listen.',
|
||||
},
|
||||
'Was ist der Unterschied zwischen Barcode und QR-Code?': {
|
||||
question: 'Was ist der Unterschied zwischen Barcode und QR-Code?',
|
||||
answer:
|
||||
'Ein Barcode speichert Daten horizontal (1D) und wird hauptsächlich für Produktkennungen verwendet. Ein QR-Code speichert Daten in 2D (Matrix) und kann viel mehr Informationen enthalten, wie URLs, Kontaktdaten oder WLAN-Zugangsdaten.',
|
||||
},
|
||||
'Kann ich mehrere Barcodes gleichzeitig erstellen?': {
|
||||
question: 'Kann ich mehrere Barcodes gleichzeitig erstellen?',
|
||||
answer:
|
||||
'Ja, mit einem PRO-Account können Sie mehrere Barcodes gleichzeitig generieren. Dies ist ideal für große Produktmengen oder Lagerverwaltung.',
|
||||
},
|
||||
'Was ist eine Prüfziffer bei Barcodes?': {
|
||||
question: 'Was ist eine Prüfziffer bei Barcodes?',
|
||||
answer:
|
||||
'Die Prüfziffer ist die letzte Ziffer in einem Barcode, die mathematisch aus den anderen Ziffern berechnet wird. Sie stellt sicher, dass der Barcode korrekt gescannt wird, selbst wenn er leicht beschädigt oder verkratzt ist.',
|
||||
},
|
||||
};
|
||||
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
generateSoftwareAppSchema(
|
||||
'Barcode Generator',
|
||||
'Erstellen Sie druckfertige Barcodes für EAN, UPC, Code 128 und weitere Formate. Kostenlos und ohne Anmeldung.',
|
||||
'/barcode-generator-preview.png',
|
||||
'UtilitiesApplication'
|
||||
),
|
||||
generateFaqSchema(faqQuestions),
|
||||
],
|
||||
};
|
||||
|
||||
export default function BarcodeGeneratorDEPage() {
|
||||
const t = de;
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
|
||||
{/* SEO Content für Suchmaschinen */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
<p>
|
||||
QR Masters kostenloser Barcode Generator ermöglicht es Ihnen,
|
||||
professionelle Barcodes für Produkte, Etiketten und Inventarsysteme zu
|
||||
erstellen. Unterstützt EAN-13 für europäischen Einzelhandel, UPC-A für
|
||||
US-Markt und Code 128 für Logistik und interne Verwendung. Alle
|
||||
Barcodes sind standardkonform und sofort druckfertig.
|
||||
</p>
|
||||
<p>
|
||||
Unser Barcode Generator funktioniert vollständig im Browser. Keine
|
||||
Software-Installation erforderlich. Exportieren Sie Ihre Barcodes als
|
||||
PNG für den sofortigen Druck oder als SVG für professionelle
|
||||
Verpackungsdesigns. Perfekt für kleine Unternehmen, Online-Händler und
|
||||
Lagerverwaltung.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="relative bg-gradient-to-b from-slate-900 to-slate-800 text-white py-16 md:py-24">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" width="100%" height="100%">
|
||||
<defs>
|
||||
<pattern
|
||||
id="barcode_pattern_de"
|
||||
width="60"
|
||||
height="60"
|
||||
patternUnits="userSpaceOnUse"
|
||||
>
|
||||
<path
|
||||
d="M5 0 V 60 M15 0 V 60 M20 0 V 60 M35 0 V 60 M40 0 V 60 M55 0 V 60"
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
strokeOpacity="0.5"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#barcode_pattern_de)" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl relative z-10">
|
||||
<div className="max-w-3xl mx-auto text-center">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-blue-400"></span>
|
||||
</span>
|
||||
Kostenloses Tool – Professionell & Schnell
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold tracking-tight mb-6">
|
||||
Kostenloser{' '}
|
||||
<span className="text-blue-400">Barcode Generator</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-slate-300 mb-8 leading-relaxed">
|
||||
Erstellen Sie professionelle Barcodes in Sekunden. Für{' '}
|
||||
<strong className="text-white">
|
||||
Einzelhandel, Lager und Logistik
|
||||
</strong>
|
||||
. Unterstützt EAN-13, UPC-A und Code 128. Keine Anmeldung
|
||||
erforderlich.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center gap-4 text-sm font-medium">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
Einzelhandel-fähig
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
SVG-Export
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
Ohne Anmeldung
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Generator Section */}
|
||||
<section className="py-12 px-4 bg-slate-100">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<div className="text-center mb-6">
|
||||
<h2 className="text-2xl font-bold mb-2">Barcode jetzt erstellen</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Geben Sie Ihre Daten ein und laden Sie den Barcode herunter
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white rounded-3xl shadow-xl overflow-hidden border border-slate-200">
|
||||
<div className="bg-slate-900 px-6 py-3 flex items-center gap-2">
|
||||
<div className="flex gap-1.5">
|
||||
<div className="w-3 h-3 rounded-full bg-red-500"></div>
|
||||
<div className="w-3 h-3 rounded-full bg-yellow-500"></div>
|
||||
<div className="w-3 h-3 rounded-full bg-green-500"></div>
|
||||
</div>
|
||||
<span className="text-white/60 text-sm ml-2">
|
||||
qrmaster.net/tools/barcode-generator
|
||||
</span>
|
||||
</div>
|
||||
<iframe
|
||||
src="https://www.qrmaster.net/tools/barcode-generator"
|
||||
className="w-full h-[650px] border-0"
|
||||
title="Barcode Generator"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-center mt-6">
|
||||
<a
|
||||
href="https://www.qrmaster.net/tools/barcode-generator"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-slate-900 transition-colors"
|
||||
>
|
||||
<span>Vollbild öffnen</span>
|
||||
<svg
|
||||
className="w-4 h-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Barcode Types Info */}
|
||||
<section className="py-16 px-4 bg-white">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-12">
|
||||
Barcode-Formate im Überblick
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">EAN-13</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Internationaler Standard für Einzelhandel. 13 Ziffern, weltweit
|
||||
anerkannt.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> Produkte in Europa & global
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-green-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-green-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">UPC-A</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Amerikanischer Standard. 12 Ziffern, hauptsächlich in
|
||||
Nordamerika.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> USA & Kanada Einzelhandel
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-purple-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">Code 128</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Flexible Lösung für Logistik. Alphanumerisch, hohe Datendichte.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> Versand, Lager, Inventar
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* How It Works */}
|
||||
<section className="py-16 px-4 bg-slate-50">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-12">
|
||||
So funktioniert unser Barcode Generator
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-5 gap-8">
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
1
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Daten eingeben</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Geben Sie Ihre Produktnummer oder Text ein.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
2
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Format wählen</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
EAN-13, UPC-A oder Code 128 auswählen.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
3
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Vorschau</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Barcode wird in Echtzeit aktualisiert.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
4
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Herunterladen</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Als PNG oder SVG speichern.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
5
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Drucken</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Sofort auf Etiketten drucken.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Use Cases */}
|
||||
<section className="py-16 px-4 bg-white">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-4">
|
||||
Für wen ist unser Barcode Generator geeignet?
|
||||
</h2>
|
||||
<p className="text-center text-muted-foreground mb-12 max-w-2xl mx-auto">
|
||||
Ob Kleinunternehmer, Online-Händler oder Lagerverwaltung – unser
|
||||
Tool unterstützt Sie bei allen Barcode-Bedarfen.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Printer className="w-8 h-8 text-blue-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Einzelhandel</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
EAN-13 Barcodes für Produktetiketten im stationären Handel.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Shield className="w-8 h-8 text-green-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">E-Commerce</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
UPC/EAN für Amazon, eBay und andere Marktplätze.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Zap className="w-8 h-8 text-orange-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Lager & Logistik</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Code 128 für interne Bestandsverfolgung und Versand.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Download className="w-8 h-8 text-purple-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Druckerei</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
SVG-Export für professionelle Verpackungsdesigns.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ Section */}
|
||||
<FAQ
|
||||
t={{
|
||||
faq: { title: 'Häufig gestellte Fragen', questions: faqQuestions },
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
{/* Scroll to Top */}
|
||||
<ScrollToTop />
|
||||
</>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { organizationSchema, websiteSchema } from '@/lib/schema';
|
||||
import {
|
||||
generateFaqSchema,
|
||||
generateSoftwareAppSchema,
|
||||
} from '@/lib/schema-utils';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
import de from '@/i18n/de.json';
|
||||
import { FAQ } from '@/components/marketing/FAQ';
|
||||
import { ScrollToTop } from '@/components/ui/ScrollToTop';
|
||||
import {
|
||||
Barcode as BarcodeIcon,
|
||||
Check,
|
||||
Shield,
|
||||
Zap,
|
||||
Printer,
|
||||
Download,
|
||||
} from 'lucide-react';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Barcode Generator Kostenlos – EAN, UPC, Code 128 Online',
|
||||
},
|
||||
description:
|
||||
'Erstellen Sie Barcodes kostenlos online: EAN-13, UPC-A und Code 128. Sofort druckfertig. Für Einzelhandel, Lager und Logistik. Keine Anmeldung erforderlich.',
|
||||
keywords: [
|
||||
'barcode generator',
|
||||
'barcode generator kostenlos',
|
||||
'ean-13 generator',
|
||||
'upc-a generator',
|
||||
'code 128 generator',
|
||||
'barcode erstellen',
|
||||
'barcode online erstellen',
|
||||
'strichcode generator',
|
||||
'barcode für amazon erstellen',
|
||||
'ean barcode generator',
|
||||
'produktbarcode erstellen',
|
||||
'lagerverwaltung barcode',
|
||||
'barcode drucken',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
en: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
de: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Barcode Generator – Kostenlos EAN, UPC & Code 128 erstellen',
|
||||
description:
|
||||
'Barcode Generator: Erstellen Sie professionelle Barcodes für Einzelhandel, Lager und Logistik. Kostenlos, ohne Anmeldung. Sofort druckfertig.',
|
||||
url: 'https://www.qrmaster.net/tools/barcode-generator',
|
||||
locale: 'de_DE',
|
||||
type: 'website',
|
||||
images: [
|
||||
{
|
||||
url: 'https://www.qrmaster.net/barcode-generator-preview.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: 'summary_large_image',
|
||||
title: 'Barcode Generator – Kostenlos Online erstellen',
|
||||
description:
|
||||
'EAN-13, UPC-A und Code 128 Barcodes kostenlos erstellen. Sofort druckfertig.',
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
},
|
||||
};
|
||||
|
||||
const faqQuestions = {
|
||||
'Was ist ein Barcode Generator?': {
|
||||
question: 'Was ist ein Barcode Generator?',
|
||||
answer:
|
||||
'Ein Barcode Generator ist ein Online-Tool, das Zahlen oder Texte in scannbare Barcode-Bilder umwandelt. Diese können für Produkte, Etiketten und Inventarsysteme verwendet werden.',
|
||||
},
|
||||
'Ist der Barcode Generator kostenlos?': {
|
||||
question: 'Ist der Barcode Generator kostenlos?',
|
||||
answer:
|
||||
'Ja, unser Barcode Generator ist vollständig kostenlos nutzbar. Sie können Barcodes ohne Anmeldung generieren, herunterladen und drucken.',
|
||||
},
|
||||
'Welches Barcode-Format brauche ich?': {
|
||||
question: 'Welches Barcode-Format brauche ich?',
|
||||
answer:
|
||||
'EAN-13 ist der Standard für Einzelhandel in Europa und weltweit. UPC-A wird hauptsächlich in den USA und Kanada verwendet. Code 128 eignet sich am besten für Logistik und interne Verfolgung, da er Buchstaben und Zahlen unterstützt.',
|
||||
},
|
||||
'Kann ich Barcodes als Vektorgrafik (SVG) herunterladen?': {
|
||||
question: 'Kann ich Barcodes als Vektorgrafik (SVG) herunterladen?',
|
||||
answer:
|
||||
'Ja! SVG-Dateien sind vektorbasiert und können ohne Qualitätsverlust auf jede Größe skaliert werden. Perfekt für professionelle Produktverpackungen und Etiketten.',
|
||||
},
|
||||
'Wie erstelle ich einen Barcode online?': {
|
||||
question: 'Wie erstelle ich einen Barcode online?',
|
||||
answer:
|
||||
'Geben Sie Ihre Produktnummer oder Ihren Text ein, wählen Sie das gewünschte Barcode-Format (z.B. EAN-13 oder Code 128) und der Barcode wird sofort erstellt. Dann können Sie ihn als PNG oder SVG herunterladen.',
|
||||
},
|
||||
'Sind die erstellten Barcodes scannbar?': {
|
||||
question: 'Sind die erstellten Barcodes scannbar?',
|
||||
answer:
|
||||
'Ja, wir generieren standardkonforme Barcodes, die von jedem handelsüblichen Barcode-Scanner gelesen werden können, einschließlich Smartphone-Kamera-Apps.',
|
||||
},
|
||||
'Kann ich diese Barcodes für Amazon verwenden?': {
|
||||
question: 'Kann ich diese Barcodes für Amazon verwenden?',
|
||||
answer:
|
||||
'Sie können hier das Barcode-Bild erstellen, wenn Sie bereits eine gültige EAN/UPC-Nummer haben. Offizielle GS1-Registrierungsnummern erhalten Sie jedoch nur direkt bei GS1, um Produkte auf Amazon oder in großen Einzelhandelssystemen zu listen.',
|
||||
},
|
||||
'Was ist der Unterschied zwischen Barcode und QR-Code?': {
|
||||
question: 'Was ist der Unterschied zwischen Barcode und QR-Code?',
|
||||
answer:
|
||||
'Ein Barcode speichert Daten horizontal (1D) und wird hauptsächlich für Produktkennungen verwendet. Ein QR-Code speichert Daten in 2D (Matrix) und kann viel mehr Informationen enthalten, wie URLs, Kontaktdaten oder WLAN-Zugangsdaten.',
|
||||
},
|
||||
'Kann ich mehrere Barcodes gleichzeitig erstellen?': {
|
||||
question: 'Kann ich mehrere Barcodes gleichzeitig erstellen?',
|
||||
answer:
|
||||
'Ja, mit einem PRO-Account können Sie mehrere Barcodes gleichzeitig generieren. Dies ist ideal für große Produktmengen oder Lagerverwaltung.',
|
||||
},
|
||||
'Was ist eine Prüfziffer bei Barcodes?': {
|
||||
question: 'Was ist eine Prüfziffer bei Barcodes?',
|
||||
answer:
|
||||
'Die Prüfziffer ist die letzte Ziffer in einem Barcode, die mathematisch aus den anderen Ziffern berechnet wird. Sie stellt sicher, dass der Barcode korrekt gescannt wird, selbst wenn er leicht beschädigt oder verkratzt ist.',
|
||||
},
|
||||
};
|
||||
|
||||
const jsonLd = {
|
||||
'@context': 'https://schema.org',
|
||||
'@graph': [
|
||||
generateSoftwareAppSchema(
|
||||
'Barcode Generator',
|
||||
'Erstellen Sie druckfertige Barcodes für EAN, UPC, Code 128 und weitere Formate. Kostenlos und ohne Anmeldung.',
|
||||
'/barcode-generator-preview.png',
|
||||
'UtilitiesApplication'
|
||||
),
|
||||
generateFaqSchema(faqQuestions),
|
||||
],
|
||||
};
|
||||
|
||||
export default function BarcodeGeneratorDEPage() {
|
||||
const t = de;
|
||||
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
|
||||
{/* SEO Content für Suchmaschinen */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
<p>
|
||||
QR Masters kostenloser Barcode Generator ermöglicht es Ihnen,
|
||||
professionelle Barcodes für Produkte, Etiketten und Inventarsysteme zu
|
||||
erstellen. Unterstützt EAN-13 für europäischen Einzelhandel, UPC-A für
|
||||
US-Markt und Code 128 für Logistik und interne Verwendung. Alle
|
||||
Barcodes sind standardkonform und sofort druckfertig.
|
||||
</p>
|
||||
<p>
|
||||
Unser Barcode Generator funktioniert vollständig im Browser. Keine
|
||||
Software-Installation erforderlich. Exportieren Sie Ihre Barcodes als
|
||||
PNG für den sofortigen Druck oder als SVG für professionelle
|
||||
Verpackungsdesigns. Perfekt für kleine Unternehmen, Online-Händler und
|
||||
Lagerverwaltung.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="relative bg-gradient-to-b from-slate-900 to-slate-800 text-white py-16 md:py-24">
|
||||
<div className="absolute inset-0 opacity-10">
|
||||
<svg className="w-full h-full" width="100%" height="100%">
|
||||
<defs>
|
||||
<pattern
|
||||
id="barcode_pattern_de"
|
||||
width="60"
|
||||
height="60"
|
||||
patternUnits="userSpaceOnUse"
|
||||
>
|
||||
<path
|
||||
d="M5 0 V 60 M15 0 V 60 M20 0 V 60 M35 0 V 60 M40 0 V 60 M55 0 V 60"
|
||||
stroke="white"
|
||||
strokeWidth="2"
|
||||
strokeOpacity="0.5"
|
||||
/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="100%" height="100%" fill="url(#barcode_pattern_de)" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl relative z-10">
|
||||
<div className="max-w-3xl mx-auto text-center">
|
||||
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-white/10 text-white/90 text-sm font-medium mb-6 backdrop-blur-sm border border-white/10">
|
||||
<span className="flex h-2 w-2 relative">
|
||||
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-blue-400 opacity-75"></span>
|
||||
<span className="relative inline-flex rounded-full h-2 w-2 bg-blue-400"></span>
|
||||
</span>
|
||||
Kostenloses Tool – Professionell & Schnell
|
||||
</div>
|
||||
|
||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold tracking-tight mb-6">
|
||||
Kostenloser{' '}
|
||||
<span className="text-blue-400">Barcode Generator</span>
|
||||
</h1>
|
||||
|
||||
<p className="text-lg md:text-xl text-slate-300 mb-8 leading-relaxed">
|
||||
Erstellen Sie professionelle Barcodes in Sekunden. Für{' '}
|
||||
<strong className="text-white">
|
||||
Einzelhandel, Lager und Logistik
|
||||
</strong>
|
||||
. Unterstützt EAN-13, UPC-A und Code 128. Keine Anmeldung
|
||||
erforderlich.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap justify-center gap-4 text-sm font-medium">
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
Einzelhandel-fähig
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
SVG-Export
|
||||
</div>
|
||||
<div className="flex items-center gap-2 bg-white/5 px-4 py-2.5 rounded-xl border border-white/10">
|
||||
<Check className="w-4 h-4 text-blue-400" />
|
||||
Ohne Anmeldung
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Generator Section */}
|
||||
<section className="py-12 px-4 bg-slate-100">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<div className="text-center mb-6">
|
||||
<h2 className="text-2xl font-bold mb-2">Barcode jetzt erstellen</h2>
|
||||
<p className="text-muted-foreground">
|
||||
Geben Sie Ihre Daten ein und laden Sie den Barcode herunter
|
||||
</p>
|
||||
</div>
|
||||
<div className="bg-white rounded-3xl shadow-xl overflow-hidden border border-slate-200">
|
||||
<div className="bg-slate-900 px-6 py-3 flex items-center gap-2">
|
||||
<div className="flex gap-1.5">
|
||||
<div className="w-3 h-3 rounded-full bg-red-500"></div>
|
||||
<div className="w-3 h-3 rounded-full bg-yellow-500"></div>
|
||||
<div className="w-3 h-3 rounded-full bg-green-500"></div>
|
||||
</div>
|
||||
<span className="text-white/60 text-sm ml-2">
|
||||
qrmaster.net/tools/barcode-generator
|
||||
</span>
|
||||
</div>
|
||||
<iframe
|
||||
src="https://www.qrmaster.net/tools/barcode-generator"
|
||||
className="w-full h-[650px] border-0"
|
||||
title="Barcode Generator"
|
||||
/>
|
||||
</div>
|
||||
<div className="text-center mt-6">
|
||||
<a
|
||||
href="https://www.qrmaster.net/tools/barcode-generator"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-slate-900 transition-colors"
|
||||
>
|
||||
<span>Vollbild öffnen</span>
|
||||
<svg
|
||||
className="w-4 h-4"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Barcode Types Info */}
|
||||
<section className="py-16 px-4 bg-white">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-12">
|
||||
Barcode-Formate im Überblick
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-3 gap-8">
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-blue-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">EAN-13</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Internationaler Standard für Einzelhandel. 13 Ziffern, weltweit
|
||||
anerkannt.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> Produkte in Europa & global
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-green-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-green-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">UPC-A</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Amerikanischer Standard. 12 Ziffern, hauptsächlich in
|
||||
Nordamerika.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> USA & Kanada Einzelhandel
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-6 border rounded-xl">
|
||||
<div className="w-12 h-12 bg-purple-100 rounded-xl flex items-center justify-center mb-4">
|
||||
<BarcodeIcon className="w-6 h-6 text-purple-600" />
|
||||
</div>
|
||||
<h3 className="font-bold text-lg mb-2">Code 128</h3>
|
||||
<p className="text-sm text-muted-foreground mb-3">
|
||||
Flexible Lösung für Logistik. Alphanumerisch, hohe Datendichte.
|
||||
</p>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
<strong>Einsatz:</strong> Versand, Lager, Inventar
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* How It Works */}
|
||||
<section className="py-16 px-4 bg-slate-50">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-12">
|
||||
So funktioniert unser Barcode Generator
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-5 gap-8">
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
1
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Daten eingeben</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Geben Sie Ihre Produktnummer oder Text ein.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
2
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Format wählen</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
EAN-13, UPC-A oder Code 128 auswählen.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
3
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Vorschau</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Barcode wird in Echtzeit aktualisiert.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
4
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Herunterladen</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Als PNG oder SVG speichern.
|
||||
</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<div className="w-12 h-12 bg-slate-900 text-white rounded-full flex items-center justify-center mx-auto mb-4 font-bold">
|
||||
5
|
||||
</div>
|
||||
<h3 className="font-bold mb-2">Drucken</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Sofort auf Etiketten drucken.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Use Cases */}
|
||||
<section className="py-16 px-4 bg-white">
|
||||
<div className="container mx-auto max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-4">
|
||||
Für wen ist unser Barcode Generator geeignet?
|
||||
</h2>
|
||||
<p className="text-center text-muted-foreground mb-12 max-w-2xl mx-auto">
|
||||
Ob Kleinunternehmer, Online-Händler oder Lagerverwaltung – unser
|
||||
Tool unterstützt Sie bei allen Barcode-Bedarfen.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Printer className="w-8 h-8 text-blue-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Einzelhandel</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
EAN-13 Barcodes für Produktetiketten im stationären Handel.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Shield className="w-8 h-8 text-green-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">E-Commerce</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
UPC/EAN für Amazon, eBay und andere Marktplätze.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Zap className="w-8 h-8 text-orange-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Lager & Logistik</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Code 128 für interne Bestandsverfolgung und Versand.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 bg-slate-50 rounded-xl">
|
||||
<Download className="w-8 h-8 text-purple-600 mb-3" />
|
||||
<h3 className="font-bold mb-2">Druckerei</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
SVG-Export für professionelle Verpackungsdesigns.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* FAQ Section */}
|
||||
<FAQ
|
||||
t={{
|
||||
faq: { title: 'Häufig gestellte Fragen', questions: faqQuestions },
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
{/* Scroll to Top */}
|
||||
<ScrollToTop />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,316 +1,316 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { organizationSchema, websiteSchema } from '@/lib/schema';
|
||||
import { generateFaqSchema } from '@/lib/schema-utils';
|
||||
import { Hero } from '@/components/marketing/Hero';
|
||||
import { InstantGenerator } from '@/components/marketing/InstantGenerator';
|
||||
import { StaticVsDynamic } from '@/components/marketing/StaticVsDynamic';
|
||||
import { Features } from '@/components/marketing/Features';
|
||||
import { Pricing } from '@/components/marketing/Pricing';
|
||||
import { FAQ } from '@/components/marketing/FAQ';
|
||||
import { ScrollToTop } from '@/components/ui/ScrollToTop';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
import de from '@/i18n/de.json';
|
||||
import { AnswerFirstBlock } from '@/components/marketing/AnswerFirstBlock';
|
||||
|
||||
function truncateAtWord(text: string, maxLength: number): string {
|
||||
if (text.length <= maxLength) return text;
|
||||
const truncated = text.slice(0, maxLength);
|
||||
const lastSpace = truncated.lastIndexOf(' ');
|
||||
return lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated;
|
||||
}
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const title = 'QR Code Erstellen – Kostenlos | QR Master';
|
||||
const description =
|
||||
'Erstellen Sie QR Codes kostenlos in Sekunden. Dynamische QR-Codes für Feedback, PDF und mehr. Mit Tracking, Branding und Massen-Erstellung.';
|
||||
|
||||
return {
|
||||
title: {
|
||||
absolute: title,
|
||||
},
|
||||
description,
|
||||
keywords: [
|
||||
'qr code erstellen',
|
||||
'qr code generator',
|
||||
'qr code kostenlos',
|
||||
'qr-code-generatoren',
|
||||
'qr codes erstellen',
|
||||
'qr code erstellen kostenlos',
|
||||
'dynamischer qr code',
|
||||
'qr code mit logo',
|
||||
'feedback qr code',
|
||||
'pdf qr code',
|
||||
'coupon qr code',
|
||||
'app store qr code',
|
||||
'qr code generator online',
|
||||
'qr code erstellen ohne anmeldung',
|
||||
'qr code für speisekarte erstellen',
|
||||
'qr code erstellen free',
|
||||
'online qr code generator kostenlos',
|
||||
'qr code für restaurant erstellen',
|
||||
'qr code für flyer erstellen',
|
||||
'qr code für visitenkarte erstellen',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/qr-code-erstellen',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/',
|
||||
en: 'https://www.qrmaster.net/',
|
||||
de: 'https://www.qrmaster.net/qr-code-erstellen',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'QR Code Erstellen – Kostenlos & Sofort | QR Master',
|
||||
description:
|
||||
'Erstellen Sie QR Codes kostenlos in Sekunden. Mit Tracking, Branding und Massen-Erstellung.',
|
||||
url: 'https://www.qrmaster.net/qr-code-erstellen',
|
||||
type: 'website',
|
||||
locale: 'de_DE',
|
||||
images: [
|
||||
{
|
||||
url: 'https://www.qrmaster.net/og-image.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'QR Code Erstellen - Kostenlos & Sofort',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
title: 'QR Code Erstellen – Kostenlos | QR Master',
|
||||
description:
|
||||
'QR Codes erstellen in Sekunden. Kostenlos, mit Tracking und individuellem Branding.',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default function QRCodeErstellenPage() {
|
||||
// Use German translations
|
||||
const t = de;
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd
|
||||
data={[
|
||||
organizationSchema(),
|
||||
websiteSchema(),
|
||||
generateFaqSchema(t.faq.questions),
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Server-rendered SEO content for crawlers - GERMAN */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
<p>
|
||||
Erstellen Sie professionelle QR Codes für Ihr Unternehmen mit QR
|
||||
Master. Unser dynamischer QR Code Generator ermöglicht es Ihnen,
|
||||
trackbare QR Codes für Feedback, PDF-Dateien, Coupons und App Stores
|
||||
zu erstellen, Ziel-URLs jederzeit zu ändern und detaillierte
|
||||
Statistiken einzusehen. Perfekt für Restaurants, Einzelhandel, Events
|
||||
und Marketing-Kampagnen.
|
||||
</p>
|
||||
<p>
|
||||
Funktionen: Dynamische QR Codes mit Echtzeit-Tracking,
|
||||
Massen-QR-Code-Erstellung aus Excel/CSV, individuelles Branding mit
|
||||
Farben und Logos, erweiterte Scan-Statistiken mit Gerätetypen und
|
||||
Standorten, vCard QR Codes für digitale Visitenkarten und QR Codes für
|
||||
Restaurant-Speisekarten.
|
||||
</p>
|
||||
<p>
|
||||
Starten Sie kostenlos mit 3 aktiven dynamischen QR Codes (8 Typen
|
||||
verfügbar) und unbegrenzten statischen Codes. Upgrade auf Pro für 50
|
||||
Codes mit erweiterten Statistiken, oder Business für 500 Codes mit
|
||||
Massen-Erstellung und Prioritäts-Support.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Hero t={t} />
|
||||
|
||||
{/* SEO Content: QR-Code-Typen und Anwendungen */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl py-12">
|
||||
<h2 className="text-3xl font-bold text-center mb-8">
|
||||
Beliebte QR-Code-Typen für deutsche Unternehmen
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">Speisekarten QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Ideal für Restaurants, Cafés und Bars. Gäste scannen den Code und
|
||||
sehen Ihre Speisekarte digital auf dem Handy –无需接触实物菜单。
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">Feedback QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Sammeln Sie Kundenfeedback direkt nach dem Besuch. Perfekt für
|
||||
Hotels, Zahnarztpraxen und Dienstleister.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">Coupon QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Erstellen Sie einlösbare Coupons mit Zeitlimit. Steigern Sie die
|
||||
Kundentreue in Ihrem Einzelhandel oder Onlineshop.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">vCard QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Digitale Visitenkarte: Kontaktdaten werden mit einem Scan ins
|
||||
Adressbuch übertragen. Für Vertrieb und Networking.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">PDF QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Verteilen Sie PDFs wie Speisekarten, Preislisten oder Anleitungen.
|
||||
Ändern Sie den Inhalt jederzeit ohne Neudruck.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">WiFi QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Gäste verbinden sich automatisch mit Ihrem WLAN. Für Hotels,
|
||||
Coworking Spaces und Gastronomie.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SEO Content: Branchen-Anwendungen */}
|
||||
<div className="bg-slate-50 py-12">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-8">
|
||||
QR-Codes nutzen: Für jede Branche
|
||||
</h2>
|
||||
<div className="space-y-6">
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">
|
||||
Restaurants & Gastronomie
|
||||
</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
Digitale Speisekarten statt Papier, Bestellsysteme über QR-Code,
|
||||
Feedback-Schleifen nach dem Besuch. Spart Druckkosten und
|
||||
reduziert Kontaktpunkte.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">Einzelhandel</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
Produktinformationen per QR-Code, Coupons und Aktionen,
|
||||
Cross-Selling zu Ihrem Onlineshop, Abfrage von
|
||||
Produktbewertungen.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">Events & Messen</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
Digitale Visitenkarten, Event-Flyer mit Programm-QR-Code,
|
||||
Feedback nach Vorträgen, Social-Media-Verbindungen.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">
|
||||
Hotels & Ferienwohnungen
|
||||
</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
Check-in über QR-Code, WLAN-Zugang ohne Passwort, digitale
|
||||
Hausordnung, lokale Empfehlungen und Concierge-Service.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">
|
||||
Dienstleister & Agenturen
|
||||
</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
vCards für Vertriebsteams, Projekt-Updates per PDF-QR-Code,
|
||||
Bewertungsanfragen nach Projektabschluss.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SEO Content: Tipps für höhere Scan-Raten */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl py-12">
|
||||
<h2 className="text-3xl font-bold text-center mb-8">
|
||||
Tipps für mehr QR-Code-Scans
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
<div>
|
||||
<h3 className="font-semibold mb-3">Design optimieren</h3>
|
||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
||||
<li>• Hoher Kontrast: Dunkler Code auf hellem Hintergrund</li>
|
||||
<li>• Ausreichende Größe: Mindestens 2x2 cm, besser 3x3 cm</li>
|
||||
<li>
|
||||
• Eigenes Logo einbinden für Vertrauen und Wiedererkennung
|
||||
</li>
|
||||
<li>• Farben Ihrer Marke verwenden (Logo-Bereich)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-3">Placement verbessern</h3>
|
||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
||||
<li>
|
||||
• Augenhöhe: QR-Codes auf Tischhöhe oder Wandhöhe platzieren
|
||||
</li>
|
||||
<li>• Ausreichend Weißraum um den Code herum</li>
|
||||
<li>• In der Nähe des Call-to-Action: "Scannen Sie hier"</li>
|
||||
<li>• Mehrfach platzieren: Eingang, Theke, Tische, Kasse</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-center text-sm text-muted-foreground mt-6">
|
||||
<strong>Tipp:</strong> Testen Sie Ihren QR-Code vor dem Druck mit
|
||||
mindestens 3 verschiedenen Smartphone-Modellen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Answer First Block (SEO/AEO) - German */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
<AnswerFirstBlock
|
||||
whatIsIt="Ein QR-Code (Quick Response Code) ist ein zweidimensionaler Barcode, der von Smartphones gescannt werden kann, um sofort auf Informationen wie Webseiten, Kontaktdaten oder Speisekarten zuzugreifen. Mit QR Master erstellen Sie dynamische Codes, die Sie nachträglich ändern und statistisch auswerten können."
|
||||
whenToUse={[
|
||||
'Wenn Sie Printmaterialien (Flyer, Plakate) drucken und den Link später ändern möchten',
|
||||
'Wenn Sie wissen wollen, wie oft und wo Ihr Code gescannt wurde',
|
||||
'Wenn Sie professionelles Branding mit eigenem Logo benötigen',
|
||||
]}
|
||||
comparison={{
|
||||
leftTitle: 'Statisch',
|
||||
rightTitle: 'Dynamisch',
|
||||
items: [
|
||||
{ label: 'Inhalt änderbar', value: true, text: 'Nein' },
|
||||
{ label: 'Scan-Statistik', value: true, text: 'Nein' },
|
||||
{ label: 'Druckqualität', value: true, text: 'Hoch' },
|
||||
],
|
||||
}}
|
||||
howTo={{
|
||||
steps: [
|
||||
'Kostenlos bei QR Master anmelden',
|
||||
'Ziel-URL eingeben und QR-Code Design anpassen',
|
||||
'Code herunterladen, testen und drucken. Der Inhalt ist jederzeit änderbar.',
|
||||
],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Main Interaction: Generator */}
|
||||
<InstantGenerator t={t} />
|
||||
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
<StaticVsDynamic t={t} />
|
||||
<Features t={t} />
|
||||
|
||||
{/* Pricing Section */}
|
||||
<Pricing t={t} />
|
||||
|
||||
{/* FAQ Section */}
|
||||
<FAQ t={t} />
|
||||
|
||||
{/* Scroll to Top Button */}
|
||||
<ScrollToTop />
|
||||
</>
|
||||
);
|
||||
}
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import { organizationSchema, websiteSchema } from '@/lib/schema';
|
||||
import { generateFaqSchema } from '@/lib/schema-utils';
|
||||
import { Hero } from '@/components/marketing/Hero';
|
||||
import { InstantGenerator } from '@/components/marketing/InstantGenerator';
|
||||
import { StaticVsDynamic } from '@/components/marketing/StaticVsDynamic';
|
||||
import { Features } from '@/components/marketing/Features';
|
||||
import { Pricing } from '@/components/marketing/Pricing';
|
||||
import { FAQ } from '@/components/marketing/FAQ';
|
||||
import { ScrollToTop } from '@/components/ui/ScrollToTop';
|
||||
import { FreeToolsGrid } from '@/components/marketing/FreeToolsGrid';
|
||||
import de from '@/i18n/de.json';
|
||||
import { AnswerFirstBlock } from '@/components/marketing/AnswerFirstBlock';
|
||||
|
||||
function truncateAtWord(text: string, maxLength: number): string {
|
||||
if (text.length <= maxLength) return text;
|
||||
const truncated = text.slice(0, maxLength);
|
||||
const lastSpace = truncated.lastIndexOf(' ');
|
||||
return lastSpace > 0 ? truncated.slice(0, lastSpace) : truncated;
|
||||
}
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
const title = 'QR Code Erstellen – Kostenlos | QR Master';
|
||||
const description =
|
||||
'Erstellen Sie QR Codes kostenlos in Sekunden. Dynamische QR-Codes für Feedback, PDF und mehr. Mit Tracking, Branding und Massen-Erstellung.';
|
||||
|
||||
return {
|
||||
title: {
|
||||
absolute: title,
|
||||
},
|
||||
description,
|
||||
keywords: [
|
||||
'qr code erstellen',
|
||||
'qr code generator',
|
||||
'qr code kostenlos',
|
||||
'qr-code-generatoren',
|
||||
'qr codes erstellen',
|
||||
'qr code erstellen kostenlos',
|
||||
'dynamischer qr code',
|
||||
'qr code mit logo',
|
||||
'feedback qr code',
|
||||
'pdf qr code',
|
||||
'coupon qr code',
|
||||
'app store qr code',
|
||||
'qr code generator online',
|
||||
'qr code erstellen ohne anmeldung',
|
||||
'qr code für speisekarte erstellen',
|
||||
'qr code erstellen free',
|
||||
'online qr code generator kostenlos',
|
||||
'qr code für restaurant erstellen',
|
||||
'qr code für flyer erstellen',
|
||||
'qr code für visitenkarte erstellen',
|
||||
],
|
||||
alternates: {
|
||||
canonical: 'https://www.qrmaster.net/qr-code-erstellen',
|
||||
languages: {
|
||||
'x-default': 'https://www.qrmaster.net/',
|
||||
en: 'https://www.qrmaster.net/',
|
||||
de: 'https://www.qrmaster.net/qr-code-erstellen',
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'QR Code Erstellen – Kostenlos & Sofort | QR Master',
|
||||
description:
|
||||
'Erstellen Sie QR Codes kostenlos in Sekunden. Mit Tracking, Branding und Massen-Erstellung.',
|
||||
url: 'https://www.qrmaster.net/qr-code-erstellen',
|
||||
type: 'website',
|
||||
locale: 'de_DE',
|
||||
images: [
|
||||
{
|
||||
url: 'https://www.qrmaster.net/og-image.png',
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: 'QR Code Erstellen - Kostenlos & Sofort',
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
title: 'QR Code Erstellen – Kostenlos | QR Master',
|
||||
description:
|
||||
'QR Codes erstellen in Sekunden. Kostenlos, mit Tracking und individuellem Branding.',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default function QRCodeErstellenPage() {
|
||||
// Use German translations
|
||||
const t = de;
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd
|
||||
data={[
|
||||
organizationSchema(),
|
||||
websiteSchema(),
|
||||
generateFaqSchema(t.faq.questions),
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Server-rendered SEO content for crawlers - GERMAN */}
|
||||
<div className="sr-only" aria-hidden="false">
|
||||
<p>
|
||||
Erstellen Sie professionelle QR Codes für Ihr Unternehmen mit QR
|
||||
Master. Unser dynamischer QR Code Generator ermöglicht es Ihnen,
|
||||
trackbare QR Codes für Feedback, PDF-Dateien, Coupons und App Stores
|
||||
zu erstellen, Ziel-URLs jederzeit zu ändern und detaillierte
|
||||
Statistiken einzusehen. Perfekt für Restaurants, Einzelhandel, Events
|
||||
und Marketing-Kampagnen.
|
||||
</p>
|
||||
<p>
|
||||
Funktionen: Dynamische QR Codes mit Echtzeit-Tracking,
|
||||
Massen-QR-Code-Erstellung aus Excel/CSV, individuelles Branding mit
|
||||
Farben und Logos, erweiterte Scan-Statistiken mit Gerätetypen und
|
||||
Standorten, vCard QR Codes für digitale Visitenkarten und QR Codes für
|
||||
Restaurant-Speisekarten.
|
||||
</p>
|
||||
<p>
|
||||
Starten Sie kostenlos mit 3 aktiven dynamischen QR Codes (8 Typen
|
||||
verfügbar) und unbegrenzten statischen Codes. Upgrade auf Pro für 50
|
||||
Codes mit erweiterten Statistiken, oder Business für 500 Codes mit
|
||||
Massen-Erstellung und Prioritäts-Support.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<Hero t={t} />
|
||||
|
||||
{/* SEO Content: QR-Code-Typen und Anwendungen */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl py-12">
|
||||
<h2 className="text-3xl font-bold text-center mb-8">
|
||||
Beliebte QR-Code-Typen für deutsche Unternehmen
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">Speisekarten QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Ideal für Restaurants, Cafés und Bars. Gäste scannen den Code und
|
||||
sehen Ihre Speisekarte digital auf dem Handy –无需接触实物菜单。
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">Feedback QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Sammeln Sie Kundenfeedback direkt nach dem Besuch. Perfekt für
|
||||
Hotels, Zahnarztpraxen und Dienstleister.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">Coupon QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Erstellen Sie einlösbare Coupons mit Zeitlimit. Steigern Sie die
|
||||
Kundentreue in Ihrem Einzelhandel oder Onlineshop.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">vCard QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Digitale Visitenkarte: Kontaktdaten werden mit einem Scan ins
|
||||
Adressbuch übertragen. Für Vertrieb und Networking.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">PDF QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Verteilen Sie PDFs wie Speisekarten, Preislisten oder Anleitungen.
|
||||
Ändern Sie den Inhalt jederzeit ohne Neudruck.
|
||||
</p>
|
||||
</div>
|
||||
<div className="p-6 border rounded-lg">
|
||||
<h3 className="font-semibold text-lg mb-2">WiFi QR-Code</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Gäste verbinden sich automatisch mit Ihrem WLAN. Für Hotels,
|
||||
Coworking Spaces und Gastronomie.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SEO Content: Branchen-Anwendungen */}
|
||||
<div className="bg-slate-50 py-12">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
<h2 className="text-3xl font-bold text-center mb-8">
|
||||
QR-Codes nutzen: Für jede Branche
|
||||
</h2>
|
||||
<div className="space-y-6">
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">
|
||||
Restaurants & Gastronomie
|
||||
</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
Digitale Speisekarten statt Papier, Bestellsysteme über QR-Code,
|
||||
Feedback-Schleifen nach dem Besuch. Spart Druckkosten und
|
||||
reduziert Kontaktpunkte.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">Einzelhandel</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
Produktinformationen per QR-Code, Coupons und Aktionen,
|
||||
Cross-Selling zu Ihrem Onlineshop, Abfrage von
|
||||
Produktbewertungen.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">Events & Messen</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
Digitale Visitenkarten, Event-Flyer mit Programm-QR-Code,
|
||||
Feedback nach Vorträgen, Social-Media-Verbindungen.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">
|
||||
Hotels & Ferienwohnungen
|
||||
</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
Check-in über QR-Code, WLAN-Zugang ohne Passwort, digitale
|
||||
Hausordnung, lokale Empfehlungen und Concierge-Service.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col md:flex-row gap-4 items-start">
|
||||
<div className="md:w-1/3 font-semibold">
|
||||
Dienstleister & Agenturen
|
||||
</div>
|
||||
<div className="md:w-2/3 text-sm text-muted-foreground">
|
||||
vCards für Vertriebsteams, Projekt-Updates per PDF-QR-Code,
|
||||
Bewertungsanfragen nach Projektabschluss.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* SEO Content: Tipps für höhere Scan-Raten */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl py-12">
|
||||
<h2 className="text-3xl font-bold text-center mb-8">
|
||||
Tipps für mehr QR-Code-Scans
|
||||
</h2>
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
<div>
|
||||
<h3 className="font-semibold mb-3">Design optimieren</h3>
|
||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
||||
<li>• Hoher Kontrast: Dunkler Code auf hellem Hintergrund</li>
|
||||
<li>• Ausreichende Größe: Mindestens 2x2 cm, besser 3x3 cm</li>
|
||||
<li>
|
||||
• Eigenes Logo einbinden für Vertrauen und Wiedererkennung
|
||||
</li>
|
||||
<li>• Farben Ihrer Marke verwenden (Logo-Bereich)</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="font-semibold mb-3">Placement verbessern</h3>
|
||||
<ul className="space-y-2 text-sm text-muted-foreground">
|
||||
<li>
|
||||
• Augenhöhe: QR-Codes auf Tischhöhe oder Wandhöhe platzieren
|
||||
</li>
|
||||
<li>• Ausreichend Weißraum um den Code herum</li>
|
||||
<li>• In der Nähe des Call-to-Action: "Scannen Sie hier"</li>
|
||||
<li>• Mehrfach platzieren: Eingang, Theke, Tische, Kasse</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-center text-sm text-muted-foreground mt-6">
|
||||
<strong>Tipp:</strong> Testen Sie Ihren QR-Code vor dem Druck mit
|
||||
mindestens 3 verschiedenen Smartphone-Modellen.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Answer First Block (SEO/AEO) - German */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
<AnswerFirstBlock
|
||||
whatIsIt="Ein QR-Code (Quick Response Code) ist ein zweidimensionaler Barcode, der von Smartphones gescannt werden kann, um sofort auf Informationen wie Webseiten, Kontaktdaten oder Speisekarten zuzugreifen. Mit QR Master erstellen Sie dynamische Codes, die Sie nachträglich ändern und statistisch auswerten können."
|
||||
whenToUse={[
|
||||
'Wenn Sie Printmaterialien (Flyer, Plakate) drucken und den Link später ändern möchten',
|
||||
'Wenn Sie wissen wollen, wie oft und wo Ihr Code gescannt wurde',
|
||||
'Wenn Sie professionelles Branding mit eigenem Logo benötigen',
|
||||
]}
|
||||
comparison={{
|
||||
leftTitle: 'Statisch',
|
||||
rightTitle: 'Dynamisch',
|
||||
items: [
|
||||
{ label: 'Inhalt änderbar', value: true, text: 'Nein' },
|
||||
{ label: 'Scan-Statistik', value: true, text: 'Nein' },
|
||||
{ label: 'Druckqualität', value: true, text: 'Hoch' },
|
||||
],
|
||||
}}
|
||||
howTo={{
|
||||
steps: [
|
||||
'Kostenlos bei QR Master anmelden',
|
||||
'Ziel-URL eingeben und QR-Code Design anpassen',
|
||||
'Code herunterladen, testen und drucken. Der Inhalt ist jederzeit änderbar.',
|
||||
],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Main Interaction: Generator */}
|
||||
<InstantGenerator t={t} />
|
||||
|
||||
{/* Free Tools Grid */}
|
||||
<FreeToolsGrid />
|
||||
|
||||
<StaticVsDynamic t={t} />
|
||||
<Features t={t} />
|
||||
|
||||
{/* Pricing Section */}
|
||||
<Pricing t={t} />
|
||||
|
||||
{/* FAQ Section */}
|
||||
<FAQ t={t} />
|
||||
|
||||
{/* Scroll to Top Button */}
|
||||
<ScrollToTop />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user