diff --git a/scripts/debug-hang.ts b/scripts/debug-hang.ts new file mode 100644 index 0000000..c28013e --- /dev/null +++ b/scripts/debug-hang.ts @@ -0,0 +1,32 @@ + +console.log('1. Starting debug script...'); + +try { + console.log('2. Importing fs...'); + const fs = require('fs'); + console.log(' fs imported.'); + + console.log('3. Importing path...'); + const path = require('path'); + console.log(' path imported.'); + + console.log('4. Importing googleapis...'); + const { google } = require('googleapis'); + console.log(' googleapis imported.'); + + console.log('5. Importing ../src/lib/indexnow...'); + const indexnow = require('../src/lib/indexnow'); + console.log(' indexnow imported.'); + console.log(' Keys:', Object.keys(indexnow)); + + if (indexnow.getAllIndexableUrls) { + console.log('6. Calling getAllIndexableUrls...'); + const urls = indexnow.getAllIndexableUrls(); + console.log(` Got ${urls.length} URLs.`); + } + + console.log('7. Done!'); + +} catch (err) { + console.error('ERROR during import:', err); +} diff --git a/src/app/(main)/(marketing)/contact/page.tsx b/src/app/(main)/(marketing)/contact/page.tsx new file mode 100644 index 0000000..b0c27d7 --- /dev/null +++ b/src/app/(main)/(marketing)/contact/page.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import Link from 'next/link'; +import { ObfuscatedMailto } from '@/components/ui/ObfuscatedMailto'; +import { Metadata } from 'next'; + +export const metadata: Metadata = { + title: 'Contact Us | QR Master', + description: 'Get in touch with QR Master support.', +}; + +export default function ContactPage() { + return ( +
+
+
+

+ Contact Us +

+

+ We are here to help. +

+
+
+
+ + {/* Email Section */} +
+

+ Email Support +

+
+

For any inquiries, please email us at:

+
+ +
+
+
+ + {/* Address Section */} +
+

+ Business Address +

+
+

1001 Blucher Street

+

Corpus Christi, Texas

+
+
+ + {/* Hours Section */} +
+

+ Support Hours +

+

+ Monday - Friday, 9:00 AM - 5:00 PM CET +

+
+ + {/* Useful Links */} +
+

+ Useful Links +

+
    +
  • + + Check our FAQ first → + +
  • +
  • + + Back to Home → + +
  • +
+
+ +
+
+
+
+ ); +} diff --git a/src/app/(main)/(marketing)/cookie-policy/page.tsx b/src/app/(main)/(marketing)/cookie-policy/page.tsx new file mode 100644 index 0000000..f0467e3 --- /dev/null +++ b/src/app/(main)/(marketing)/cookie-policy/page.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import Link from 'next/link'; + +export const metadata = { + title: 'Cookie Policy | QR Master', + description: 'Information about how QR Master uses cookies.', + openGraph: { + title: 'Cookie Policy | QR Master', + url: 'https://www.qrmaster.net/cookie-policy', + type: 'website', + }, +}; + +export default function CookiePolicyPage() { + return ( +
+
+
+ + ← Back to Home + +
+ +

Cookie Policy

+

Last updated: January 2025

+ +
+
+

What Are Cookies

+

+ As is common practice with almost all professional websites, this site uses cookies, which are tiny files that are downloaded to your computer, to improve your experience. +

+
+ +
+

How We Use Cookies

+
    +
  • Essential Cookies: Required for the website to function (e.g., login, session management).
  • +
  • Analytics Cookies (Optional): We use tools like PostHog to understand how you use the site and improve it. These are only set with your consent.
  • +
  • Functionality Cookies: To remember your preferences.
  • +
+
+ +
+

Disabling Cookies

+

+ You can prevent the setting of cookies by adjusting the settings on your browser. Be aware that disabling cookies will affect the functionality of this and many other websites that you visit. Disabling essential cookies will result in disabling certain functionality and features of this site (like logging in). +

+
+
+
+
+ ); +} diff --git a/src/app/(main)/(marketing)/dynamic-qr-code-generator/page.tsx b/src/app/(main)/(marketing)/dynamic-qr-code-generator/page.tsx index 426c353..367c08b 100644 --- a/src/app/(main)/(marketing)/dynamic-qr-code-generator/page.tsx +++ b/src/app/(main)/(marketing)/dynamic-qr-code-generator/page.tsx @@ -6,6 +6,7 @@ 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'; export const metadata: Metadata = { title: { @@ -326,6 +327,34 @@ export default function DynamicQRCodeGeneratorPage() { + {/* Answer First Block (SEO/AEO) */} +
+ +
+ {/* Static vs Dynamic */}
diff --git a/src/app/(main)/(marketing)/faq/page.tsx b/src/app/(main)/(marketing)/faq/page.tsx index 4cd0417..b3561c3 100644 --- a/src/app/(main)/(marketing)/faq/page.tsx +++ b/src/app/(main)/(marketing)/faq/page.tsx @@ -51,61 +51,141 @@ export async function generateMetadata(): Promise { }; } -const faqs = [ +import Link from 'next/link'; + +// Extended type for UI with Rich Text support +type FAQItemWithRichText = { + question: string; + answer: string; // Plain text for Schema + answerRich?: React.ReactNode; // JSX for UI +}; + +const faqs: FAQItemWithRichText[] = [ { question: 'What is a dynamic QR code?', - answer: 'A dynamic QR code allows you to change the destination URL after the code has been created and printed. Unlike static QR codes, dynamic codes redirect through a short URL that you control, enabling real-time updates, scan analytics, and campaign tracking without reprinting the code.', + answer: 'A dynamic QR code points to a redirect URL, so you can change the final destination later without reprinting. Key benefits: Update the destination anytime, Track scans (time, device, location), Pause/disable campaigns.', + answerRich: ( + <> + A dynamic QR code points to a redirect URL, so you can change the final destination later without reprinting. +

+ Key benefits: +
    +
  • Update the destination anytime
  • +
  • Track scans (time, device, location) via Analytics
  • +
  • Pause/disable campaigns without changing the printed code
  • +
+ + ), }, { question: 'How do I track QR scans?', - answer: 'QR Master provides a comprehensive analytics dashboard that tracks every scan in real-time. You can monitor scan rates, geographic locations, device types, timestamps, and user behavior. Enable UTM parameters to integrate with Google Analytics for advanced campaign tracking and conversion attribution.', + answer: 'QR Master tracks scan events in real-time via the short URL redirect. Metrics included: Total and unique scans, Device type, Geographic location, and Time of day.', + answerRich: ( + <> + QR Master tracks scan events in real-time via the short URL redirect. +

+ Metrics included: +
    +
  • Total and unique scans
  • +
  • Device type (iOS, Android, Desktop)
  • +
  • Geographic location (Country, City)
  • +
  • Time of day
  • +
+
+ Learn more about Tracking → + + ), }, { - question: 'What security features does QR Master offer?', - answer: 'QR Master employs enterprise-grade security including SSL encryption, link validation to prevent malicious redirects, fraud detection, and GDPR-compliant data handling. All scan analytics are stored securely and access is protected with multi-factor authentication for business accounts.', + question: 'What security measures are in place?', + answer: 'We prioritize data security through standard industry practices. Security features: HTTPS/TLS encryption, Automated link validation, and Rate limiting.', + answerRich: ( + <> + We prioritize data security through standard industry practices. +

+ Security features: +
    +
  • HTTPS/TLS encryption for all connections
  • +
  • Automated link validation to prevent malicious redirects
  • +
  • Rate limiting to prevent abuse
  • +
+ + ), }, { - question: 'Can I generate bulk QR codes for print?', - answer: 'Yes. Our bulk QR generation tool allows you to create thousands of QR codes at once by uploading a CSV file. Each code can be customized with unique URLs, UTM parameters, and branding. Download print-ready files in SVG, PNG, or PDF formats optimized for high-resolution printing.', + question: 'Bulk QR codes: Print, Marketing, and API?', + answer: 'You can generate thousands of codes via CSV upload or API for scalable campaigns. Features: CSV Upload (1,000+ codes), Customization, and API access.', + answerRich: ( + <> + You can generate thousands of codes via CSV upload or API for scalable campaigns. +

+ Features: +
    +
  • CSV Upload: Create up to 1,000 codes at once (Bulk Generator)
  • +
  • Customization: Apply branding to all batch codes
  • +
  • API: Programmatic generation for internal systems
  • +
+ + ), }, { - question: 'How do I brand my QR codes?', - answer: 'QR Master offers customization options including custom colors, corner styles, and pattern designs. Branded QR codes maintain scannability while matching your brand identity. Choose your color palette and preview designs before downloading.', + question: 'What are the best practices for printing QR codes?', + answer: 'Ensure high scannability by following these rules: Minimum size 2x2 cm, High contrast (dark on light), Vector formats (SVG/EPS) for large print, and maintain a quiet zone border.', + answerRich: ( + <> + Ensure high scannability by following these rules: +

+ Print Guidelines: +
    +
  • Size: Minimum 2x2 cm (0.8x0.8 inch) for close range
  • +
  • Format: Use SVG/EPS (Vector) for professional print quality
  • +
  • Contrast: Always use dark foreground on light background
  • +
  • Quiet Zone: Leave a margin around the code
  • +
+ + ), }, { - question: 'Is scan analytics GDPR compliant?', - answer: 'Yes. All QR Master analytics are fully GDPR compliant. We collect only necessary data, provide transparent privacy policies, allow users to opt out, and store data securely in EU-compliant data centers. You maintain full control over data retention and deletion.', + question: 'Is the service GDPR aligned?', + answer: 'Yes, we minimize data collection to ensure privacy compliance. Privacy measures: IP anonymization, No PII storage, and EU-based servers.', + answerRich: ( + <> + Yes, we minimize data collection to ensure privacy compliance. +

+ Privacy measures: +
    +
  • IP addresses are anonymized or hashed
  • +
  • No personal data (PII) is stored from scanners
  • +
  • Servers located in EU regions (for EU customers)
  • +
+
+ Read Privacy Policy → + + ), }, { - question: 'Can QR Master track campaigns with UTM?', - answer: 'Absolutely. QR Master supports UTM parameter integration for all dynamic QR codes. Automatically append source, medium, campaign, term, and content parameters to track QR performance in Google Analytics, Adobe Analytics, and other marketing platforms. UTM tracking enables multi-channel attribution and ROI measurement.', - }, - { - question: 'Difference between static and dynamic QR codes?', - answer: 'Static QR codes encode the destination URL directly in the code pattern and cannot be changed after creation. Dynamic QR codes use a short redirect URL, allowing you to update destinations, track scans, enable/disable codes, and gather analytics—all without reprinting. Dynamic codes are essential for professional marketing campaigns.', - }, - { - question: 'How are QR codes used for events?', - answer: 'QR codes streamline event check-ins, ticket validation, attendee tracking, and engagement measurement. Generate unique codes for each ticket, track scan times and locations, enable contactless entry, and analyze attendee behavior. Event organizers use QR analytics to measure session popularity and optimize future events.', - }, - { - question: 'Can I make QR codes for business cards?', - answer: 'Yes. QR codes on business cards provide instant contact sharing via vCard format, link to your portfolio or LinkedIn profile, and track networking effectiveness. Use branded QR codes that match your card design, and leverage scan analytics to see how many contacts engage and when they follow up.', - }, - { - question: 'How do I use QR codes for bulk marketing?', - answer: 'Bulk QR codes enable scalable campaigns across print ads, packaging, direct mail, and retail displays. Generate thousands of codes with unique tracking URLs, distribute them across channels, and use analytics to measure which placements drive the highest engagement. Bulk generation supports CSV upload, API integration, and automated workflows.', - }, - { - question: 'Is API access available for bulk QR generation?', - answer: 'Yes. QR Master offers a developer-friendly REST API for programmatic QR code generation, URL management, and analytics retrieval. Integrate QR creation into your CRM, marketing automation platform, or e-commerce system. API access is included in Business plans and supports bulk operations, webhooks, and real-time updates.', + question: 'Dynamic vs Static QR Codes?', + answer: 'Static codes are fixed forever; Dynamic codes can be edited and tracked. Comparison: Static (free, permanent, no tracking) vs Dynamic (editable, analytics, campaign logic).', + answerRich: ( + <> + Static codes are fixed forever; Dynamic codes can be edited and tracked. +

+ Comparison: +
    +
  • Static: content embedded directly, no tracking, free forever
  • +
  • Dynamic: redirect link, editable destination, scan analytics
  • +
+
+ Create Dynamic QR → + + ), }, ]; export default function FAQPage() { return ( <> - + ({ question, answer })))} />
@@ -113,9 +193,12 @@ export default function FAQPage() {

Frequently Asked Questions

-

+

Everything you need to know about dynamic QR codes, security, analytics, bulk generation, events, and print quality.

+

+ Last updated: January 25, 2025 +

@@ -125,9 +208,9 @@ export default function FAQPage() {

{faq.question}

-

- {faq.answer} -

+
+ {faq.answerRich || faq.answer} +
))} diff --git a/src/app/(main)/(marketing)/page.tsx b/src/app/(main)/(marketing)/page.tsx index 6fd33e8..2cd660e 100644 --- a/src/app/(main)/(marketing)/page.tsx +++ b/src/app/(main)/(marketing)/page.tsx @@ -54,7 +54,7 @@ export async function generateMetadata(): Promise { export default function HomePage() { return ( <> - + {/* Server-rendered SEO content for crawlers */}
diff --git a/src/app/(main)/features/page.tsx b/src/app/(main)/features/page.tsx index 734ef81..91344fe 100644 --- a/src/app/(main)/features/page.tsx +++ b/src/app/(main)/features/page.tsx @@ -12,6 +12,9 @@ export const metadata: Metadata = { alternates: { canonical: 'https://www.qrmaster.net/features', }, + openGraph: { + url: 'https://www.qrmaster.net/features', + }, }; export default function FeaturesPage() { diff --git a/src/app/(main)/guide/bulk-qr-code-generation/page.tsx b/src/app/(main)/guide/bulk-qr-code-generation/page.tsx index 9ebfd41..2ac7ced 100644 --- a/src/app/(main)/guide/bulk-qr-code-generation/page.tsx +++ b/src/app/(main)/guide/bulk-qr-code-generation/page.tsx @@ -12,6 +12,9 @@ export const metadata: Metadata = { alternates: { canonical: 'https://www.qrmaster.net/guide/bulk-qr-code-generation', }, + openGraph: { + url: 'https://www.qrmaster.net/guide/bulk-qr-code-generation', + }, }; export default function BulkGuidePage() { diff --git a/src/app/(main)/guide/qr-code-best-practices/page.tsx b/src/app/(main)/guide/qr-code-best-practices/page.tsx index 9770ae7..3c2d4f2 100644 --- a/src/app/(main)/guide/qr-code-best-practices/page.tsx +++ b/src/app/(main)/guide/qr-code-best-practices/page.tsx @@ -7,11 +7,14 @@ import SeoJsonLd from '@/components/SeoJsonLd'; import { articleSchema } from '@/lib/schema'; export const metadata: Metadata = { - title: 'QR Code Best Practices (Size, Color, Testing) | QR Master Guide', + title: 'QR Code Best Practices: Size, Color & Testing', description: 'Ensure your QR codes scan every time. Guide on minimum size, color contrast, error correction, and placement best practices.', alternates: { canonical: 'https://www.qrmaster.net/guide/qr-code-best-practices', }, + openGraph: { + url: 'https://www.qrmaster.net/guide/qr-code-best-practices', + }, }; export default function BestPracticesGuidePage() { @@ -92,7 +95,7 @@ export default function BestPracticesGuidePage() {
- + diff --git a/src/app/(main)/guide/tracking-analytics/page.tsx b/src/app/(main)/guide/tracking-analytics/page.tsx index 2d282d0..5574d85 100644 --- a/src/app/(main)/guide/tracking-analytics/page.tsx +++ b/src/app/(main)/guide/tracking-analytics/page.tsx @@ -15,6 +15,9 @@ export const metadata: Metadata = { alternates: { canonical: 'https://www.qrmaster.net/guide/tracking-analytics', }, + openGraph: { + url: 'https://www.qrmaster.net/guide/tracking-analytics', + }, }; export default function TrackingGuidePage() { diff --git a/src/app/(marketing-de)/qr-code-erstellen/page.tsx b/src/app/(marketing-de)/qr-code-erstellen/page.tsx index 49e255b..0f558a2 100644 --- a/src/app/(marketing-de)/qr-code-erstellen/page.tsx +++ b/src/app/(marketing-de)/qr-code-erstellen/page.tsx @@ -12,6 +12,7 @@ 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; @@ -96,13 +97,41 @@ export default function QRCodeErstellenPage() { vCard QR Codes für digitale Visitenkarten und QR Codes für Restaurant-Speisekarten.

- Starten Sie kostenlos mit 8 dynamischen QR Codes und unbegrenzten statischen Codes. Upgrade auf Pro für 50 Codes + 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.

+ {/* Answer First Block (SEO/AEO) - German */} +
+ +
+ {/* Main Interaction: Generator */} diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index d1decb5..717973d 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -146,6 +146,12 @@ export default function sitemap(): MetadataRoute.Sitemap { changeFrequency: 'yearly', priority: 0.4, }, + { + url: `${baseUrl}/contact`, + lastModified: new Date(), + changeFrequency: 'yearly', + priority: 0.5, + }, { url: `${baseUrl}/guide/tracking-analytics`, lastModified: new Date(), diff --git a/src/components/marketing/AnswerFirstBlock.tsx b/src/components/marketing/AnswerFirstBlock.tsx new file mode 100644 index 0000000..a101ce8 --- /dev/null +++ b/src/components/marketing/AnswerFirstBlock.tsx @@ -0,0 +1,107 @@ +import React from 'react'; +import { Card } from '@/components/ui/Card'; +import { Check, X } from 'lucide-react'; + +interface ComparisonItem { + label: string; + value: boolean; + text?: string; +} + +interface AnswerFirstBlockProps { + whatIsIt: string; // 2 sentences: "Was ist das?" + whenToUse: string[]; // 3 Bulletpoints: "Wann brauchst du's?" + comparison: { + leftTitle: string; + rightTitle: string; + items: ComparisonItem[]; + }; + howTo: { + steps: string[]; // 3 Steps: "So funktioniert's" + }; + className?: string; // Add className prop +} + +export const AnswerFirstBlock: React.FC = ({ + whatIsIt, + whenToUse, + comparison, + howTo, + className, +}) => { + return ( +
+ {/* 1. Definition */} +
+

Quick Summary

+

+ {whatIsIt} +

+
+ +
+ {/* 2. Usage Reasons */} + +

When to use this?

+
    + {whenToUse.map((item, idx) => ( +
  • + + {item} +
  • + ))} +
+
+ + {/* 3. Mini Comparison */} + +

Comparison

+
+
+ Feature + {comparison.leftTitle} + {comparison.rightTitle} +
+ {comparison.items.map((item, idx) => ( +
+ {item.label} +
+ {/* Logic for Left Side (usually Static/Free) might be false/X or true/Check based on context. + But user said "Static vs Dynamic / Free vs Pro". + Let's assume the comparison object passes explicit logic or we simplify. + For now, assuming ComparisonItem has a single boolean for the 'right' side vs left? + Actually, let's make it simpler: Items have label, and we show check/x for both columns? + Wait, the user requirement is "Mini-Vergleich ... (3-5 Zeilen)". + Let's keep it simple: Feature | A | B + */} + {/* Placeholder logic: Assuming 'value' applies to the Right Side (Pro/Dynamic) usually being better? + Actually, let's request structure: `leftValue`, `rightValue`. + */} + {item.text ? {item.text} : } +
+
+ {item.value ? : } +
+
+ ))} +
+
+ + {/* 4. How To Steps */} + +

How it works

+
    + {howTo.steps.map((step, idx) => ( +
  1. + + {idx + 1} + + {step} +
  2. + ))} +
+
+
+
+ ); +}; diff --git a/src/components/ui/Footer.tsx b/src/components/ui/Footer.tsx index 92d63f8..9dc2854 100644 --- a/src/components/ui/Footer.tsx +++ b/src/components/ui/Footer.tsx @@ -28,7 +28,7 @@ export function Footer({ variant = 'marketing', t }: FooterProps) {

{translations.product}

    -
  • {translations.features}
  • +
  • {translations.features}
  • {translations.pricing}
  • QR Analytics
  • {translations.faq}
  • @@ -50,6 +50,9 @@ export function Footer({ variant = 'marketing', t }: FooterProps) {
  • Manage QR Codes
  • Custom QR
  • Barcode Generator
  • +
  • Tracking Guide
  • +
  • Best Practices
  • +
  • Bulk Generation Guide
@@ -57,6 +60,7 @@ export function Footer({ variant = 'marketing', t }: FooterProps) {

{translations.legal}

  • {translations.privacy_policy}
  • +
  • Contact
  • QR Code Erstellen (DE)
diff --git a/src/i18n/de.json b/src/i18n/de.json index b09ddc6..fd3d72b 100644 --- a/src/i18n/de.json +++ b/src/i18n/de.json @@ -139,7 +139,7 @@ "price": "€0", "period": "für immer", "features": [ - "8 dynamische QR-Codes", + "3 aktive dynamische QR-Codes (8 Typen verfügbar)", "Unbegrenzte statische QR-Codes", "Basis-Scan-Tracking", "Standard QR-Design-Vorlagen" diff --git a/src/lib/blog-data.ts b/src/lib/blog-data.ts index d3cb270..1633bf0 100644 --- a/src/lib/blog-data.ts +++ b/src/lib/blog-data.ts @@ -1586,7 +1586,7 @@ const response = await fetch('https://api.qrmaster.net/v1/bulk', { 'qr-code-print-size-guide': { slug: 'qr-code-print-size-guide', - title: 'QR Code Print Size Guide: Minimum Sizes for Every Use Case', + title: 'QR Code Print Size Guide: Minimum Sizes', excerpt: 'Complete guide to QR code print sizes. Learn minimum dimensions for business cards, posters, banners, and more to ensure reliable scanning.', date: 'January 5, 2026', datePublished: '2026-01-05T12:00:00Z', diff --git a/src/middleware.ts b/src/middleware.ts index 97bfb0d..5faa79f 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -29,6 +29,7 @@ export function middleware(req: NextRequest) { '/feedback', '/vcard', '/display', + '/contact', ]; // Check if path is public