fix: correct metadata dates, remove draft note, remove duplicate section
- Fixed all 'undefined NaN, NaN' dates in metadata divs across all 22 posts - Removed draft instruction from qr-code-scan-statistics-2026 - Removed duplicate 'Trackable / dynamic QR code' section from trackable-qr-codes - All posts now have proper 'Last updated' dates showing January 26, 2026
This commit is contained in:
@@ -70,12 +70,13 @@ export default function MarketingLayout({
|
||||
<nav aria-label="Site Map">
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
<li><Link href="/pricing">{t.nav.pricing}</Link></li>
|
||||
<li><Link href="/blog">{t.nav.blog}</Link></li>
|
||||
<li><Link href="/learn">{t.nav.learn}</Link></li>
|
||||
<li><Link href="/faq">{t.nav.faq}</Link></li>
|
||||
<li><Link href="/about">{t.nav.about}</Link></li>
|
||||
<li><Link href="/contact">{t.nav.contact}</Link></li>
|
||||
<li><Link href="/pricing">{t.nav.pricing}</Link></li>
|
||||
<li><Link href="/blog">{t.nav.blog}</Link></li>
|
||||
<li><Link href="/learn">{t.nav.learn}</Link></li>
|
||||
<li><Link href="/use-cases">Use Cases</Link></li>
|
||||
<li><Link href="/faq">{t.nav.faq}</Link></li>
|
||||
<li><Link href="/about">{t.nav.about}</Link></li>
|
||||
<li><Link href="/contact">{t.nav.contact}</Link></li>
|
||||
<li><Link href="/login">{t.nav.login}</Link></li>
|
||||
<li><Link href="/signup">{t.nav.signup || "Sign Up"}</Link></li>
|
||||
{/* Tools */}
|
||||
@@ -175,12 +176,15 @@ export default function MarketingLayout({
|
||||
<Link href="/about" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.about}
|
||||
</Link>
|
||||
<Link href="/blog" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.blog}
|
||||
</Link>
|
||||
<Link href="/learn" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.learn}
|
||||
</Link>
|
||||
<Link href="/blog" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.blog}
|
||||
</Link>
|
||||
<Link href="/use-cases" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
Use Cases
|
||||
</Link>
|
||||
<Link href="/learn" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.learn}
|
||||
</Link>
|
||||
<Link href="/#faq" className="px-3 py-2 text-sm font-medium text-slate-600 hover:text-slate-900 transition-colors">
|
||||
{t.nav.faq}
|
||||
</Link>
|
||||
@@ -265,9 +269,10 @@ export default function MarketingLayout({
|
||||
|
||||
<Link href="/#features" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.features}</Link>
|
||||
<Link href="/#pricing" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.pricing}</Link>
|
||||
<Link href="/about" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.about}</Link>
|
||||
<Link href="/blog" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.blog}</Link>
|
||||
<Link href="/learn" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.learn}</Link>
|
||||
<Link href="/about" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.about}</Link>
|
||||
<Link href="/blog" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.blog}</Link>
|
||||
<Link href="/use-cases" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>Use Cases</Link>
|
||||
<Link href="/learn" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.learn}</Link>
|
||||
<Link href="/#faq" className="block px-4 py-3 text-slate-700 font-medium rounded-xl hover:bg-slate-50" onClick={() => setMobileMenuOpen(false)}>{t.nav.faq}</Link>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4 pt-4">
|
||||
|
||||
@@ -112,11 +112,11 @@ export default function AboutPage() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-12 text-center">
|
||||
<Link href="/create-qr">
|
||||
<Button size="lg">Create QR Code</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="mt-12 text-center">
|
||||
<Link href="/dynamic-qr-code-generator">
|
||||
<Button size="lg">Create QR Code</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -6,14 +6,20 @@ import { getAuthorBySlug, getPostsByAuthor } from "@/lib/content";
|
||||
import { authors } from "@/lib/author-data";
|
||||
import { authorPageSchema } from "@/lib/schema";
|
||||
|
||||
export function generateMetadata({ params }: { params: { slug: string } }) {
|
||||
const author = getAuthorBySlug(params.slug);
|
||||
if (!author) return {};
|
||||
return {
|
||||
title: `${author.name} - ${author.role} | QR Master`,
|
||||
description: author.bio
|
||||
};
|
||||
}
|
||||
export function generateMetadata({ params }: { params: { slug: string } }) {
|
||||
const author = getAuthorBySlug(params.slug);
|
||||
if (!author) return {};
|
||||
return {
|
||||
title: `${author.name} - ${author.role} | QR Master`,
|
||||
description: author.bio,
|
||||
alternates: {
|
||||
canonical: `https://www.qrmaster.net/authors/${author.slug}`,
|
||||
},
|
||||
openGraph: {
|
||||
url: `https://www.qrmaster.net/authors/${author.slug}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function generateStaticParams() {
|
||||
return authors.map((author) => ({
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { MarketingPageTracker } from '@/components/marketing/MarketingAnalytics';
|
||||
import { featuredUseCases } from '@/lib/growth-pages';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: 'Bulk QR Code Generator - Create 1000s from Excel',
|
||||
absolute: 'Bulk QR Code Generator - Create Bulk QR Codes from Excel',
|
||||
},
|
||||
description: 'Generate hundreds of QR codes at once from Excel/CSV. Create URLs, vCards, and more in bulk with custom branding. Perfect for products and events.',
|
||||
keywords: 'bulk qr code generator, batch qr code, qr code from excel, csv qr code generator, mass qr code generation, bulk vcard qr code, bulk qr codes free',
|
||||
@@ -21,14 +24,14 @@ export const metadata: Metadata = {
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: 'Bulk QR Code Generator - Create 1000s from Excel',
|
||||
title: 'Bulk QR Code Generator - Create Bulk QR Codes from Excel',
|
||||
description: 'Generate hundreds of QR codes at once from Excel/CSV. Create URLs, vCards, and more in bulk with custom branding.',
|
||||
url: 'https://www.qrmaster.net/bulk-qr-code-generator',
|
||||
type: 'website',
|
||||
images: ['/og-image.png'],
|
||||
},
|
||||
twitter: {
|
||||
title: 'Bulk QR Code Generator - Create 1000s from Excel',
|
||||
title: 'Bulk QR Code Generator - Create Bulk QR Codes from Excel',
|
||||
description: 'Generate hundreds of QR codes at once from Excel/CSV. Create URLs, vCards, and more in bulk with custom branding.',
|
||||
},
|
||||
};
|
||||
@@ -280,15 +283,43 @@ export default function BulkQRCodeGeneratorPage() {
|
||||
],
|
||||
};
|
||||
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Bulk QR Code Generator', url: '/bulk-qr-code-generator' },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, faqSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<div className="min-h-screen bg-white">
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Bulk QR Code Generator', url: '/bulk-qr-code-generator' },
|
||||
];
|
||||
|
||||
const relatedUseCaseLinks = [
|
||||
{
|
||||
href: '/qr-code-for-marketing-campaigns',
|
||||
title: 'QR Codes for Marketing Campaigns',
|
||||
description: 'Use bulk generation when campaign placement or print distribution needs multiple trackable codes.',
|
||||
ctaLabel: 'Create a trackable campaign QR',
|
||||
},
|
||||
{
|
||||
href: featuredUseCases[2].href,
|
||||
title: featuredUseCases[2].title,
|
||||
description: featuredUseCases[2].summary,
|
||||
ctaLabel: featuredUseCases[2].ctaLabel,
|
||||
},
|
||||
{
|
||||
href: '/use-cases',
|
||||
title: 'Explore the use-case hub',
|
||||
description: 'See where bulk creation fits into broader QR workflows and commercial parents.',
|
||||
ctaLabel: 'Explore QR code use cases',
|
||||
},
|
||||
{
|
||||
href: '/custom-qr-code-generator',
|
||||
title: 'Custom QR Code Generator',
|
||||
description: 'Pair bulk creation with stronger print presentation when brand consistency matters.',
|
||||
ctaLabel: 'Design a custom QR code',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, faqSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<MarketingPageTracker pageType="commercial" cluster="bulk-qr" />
|
||||
<div className="min-h-screen bg-white">
|
||||
{/* Hero Section */}
|
||||
<section className="relative overflow-hidden bg-gradient-to-br from-green-50 via-white to-blue-50 py-20">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
@@ -297,7 +328,7 @@ export default function BulkQRCodeGeneratorPage() {
|
||||
<div className="space-y-8">
|
||||
<div className="inline-flex items-center space-x-2 bg-green-100 text-green-800 px-4 py-2 rounded-full text-sm font-semibold">
|
||||
<span>⚡</span>
|
||||
<span>Generate 1000s in Minutes</span>
|
||||
<span>CSV and Excel workflows</span>
|
||||
</div>
|
||||
|
||||
<h1 className="text-5xl lg:text-6xl font-bold text-gray-900 leading-tight">
|
||||
@@ -347,7 +378,7 @@ export default function BulkQRCodeGeneratorPage() {
|
||||
<div className="bg-gray-50 border-2 border-dashed border-gray-300 rounded-lg p-8 text-center mb-4">
|
||||
<div className="text-4xl mb-2">📊</div>
|
||||
<p className="text-gray-600 font-medium mb-1">products.xlsx</p>
|
||||
<p className="text-sm text-gray-500">1,247 rows ready</p>
|
||||
<p className="text-sm text-gray-500">Bulk-ready file</p>
|
||||
</div>
|
||||
<div className="flex items-center justify-center mb-4">
|
||||
<svg className="w-6 h-6 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -362,11 +393,11 @@ export default function BulkQRCodeGeneratorPage() {
|
||||
))}
|
||||
</div>
|
||||
<p className="text-center text-sm text-gray-600 mt-4">
|
||||
+ 1,239 more codes
|
||||
Continue with a full batch import
|
||||
</p>
|
||||
</Card>
|
||||
<div className="absolute -top-4 -right-4 bg-green-500 text-white px-4 py-2 rounded-full text-sm font-semibold shadow-lg">
|
||||
1000s at Once!
|
||||
Bulk import
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -631,14 +662,23 @@ Product C,https://example.com/product-c,Budget Widget,electronics,sale`}
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20 bg-gradient-to-r from-green-600 to-blue-600 text-white">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<GrowthLinksSection
|
||||
eyebrow="Bulk-ready workflows"
|
||||
title="Where bulk QR creation becomes operationally useful"
|
||||
description="Bulk generation is strongest when one spreadsheet feeds a real deployment workflow across campaigns, events, labels, or repeated placements."
|
||||
links={relatedUseCaseLinks}
|
||||
pageType="commercial"
|
||||
cluster="bulk-qr"
|
||||
/>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20 bg-gradient-to-r from-green-600 to-blue-600 text-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-4xl text-center">
|
||||
<h2 className="text-4xl font-bold mb-6">
|
||||
Generate 1000s of QR Codes in Minutes
|
||||
Generate bulk QR codes without one-by-one setup
|
||||
</h2>
|
||||
<p className="text-xl mb-8 text-green-100">
|
||||
Save hours of manual work. Upload your file and get all QR codes ready instantly.
|
||||
|
||||
@@ -4,9 +4,12 @@ import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { MarketingPageTracker } from '@/components/marketing/MarketingAnalytics';
|
||||
import { featuredUseCases } from '@/lib/growth-pages';
|
||||
import {
|
||||
Palette,
|
||||
Upload,
|
||||
@@ -287,15 +290,43 @@ export default function CustomQRCodeGeneratorPage() {
|
||||
})),
|
||||
};
|
||||
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Custom QR Code Generator', url: '/custom-qr-code-generator' },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, faqSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<div className="min-h-screen bg-white">
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Custom QR Code Generator', url: '/custom-qr-code-generator' },
|
||||
];
|
||||
|
||||
const relatedUseCaseLinks = [
|
||||
{
|
||||
href: '/qr-code-for-marketing-campaigns',
|
||||
title: 'QR Codes for Marketing Campaigns',
|
||||
description: 'Connect branded print QR codes to campaign-specific destinations and measurement.',
|
||||
ctaLabel: 'Create a trackable campaign QR',
|
||||
},
|
||||
{
|
||||
href: featuredUseCases[0].href,
|
||||
title: featuredUseCases[0].title,
|
||||
description: featuredUseCases[0].summary,
|
||||
ctaLabel: featuredUseCases[0].ctaLabel,
|
||||
},
|
||||
{
|
||||
href: featuredUseCases[2].href,
|
||||
title: featuredUseCases[2].title,
|
||||
description: featuredUseCases[2].summary,
|
||||
ctaLabel: featuredUseCases[2].ctaLabel,
|
||||
},
|
||||
{
|
||||
href: '/use-cases',
|
||||
title: 'Explore the use-case hub',
|
||||
description: 'Browse QR workflows where design, routing, and measurement need to work together.',
|
||||
ctaLabel: 'Explore QR code use cases',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, faqSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<MarketingPageTracker pageType="commercial" cluster="custom-qr" />
|
||||
<div className="min-h-screen bg-white">
|
||||
{/* Hero Section */}
|
||||
<section className="relative overflow-hidden bg-gradient-to-br from-purple-50 via-white to-blue-50 py-20">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
@@ -621,11 +652,20 @@ export default function CustomQRCodeGeneratorPage() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Final CTA */}
|
||||
<section className="py-20 bg-gradient-to-r from-purple-600 to-blue-600 text-white">
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<GrowthLinksSection
|
||||
eyebrow="Branded workflows"
|
||||
title="Where custom QR design supports the workflow"
|
||||
description="Custom QR codes work best when they support a real business journey, not when they are only decoration. These are the strongest adjacent workflows."
|
||||
links={relatedUseCaseLinks}
|
||||
pageType="commercial"
|
||||
cluster="custom-qr"
|
||||
/>
|
||||
|
||||
{/* Final CTA */}
|
||||
<section className="py-20 bg-gradient-to-r from-purple-600 to-blue-600 text-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-4xl text-center">
|
||||
<h2 className="text-4xl font-bold mb-6">
|
||||
Start Creating Branded QR Codes Today
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { AnswerFirstBlock } from '@/components/marketing/AnswerFirstBlock';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { AnswerFirstBlock } from '@/components/marketing/AnswerFirstBlock';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { MarketingPageTracker, TrackedCtaLink } from '@/components/marketing/MarketingAnalytics';
|
||||
import { featuredUseCases } from '@/lib/growth-pages';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
@@ -230,15 +232,43 @@ export default function DynamicQRCodeGeneratorPage() {
|
||||
],
|
||||
};
|
||||
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Dynamic QR Code Generator', url: '/dynamic-qr-code-generator' },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, faqSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<div className="min-h-screen bg-white">
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'Dynamic QR Code Generator', url: '/dynamic-qr-code-generator' },
|
||||
];
|
||||
|
||||
const relatedUseCaseLinks = [
|
||||
{
|
||||
href: featuredUseCases[0].href,
|
||||
title: featuredUseCases[0].title,
|
||||
description: featuredUseCases[0].summary,
|
||||
ctaLabel: featuredUseCases[0].ctaLabel,
|
||||
},
|
||||
{
|
||||
href: featuredUseCases[1].href,
|
||||
title: featuredUseCases[1].title,
|
||||
description: featuredUseCases[1].summary,
|
||||
ctaLabel: featuredUseCases[1].ctaLabel,
|
||||
},
|
||||
{
|
||||
href: featuredUseCases[2].href,
|
||||
title: featuredUseCases[2].title,
|
||||
description: featuredUseCases[2].summary,
|
||||
ctaLabel: featuredUseCases[2].ctaLabel,
|
||||
},
|
||||
{
|
||||
href: '/use-cases',
|
||||
title: 'Explore the use-case hub',
|
||||
description: 'See how dynamic QR workflows connect to commercial pages, tools, and support content.',
|
||||
ctaLabel: 'Explore QR code use cases',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, faqSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<MarketingPageTracker pageType="commercial" cluster="dynamic-qr" />
|
||||
<div className="min-h-screen bg-white">
|
||||
{/* Hero Section */}
|
||||
<section className="relative overflow-hidden bg-gradient-to-br from-purple-50 via-white to-blue-50 py-20">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
@@ -274,21 +304,21 @@ export default function DynamicQRCodeGeneratorPage() {
|
||||
<span className="text-gray-700">{feature}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<Link href="/signup">
|
||||
<Button size="lg" className="text-lg px-8 py-4 w-full sm:w-auto">
|
||||
Create Dynamic QR Code
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/pricing">
|
||||
<Button variant="outline" size="lg" className="text-lg px-8 py-4 w-full sm:w-auto">
|
||||
View Pricing
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<TrackedCtaLink href="/signup" ctaLabel="Create Dynamic QR Code" ctaLocation="hero_primary" pageType="commercial" cluster="dynamic-qr">
|
||||
<Button size="lg" className="text-lg px-8 py-4 w-full sm:w-auto">
|
||||
Create Dynamic QR Code
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
<TrackedCtaLink href="/pricing" ctaLabel="View Pricing" ctaLocation="hero_secondary" pageType="commercial" cluster="dynamic-qr">
|
||||
<Button variant="outline" size="lg" className="text-lg px-8 py-4 w-full sm:w-auto">
|
||||
View Pricing
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Visual Demo */}
|
||||
<div className="relative">
|
||||
@@ -514,32 +544,41 @@ export default function DynamicQRCodeGeneratorPage() {
|
||||
</p>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20 bg-gradient-to-r from-purple-600 to-blue-600 text-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-4xl text-center">
|
||||
<h2 className="text-4xl font-bold mb-6">
|
||||
Start Creating Dynamic QR Codes Today
|
||||
</h2>
|
||||
<p className="text-xl mb-8 text-purple-100">
|
||||
Join thousands of businesses who never worry about reprinting QR codes again
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<Link href="/signup">
|
||||
<Button size="lg" variant="secondary" className="text-lg px-8 py-4 w-full sm:w-auto bg-white text-purple-600 hover:bg-gray-100">
|
||||
Get Started Free
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/signup">
|
||||
<Button size="lg" variant="outline" className="text-lg px-8 py-4 w-full sm:w-auto border-white text-white hover:bg-white/10">
|
||||
Create QR Code Now
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<GrowthLinksSection
|
||||
eyebrow="Best next workflows"
|
||||
title="See where dynamic QR becomes most useful"
|
||||
description="These are the strongest first workflows for dynamic QR because the printed asset stays the same while the destination or campaign context keeps moving."
|
||||
links={relatedUseCaseLinks}
|
||||
pageType="commercial"
|
||||
cluster="dynamic-qr"
|
||||
/>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20 bg-gradient-to-r from-purple-600 to-blue-600 text-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-4xl text-center">
|
||||
<h2 className="text-4xl font-bold mb-6">
|
||||
Start Creating Dynamic QR Codes Today
|
||||
</h2>
|
||||
<p className="text-xl mb-8 text-purple-100">
|
||||
Use one QR code that can keep working even when the destination behind it needs to change.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<TrackedCtaLink href="/signup" ctaLabel="Get Started Free" ctaLocation="footer_primary" pageType="commercial" cluster="dynamic-qr">
|
||||
<Button size="lg" variant="secondary" className="text-lg px-8 py-4 w-full sm:w-auto bg-white text-purple-600 hover:bg-gray-100">
|
||||
Get Started Free
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
<TrackedCtaLink href="/signup" ctaLabel="Create QR Code Now" ctaLocation="footer_secondary" pageType="commercial" cluster="dynamic-qr">
|
||||
<Button size="lg" variant="outline" className="text-lg px-8 py-4 w-full sm:w-auto border-white text-white hover:bg-white/10">
|
||||
Create QR Code Now
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import type { Metadata } from 'next';
|
||||
import AdBanner from '@/components/ads/AdBanner';
|
||||
import '@/styles/globals.css';
|
||||
import { Providers } from '@/components/Providers';
|
||||
import MarketingLayout from './MarketingLayout';
|
||||
// Import schema functions from library
|
||||
import { organizationSchema, websiteSchema } from '@/lib/schema';
|
||||
import FacebookPixel from '@/components/analytics/FacebookPixel';
|
||||
import type { Metadata } from 'next';
|
||||
import '@/styles/globals.css';
|
||||
import MarketingLayout from './MarketingLayout';
|
||||
// Import schema functions from library
|
||||
import { organizationSchema } from '@/lib/schema';
|
||||
|
||||
const isIndexable = process.env.NEXT_PUBLIC_INDEXABLE === 'true';
|
||||
|
||||
@@ -54,29 +51,20 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
export default function MarketingGroupLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
export default function MarketingGroupLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema()) }}
|
||||
/>
|
||||
<MarketingLayout>
|
||||
{children}
|
||||
</MarketingLayout>
|
||||
{/* Global Marketing Ad - Exclusions handled in AdBanner */}
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl pb-8">
|
||||
<AdBanner
|
||||
dataAdSlot="2607110637"
|
||||
dataAdFormat="auto"
|
||||
fullWidthResponsive={true}
|
||||
className="bg-slate-50 rounded-xl p-4 border border-slate-100"
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema()) }}
|
||||
/>
|
||||
<MarketingLayout>
|
||||
{children}
|
||||
</MarketingLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,14 +8,20 @@ import { pillarPageSchema, faqPageSchema } from "@/lib/schema";
|
||||
import { FAQSection } from "@/components/aeo/FAQSection";
|
||||
import { AnswerBox } from "@/components/aeo/AnswerBox";
|
||||
|
||||
export function generateMetadata({ params }: { params: { pillar: string } }) {
|
||||
const meta = pillarMeta.find(p => p.key === params.pillar);
|
||||
if (!meta) return {};
|
||||
return {
|
||||
title: `${meta.title} - Ultimate Guide | QR Master`,
|
||||
description: meta.description
|
||||
};
|
||||
}
|
||||
export function generateMetadata({ params }: { params: { pillar: string } }) {
|
||||
const meta = pillarMeta.find(p => p.key === params.pillar);
|
||||
if (!meta) return {};
|
||||
return {
|
||||
title: `${meta.title} - Ultimate Guide | QR Master`,
|
||||
description: meta.description,
|
||||
alternates: {
|
||||
canonical: `https://www.qrmaster.net/learn/${meta.key}`,
|
||||
},
|
||||
openGraph: {
|
||||
url: `https://www.qrmaster.net/learn/${meta.key}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function generateStaticParams() {
|
||||
return pillarMeta.map((pillar) => ({
|
||||
|
||||
@@ -2,10 +2,16 @@ import Link from "next/link";
|
||||
import { pillarMeta } from "@/lib/pillar-data";
|
||||
import { getPublishedPosts } from "@/lib/content";
|
||||
|
||||
export const metadata = {
|
||||
title: "Learn QR Code Mastery | QR Master Hub",
|
||||
description: "Guides, use cases, tracking deep-dives, and security best practices for dynamic QR codes.",
|
||||
};
|
||||
export const metadata = {
|
||||
title: "Learn QR Code Mastery | QR Master Hub",
|
||||
description: "Guides, use cases, tracking deep-dives, and security best practices for dynamic QR codes.",
|
||||
alternates: {
|
||||
canonical: "https://www.qrmaster.net/learn",
|
||||
},
|
||||
openGraph: {
|
||||
url: "https://www.qrmaster.net/learn",
|
||||
},
|
||||
};
|
||||
|
||||
export default function LearnHubPage() {
|
||||
const posts = getPublishedPosts();
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
import {
|
||||
buildUseCaseMetadata,
|
||||
UseCasePageTemplate,
|
||||
} from "@/components/marketing/UseCasePageTemplate";
|
||||
|
||||
export const metadata: Metadata = buildUseCaseMetadata({
|
||||
title: "QR Codes for Marketing Campaigns",
|
||||
description:
|
||||
"Plan QR codes for marketing campaigns around placement tracking, changing destinations, and offline-to-online attribution.",
|
||||
canonicalPath: "/qr-code-for-marketing-campaigns",
|
||||
});
|
||||
|
||||
export default function QRCodeForMarketingCampaignsPage() {
|
||||
return (
|
||||
<UseCasePageTemplate
|
||||
title="QR Codes for Marketing Campaigns"
|
||||
description="Plan QR codes for marketing campaigns around placement tracking, changing destinations, and offline-to-online attribution."
|
||||
eyebrow="Campaign Workflows"
|
||||
intro="Marketing campaign QR codes work best when the code on the printed asset stays stable while the destination and attribution model can evolve with the campaign."
|
||||
pageType="commercial"
|
||||
cluster="marketing-campaigns"
|
||||
useCase="marketing-campaigns"
|
||||
breadcrumbs={[
|
||||
{ name: "Home", url: "/" },
|
||||
{
|
||||
name: "QR Codes for Marketing Campaigns",
|
||||
url: "/qr-code-for-marketing-campaigns",
|
||||
},
|
||||
]}
|
||||
answer="A campaign QR code should do more than open a page. It should help you compare placements, update the destination when the offer changes, and route offline traffic into a measurable funnel."
|
||||
whenToUse={[
|
||||
"You run flyers, posters, packaging inserts, or event signage with campaign-specific CTA copy.",
|
||||
"You want to compare placements or creatives instead of treating every scan as generic traffic.",
|
||||
"Your destination may change during the life of the printed campaign.",
|
||||
]}
|
||||
comparisonItems={[
|
||||
{ label: "Offer updates", text: "New print required", value: true },
|
||||
{ label: "Placement attribution", text: "Often manual", value: true },
|
||||
{ label: "Creative testing", text: "Hard to manage", value: true },
|
||||
]}
|
||||
howToSteps={[
|
||||
"Create campaign QR flows around one clear action and one named placement context.",
|
||||
"Use dynamic destinations or tagged URLs so the print stays usable when the offer changes.",
|
||||
"Measure scans with a clean CTA path into signup, lead capture, or campaign landing pages.",
|
||||
]}
|
||||
primaryCta={{
|
||||
href: "/dynamic-qr-code-generator",
|
||||
label: "Create a trackable campaign QR",
|
||||
}}
|
||||
secondaryCta={{
|
||||
href: "/use-cases",
|
||||
label: "Browse use-case workflows",
|
||||
}}
|
||||
workflowTitle="What strong campaign QR workflows look like"
|
||||
workflowIntro="Campaign QR strategy becomes more useful when creative, placement, and destination are treated as a system rather than a single link printed everywhere."
|
||||
workflowCards={[
|
||||
{
|
||||
title: "Placement-aware routing",
|
||||
description: "Keep banner, flyer, packaging, and in-store placements comparable by using distinct destinations or campaign tags.",
|
||||
},
|
||||
{
|
||||
title: "Post-print flexibility",
|
||||
description: "Adjust the landing page, offer, or CTA destination after print when the campaign learns something or needs a fast update.",
|
||||
},
|
||||
{
|
||||
title: "Measurement-ready handoff",
|
||||
description: "Push campaign scans toward signup, booking, or lead-gen paths so the QR is tied to a business outcome instead of a vanity click.",
|
||||
},
|
||||
]}
|
||||
checklistTitle="Campaign QR checklist"
|
||||
checklist={[
|
||||
"Match each QR code to one campaign purpose and one primary CTA.",
|
||||
"Differentiate placements with clean naming or URL tagging before the assets go to print.",
|
||||
"Use a destination you can update when the promotion, offer, or landing page changes.",
|
||||
"Link the campaign flow back to a measured CTA path instead of stopping at raw scan counts.",
|
||||
]}
|
||||
supportLinks={[
|
||||
{
|
||||
href: "/qr-code-tracking",
|
||||
title: "QR Code Tracking",
|
||||
description: "Use when the real priority is measuring placement and scanner context.",
|
||||
},
|
||||
{
|
||||
href: "/custom-qr-code-generator",
|
||||
title: "Custom QR Code Generator",
|
||||
description: "Useful when brand fit and print creative need more control.",
|
||||
},
|
||||
{
|
||||
href: "/blog/utm-parameter-qr-codes",
|
||||
title: "UTM Parameters with QR Codes",
|
||||
description: "Support article for placement naming and campaign attribution strategy.",
|
||||
},
|
||||
]}
|
||||
faq={[
|
||||
{
|
||||
question: "Why use QR codes in marketing campaigns?",
|
||||
answer: "Campaign QR codes help move offline audiences into a measurable online path. They are most useful when the destination and tracking setup are planned before the assets go live.",
|
||||
},
|
||||
{
|
||||
question: "Should campaign QR codes be dynamic?",
|
||||
answer: "Yes, when the destination, offer, or campaign landing page may change after print. That avoids replacing materials just because the target page changes.",
|
||||
},
|
||||
{
|
||||
question: "How do I track different QR placements in one campaign?",
|
||||
answer: "Use distinct destinations or tagged URLs for each placement so flyers, posters, booth signs, and packaging inserts can be compared cleanly.",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
import React from 'react';
|
||||
import type { Metadata } from 'next';
|
||||
import Link from 'next/link';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import SeoJsonLd from '@/components/SeoJsonLd';
|
||||
import Breadcrumbs, { BreadcrumbItem } from '@/components/Breadcrumbs';
|
||||
import { breadcrumbSchema } from '@/lib/schema';
|
||||
import { GrowthLinksSection } from '@/components/marketing/GrowthLinksSection';
|
||||
import { MarketingPageTracker, TrackedCtaLink } from '@/components/marketing/MarketingAnalytics';
|
||||
import { featuredUseCases } from '@/lib/growth-pages';
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
@@ -164,15 +166,43 @@ export default function QRCodeTrackingPage() {
|
||||
],
|
||||
};
|
||||
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'QR Code Tracking', url: '/qr-code-tracking' },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<div className="min-h-screen bg-white">
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: 'Home', url: '/' },
|
||||
{ name: 'QR Code Tracking', url: '/qr-code-tracking' },
|
||||
];
|
||||
|
||||
const relatedUseCaseLinks = [
|
||||
{
|
||||
href: featuredUseCases[2].href,
|
||||
title: featuredUseCases[2].title,
|
||||
description: featuredUseCases[2].summary,
|
||||
ctaLabel: featuredUseCases[2].ctaLabel,
|
||||
},
|
||||
{
|
||||
href: '/qr-code-for-marketing-campaigns',
|
||||
title: 'QR Codes for Marketing Campaigns',
|
||||
description: 'Map scans to campaign placements, creative tests, and offline-to-online attribution.',
|
||||
ctaLabel: 'Create a trackable campaign QR',
|
||||
},
|
||||
{
|
||||
href: featuredUseCases[0].href,
|
||||
title: featuredUseCases[0].title,
|
||||
description: featuredUseCases[0].summary,
|
||||
ctaLabel: featuredUseCases[0].ctaLabel,
|
||||
},
|
||||
{
|
||||
href: '/use-cases',
|
||||
title: 'Explore the use-case hub',
|
||||
description: 'Browse the first commercial workflows built around dynamic updates and measurable scans.',
|
||||
ctaLabel: 'Explore QR code use cases',
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[softwareSchema, howToSchema, breadcrumbSchema(breadcrumbItems)]} />
|
||||
<MarketingPageTracker pageType="commercial" cluster="qr-tracking" />
|
||||
<div className="min-h-screen bg-white">
|
||||
{/* Hero Section */}
|
||||
<section className="relative overflow-hidden bg-gradient-to-br from-blue-50 via-white to-purple-50 py-20">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-7xl">
|
||||
@@ -190,20 +220,20 @@ export default function QRCodeTrackingPage() {
|
||||
|
||||
<p className="text-xl text-gray-600 leading-relaxed">
|
||||
Monitor your QR code performance in real-time. Get detailed insights on location, device, time, and user behavior. Make data-driven decisions with our free tracking software.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<Link href="/signup">
|
||||
<Button size="lg" className="text-lg px-8 py-4 w-full sm:w-auto">
|
||||
Start Tracking Free
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/signup">
|
||||
<Button variant="outline" size="lg" className="text-lg px-8 py-4 w-full sm:w-auto">
|
||||
Create Trackable QR Code
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<TrackedCtaLink href="/signup" ctaLabel="Start Tracking Free" ctaLocation="hero_primary" pageType="commercial" cluster="qr-tracking">
|
||||
<Button size="lg" className="text-lg px-8 py-4 w-full sm:w-auto">
|
||||
Start Tracking Free
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
<TrackedCtaLink href="/signup" ctaLabel="Create Trackable QR Code" ctaLocation="hero_secondary" pageType="commercial" cluster="qr-tracking">
|
||||
<Button variant="outline" size="lg" className="text-lg px-8 py-4 w-full sm:w-auto">
|
||||
Create Trackable QR Code
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-6 text-sm text-gray-600">
|
||||
<div className="flex items-center space-x-2">
|
||||
@@ -212,13 +242,13 @@ export default function QRCodeTrackingPage() {
|
||||
</svg>
|
||||
<span>No credit card required</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<svg className="w-5 h-5 text-green-500" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span>Unlimited scans</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<svg className="w-5 h-5 text-green-500" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span>Placement-ready reports</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Analytics Preview */}
|
||||
@@ -227,20 +257,20 @@ export default function QRCodeTrackingPage() {
|
||||
<h3 className="font-semibold text-lg mb-4">Live Analytics Dashboard</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="flex justify-between items-center pb-3 border-b">
|
||||
<span className="text-gray-600">Total Scans</span>
|
||||
<span className="text-2xl font-bold text-primary-600">12,547</span>
|
||||
<span className="text-gray-600">Placement view</span>
|
||||
<span className="text-base font-semibold text-primary-600">Flyer vs booth vs table card</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center pb-3 border-b">
|
||||
<span className="text-gray-600">Unique Users</span>
|
||||
<span className="text-2xl font-bold text-primary-600">8,392</span>
|
||||
<span className="text-gray-600">Time trend</span>
|
||||
<span className="text-base font-semibold text-primary-600">Lunch, event day, or campaign burst</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center pb-3 border-b">
|
||||
<span className="text-gray-600">Top Location</span>
|
||||
<span className="font-semibold">🇩🇪 Germany</span>
|
||||
<span className="text-gray-600">Location context</span>
|
||||
<span className="font-semibold">Region and city level view</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-600">Top Device</span>
|
||||
<span className="font-semibold">📱 iPhone</span>
|
||||
<span className="text-gray-600">Device context</span>
|
||||
<span className="font-semibold">Phone, desktop, and scan mix</span>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
@@ -318,9 +348,9 @@ export default function QRCodeTrackingPage() {
|
||||
</section>
|
||||
|
||||
{/* Comparison Table */}
|
||||
<section className="py-20 bg-gray-50">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-5xl">
|
||||
<div className="text-center mb-16">
|
||||
<section className="py-20 bg-gray-50">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-5xl">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-4xl font-bold text-gray-900 mb-4">
|
||||
QR Master vs Free Tools
|
||||
</h2>
|
||||
@@ -364,33 +394,42 @@ export default function QRCodeTrackingPage() {
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20 bg-gradient-to-r from-primary-600 to-purple-600 text-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-4xl text-center">
|
||||
<h2 className="text-4xl font-bold mb-6">
|
||||
Start Tracking Your QR Codes Today
|
||||
</h2>
|
||||
<p className="text-xl mb-8 text-primary-100">
|
||||
Join thousands of businesses using QR Master to track and optimize their QR code campaigns
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<Link href="/signup">
|
||||
<Button size="lg" variant="secondary" className="text-lg px-8 py-4 w-full sm:w-auto bg-white text-primary-600 hover:bg-gray-100">
|
||||
Create Free Account
|
||||
</Button>
|
||||
</Link>
|
||||
<Link href="/pricing">
|
||||
<Button size="lg" variant="outline" className="text-lg px-8 py-4 w-full sm:w-auto border-white text-white hover:bg-white/10">
|
||||
View Pricing
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</Card>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<GrowthLinksSection
|
||||
eyebrow="Tracking-led workflows"
|
||||
title="Where scan visibility matters most"
|
||||
description="These are the workflows where scan context, placement comparison, and destination flexibility make QR tracking materially more useful."
|
||||
links={relatedUseCaseLinks}
|
||||
pageType="commercial"
|
||||
cluster="qr-tracking"
|
||||
/>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-20 bg-gradient-to-r from-primary-600 to-purple-600 text-white">
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8 max-w-4xl text-center">
|
||||
<h2 className="text-4xl font-bold mb-6">
|
||||
Start Tracking Your QR Codes Today
|
||||
</h2>
|
||||
<p className="text-xl mb-8 text-primary-100">
|
||||
Measure scans with enough context to improve the next placement, campaign, or printed workflow.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<TrackedCtaLink href="/signup" ctaLabel="Create Free Account" ctaLocation="footer_primary" pageType="commercial" cluster="qr-tracking">
|
||||
<Button size="lg" variant="secondary" className="text-lg px-8 py-4 w-full sm:w-auto bg-white text-primary-600 hover:bg-gray-100">
|
||||
Create Free Account
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
<TrackedCtaLink href="/pricing" ctaLabel="View Pricing" ctaLocation="footer_secondary" pageType="commercial" cluster="qr-tracking">
|
||||
<Button size="lg" variant="outline" className="text-lg px-8 py-4 w-full sm:w-auto border-white text-white hover:bg-white/10">
|
||||
View Pricing
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
78
src/app/(main)/(marketing)/use-cases/[slug]/page.tsx
Normal file
78
src/app/(main)/(marketing)/use-cases/[slug]/page.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import { notFound } from "next/navigation";
|
||||
|
||||
import {
|
||||
buildUseCaseMetadata,
|
||||
UseCasePageTemplate,
|
||||
} from "@/components/marketing/UseCasePageTemplate";
|
||||
import {
|
||||
featuredUseCases,
|
||||
getUseCasePage,
|
||||
} from "@/lib/growth-pages";
|
||||
|
||||
export function generateStaticParams() {
|
||||
return featuredUseCases.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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
303
src/app/(main)/(marketing)/use-cases/page.tsx
Normal file
303
src/app/(main)/(marketing)/use-cases/page.tsx
Normal file
@@ -0,0 +1,303 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
import Link from "next/link";
|
||||
import {
|
||||
ArrowRight,
|
||||
Compass,
|
||||
LibraryBig,
|
||||
Link2,
|
||||
Route,
|
||||
Sparkles,
|
||||
} from "lucide-react";
|
||||
|
||||
import Breadcrumbs, { BreadcrumbItem } from "@/components/Breadcrumbs";
|
||||
import SeoJsonLd from "@/components/SeoJsonLd";
|
||||
import {
|
||||
MarketingPageTracker,
|
||||
TrackedCtaLink,
|
||||
} from "@/components/marketing/MarketingAnalytics";
|
||||
import { Button } from "@/components/ui/Button";
|
||||
import { Card } from "@/components/ui/Card";
|
||||
import {
|
||||
commercialPages,
|
||||
featuredUseCases,
|
||||
supportResources,
|
||||
upcomingUseCaseIdeas,
|
||||
} from "@/lib/growth-pages";
|
||||
import { breadcrumbSchema } from "@/lib/schema";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: "QR Code Use Cases for Business | QR Master",
|
||||
},
|
||||
description:
|
||||
"Explore QR code use cases for restaurants, events, business cards, and campaign workflows built around dynamic updates and tracking.",
|
||||
alternates: {
|
||||
canonical: "https://www.qrmaster.net/use-cases",
|
||||
languages: {
|
||||
"x-default": "https://www.qrmaster.net/use-cases",
|
||||
en: "https://www.qrmaster.net/use-cases",
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: "QR Code Use Cases for Business | QR Master",
|
||||
description:
|
||||
"Explore QR code use cases for restaurants, events, business cards, and campaign workflows built around dynamic updates and tracking.",
|
||||
url: "https://www.qrmaster.net/use-cases",
|
||||
type: "website",
|
||||
images: ["/og-image.png"],
|
||||
},
|
||||
twitter: {
|
||||
title: "QR Code Use Cases for Business | QR Master",
|
||||
description:
|
||||
"Explore QR code use cases for restaurants, events, business cards, and campaign workflows built around dynamic updates and tracking.",
|
||||
},
|
||||
};
|
||||
|
||||
export default function UseCasesHubPage() {
|
||||
const breadcrumbItems: BreadcrumbItem[] = [
|
||||
{ name: "Home", url: "/" },
|
||||
{ name: "Use Cases", url: "/use-cases" },
|
||||
];
|
||||
|
||||
return (
|
||||
<>
|
||||
<SeoJsonLd data={[breadcrumbSchema(breadcrumbItems)]} />
|
||||
<MarketingPageTracker pageType="use_case_hub" cluster="all-use-cases" />
|
||||
|
||||
<div className="min-h-screen bg-white">
|
||||
<section className="relative overflow-hidden bg-gradient-to-br from-slate-950 via-blue-950 to-cyan-950 text-white">
|
||||
<div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(125,211,252,0.18),transparent_34%),radial-gradient(circle_at_right,rgba(255,255,255,0.06),transparent_28%)]" />
|
||||
<div className="relative container mx-auto max-w-7xl px-4 py-20 sm:px-6 lg:px-8">
|
||||
<Breadcrumbs
|
||||
items={breadcrumbItems}
|
||||
className="[&_a]:text-blue-100/80 [&_a:hover]:text-white [&_span]:text-blue-100/80 [&_[aria-current=page]]:text-white"
|
||||
/>
|
||||
|
||||
<div className="grid gap-12 lg:grid-cols-[minmax(0,1.2fr)_minmax(320px,0.8fr)] lg:items-center">
|
||||
<div className="space-y-8">
|
||||
<div className="inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/10 px-4 py-2 text-sm font-semibold text-cyan-100 shadow-lg shadow-cyan-950/30 backdrop-blur">
|
||||
<Sparkles className="h-4 w-4" />
|
||||
<span>Commercial use-case hub</span>
|
||||
</div>
|
||||
|
||||
<div className="space-y-5">
|
||||
<h1 className="max-w-4xl text-4xl font-bold tracking-tight text-white md:text-5xl lg:text-6xl">
|
||||
QR code use cases that fit real business workflows
|
||||
</h1>
|
||||
<p className="max-w-3xl text-lg leading-8 text-blue-50/88 md:text-xl">
|
||||
This hub focuses on workflows where dynamic updates and
|
||||
measurement matter. It is not a list of random QR ideas. It
|
||||
is the commercial layer between QR Master's product pages,
|
||||
tools, and editorial content.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-3 text-sm text-blue-50/80 sm:grid-cols-2">
|
||||
{[
|
||||
"Use-case pages map back to a clear commercial parent.",
|
||||
"Each workflow is written for practical deployment, not filler traffic.",
|
||||
"Support resources reinforce the wedge around dynamic and trackable QR flows.",
|
||||
"The next cluster expansion will build on measurable routing and internal links.",
|
||||
].map((line) => (
|
||||
<div
|
||||
key={line}
|
||||
className="flex items-start gap-3 rounded-2xl border border-white/10 bg-white/5 px-4 py-3 backdrop-blur-sm"
|
||||
>
|
||||
<Route className="mt-0.5 h-4 w-4 shrink-0 text-cyan-300" />
|
||||
<span>{line}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-4 sm:flex-row">
|
||||
<TrackedCtaLink
|
||||
href={featuredUseCases[0].href}
|
||||
ctaLabel="Explore restaurant menu QR codes"
|
||||
ctaLocation="hero_primary"
|
||||
pageType="use_case_hub"
|
||||
cluster="all-use-cases"
|
||||
>
|
||||
<Button size="lg" className="w-full bg-white px-8 py-4 text-slate-950 hover:bg-slate-100 sm:w-auto">
|
||||
Explore featured workflows
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
|
||||
<TrackedCtaLink
|
||||
href="/qr-code-for-marketing-campaigns"
|
||||
ctaLabel="View marketing campaign QR page"
|
||||
ctaLocation="hero_secondary"
|
||||
pageType="use_case_hub"
|
||||
cluster="all-use-cases"
|
||||
>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="w-full border-white/30 bg-white/5 px-8 py-4 text-white hover:bg-white/10 sm:w-auto"
|
||||
>
|
||||
See campaign workflows
|
||||
</Button>
|
||||
</TrackedCtaLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Card className="border-white/10 bg-white/10 p-8 text-white shadow-2xl shadow-slate-950/30 backdrop-blur">
|
||||
<div className="space-y-5">
|
||||
<div className="flex items-center gap-3">
|
||||
<Compass className="h-5 w-5 text-cyan-300" />
|
||||
<h2 className="text-2xl font-bold">How to use this hub</h2>
|
||||
</div>
|
||||
<div className="space-y-4 text-sm leading-6 text-blue-50/82">
|
||||
<p>
|
||||
Start with the workflow problem, not the QR format. If the
|
||||
printed code needs to survive destination changes or you
|
||||
need proof of performance, begin with the use case that
|
||||
matches that job.
|
||||
</p>
|
||||
<p>
|
||||
Each page below links back to the best product parent,
|
||||
forward to related workflows, and sideways to educational
|
||||
resources that help you deploy the QR well.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
</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="mb-10 max-w-3xl">
|
||||
<div className="text-sm font-semibold uppercase tracking-[0.22em] text-blue-700">
|
||||
Featured use cases
|
||||
</div>
|
||||
<h2 className="mt-3 text-3xl font-bold text-slate-900">
|
||||
First workflows in the growth rollout
|
||||
</h2>
|
||||
<p className="mt-4 text-lg leading-8 text-slate-600">
|
||||
These are the first routes worth surfacing because they connect
|
||||
cleanly to QR Master's strongest product angles and existing
|
||||
supporting content.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 lg:grid-cols-3">
|
||||
{featuredUseCases.map((page) => (
|
||||
<Link key={page.slug} href={page.href} className="group block">
|
||||
<Card className="flex h-full flex-col rounded-3xl border-slate-200 bg-white p-7 shadow-sm transition-all hover:-translate-y-1 hover:shadow-lg">
|
||||
<div className="text-sm font-semibold uppercase tracking-[0.18em] text-blue-700">
|
||||
{page.cluster}
|
||||
</div>
|
||||
<h3 className="mt-4 text-2xl font-bold text-slate-900">
|
||||
{page.title}
|
||||
</h3>
|
||||
<p className="mt-4 flex-1 text-base leading-7 text-slate-600">
|
||||
{page.summary}
|
||||
</p>
|
||||
<div className="mt-6 flex items-center justify-between rounded-2xl bg-slate-50 px-4 py-3 text-sm text-slate-600">
|
||||
<span>Primary parent: {page.parentTitle}</span>
|
||||
<ArrowRight className="h-4 w-4 text-blue-700 transition-transform group-hover:translate-x-1" />
|
||||
</div>
|
||||
</Card>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="bg-slate-50 py-16">
|
||||
<div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid gap-8 lg:grid-cols-[minmax(0,1fr)_minmax(0,0.95fr)]">
|
||||
<Card className="rounded-3xl border-slate-200 bg-white p-8 shadow-sm">
|
||||
<div className="flex items-center gap-3">
|
||||
<LibraryBig className="h-5 w-5 text-blue-700" />
|
||||
<h2 className="text-2xl font-bold text-slate-900">
|
||||
Commercial pages that anchor the hub
|
||||
</h2>
|
||||
</div>
|
||||
<div className="mt-6 grid gap-4 md:grid-cols-2">
|
||||
{commercialPages.map((page) => (
|
||||
<Link
|
||||
key={page.href}
|
||||
href={page.href}
|
||||
className="rounded-2xl border border-slate-200 p-4 transition-colors hover:border-blue-200 hover:bg-blue-50/60"
|
||||
>
|
||||
<div className={`h-1.5 rounded-full bg-gradient-to-r ${page.accent}`} />
|
||||
<div className="mt-4 text-lg font-semibold text-slate-900">
|
||||
{page.title}
|
||||
</div>
|
||||
<p className="mt-2 text-sm leading-6 text-slate-600">
|
||||
{page.description}
|
||||
</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card className="rounded-3xl border-slate-200 bg-slate-950 p-8 text-white shadow-xl shadow-slate-200">
|
||||
<div className="flex items-center gap-3">
|
||||
<Link2 className="h-5 w-5 text-cyan-300" />
|
||||
<h2 className="text-2xl font-bold">Support resources</h2>
|
||||
</div>
|
||||
<div className="mt-6 space-y-4">
|
||||
{supportResources.map((resource) => (
|
||||
<Link
|
||||
key={resource.href}
|
||||
href={resource.href}
|
||||
className="block rounded-2xl border border-white/10 bg-white/5 p-4 transition-colors hover:bg-white/10"
|
||||
>
|
||||
<div className="text-lg font-semibold text-white">
|
||||
{resource.title}
|
||||
</div>
|
||||
<p className="mt-2 text-sm leading-6 text-blue-50/78">
|
||||
{resource.description}
|
||||
</p>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</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="mb-10 max-w-3xl">
|
||||
<div className="text-sm font-semibold uppercase tracking-[0.22em] text-blue-700">
|
||||
Next cluster candidates
|
||||
</div>
|
||||
<h2 className="mt-3 text-3xl font-bold text-slate-900">
|
||||
What follows after the first use-case wave
|
||||
</h2>
|
||||
<p className="mt-4 text-lg leading-8 text-slate-600">
|
||||
These are not published use-case routes yet. They are the next
|
||||
practical cluster expansions once the first hub and CTA layer are
|
||||
established.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-3">
|
||||
{upcomingUseCaseIdeas.map((item) => (
|
||||
<Card
|
||||
key={item.title}
|
||||
className="rounded-3xl border-dashed border-slate-300 bg-slate-50 p-7"
|
||||
>
|
||||
<div className="text-xl font-semibold text-slate-900">
|
||||
{item.title}
|
||||
</div>
|
||||
<p className="mt-3 text-base leading-7 text-slate-600">
|
||||
{item.description}
|
||||
</p>
|
||||
<div className="mt-5 text-sm font-semibold text-blue-700">
|
||||
Anchored by {item.href.replace("/", "")}
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user