This commit is contained in:
2026-08-11 21:50:42 +02:00
parent bec48ab8e1
commit ca1e432f80
9 changed files with 65 additions and 22 deletions

View File

@@ -6,6 +6,12 @@
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"port": 3050
},
{
"name": "dev-node",
"runtimeExecutable": "node",
"runtimeArgs": ["node_modules/next/dist/bin/next", "dev", "-p", "3050"],
"port": 3050
}
]
}

View File

@@ -49,10 +49,13 @@ NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
NEXT_PUBLIC_POSTHOG_KEY=
NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
# Analytics (Optional - Microsoft Clarity session recordings & heatmaps)
NEXT_PUBLIC_CLARITY_PROJECT_ID=
# TikTok Content Posting API (Hermes Agent automated posting)
TIKTOK_CLIENT_KEY=
TIKTOK_CLIENT_SECRET=
TIKTOK_REDIRECT_URI=https://qrmaster.net/api/tiktok/callback
# Optional: protects /api/tiktok/connect from being triggered by strangers
TIKTOK_ADMIN_KEY=
TIKTOK_EXPECTED_OPEN_ID=
TIKTOK_ADMIN_KEY=
TIKTOK_EXPECTED_OPEN_ID=

View File

@@ -36,7 +36,7 @@ export default function CookiePolicyPage() {
<h2 className="text-2xl font-bold text-gray-900 mb-4">How We Use Cookies</h2>
<ul className="list-disc pl-6 space-y-2">
<li><strong>Essential Cookies:</strong> Required for the website to function (e.g., login, session management).</li>
<li><strong>Analytics Cookies (Optional):</strong> We use tools like PostHog to understand how you use the site and improve it. These are only set with your consent.</li>
<li><strong>Analytics Cookies (Optional):</strong> We use tools like PostHog and Microsoft Clarity (session recordings, heatmaps) to understand how you use the site and improve it. These are only set with your consent.</li>
<li><strong>Functionality Cookies:</strong> To remember your preferences.</li>
</ul>
</section>

View File

@@ -25,7 +25,7 @@ export default function PrivacyPage() {
</div>
<h1 className="text-4xl font-bold text-gray-900 mb-4">Privacy Policy</h1>
<p className="text-gray-600 mb-8">Last updated: August 2026</p>
<p className="text-gray-600 mb-8">Last updated: August 2026</p>
<div className="prose prose-lg max-w-none">
<section className="mb-8">
@@ -38,20 +38,20 @@ export default function PrivacyPage() {
We implement appropriate security measures including secure HTTPS transmission, password hashing, database access controls,
and CSRF protection to keep your data safe.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-gray-900 mb-4">2. Chrome Extension</h2>
<p className="text-gray-700 mb-4">
The QR Master: QR Code for Current Tab Chrome extension processes the active tab URL and the URL, text, Wi-Fi, or vCard details you enter only to create a QR code in the extension popup. This information is processed locally in your browser, is not stored by the extension, and is not transmitted to QR Master or third parties.
</p>
<p className="text-gray-700 mb-4">
The extension uses clipboard access only after you select Copy Image, so that it can copy the generated QR code image to your device clipboard. We do not sell, share, or use extension input data for advertising, analytics, profiling, or creditworthiness decisions.
</p>
</section>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-gray-900 mb-4">3. Information We Collect</h2>
<h2 className="text-2xl font-bold text-gray-900 mb-4">2. Chrome Extension</h2>
<p className="text-gray-700 mb-4">
The QR Master: QR Code for Current Tab Chrome extension processes the active tab URL and the URL, text, Wi-Fi, or vCard details you enter only to create a QR code in the extension popup. This information is processed locally in your browser, is not stored by the extension, and is not transmitted to QR Master or third parties.
</p>
<p className="text-gray-700 mb-4">
The extension uses clipboard access only after you select Copy Image, so that it can copy the generated QR code image to your device clipboard. We do not sell, share, or use extension input data for advertising, analytics, profiling, or creditworthiness decisions.
</p>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-gray-900 mb-4">3. Information We Collect</h2>
<h3 className="text-xl font-semibold text-gray-900 mb-3">Information You Provide</h3>
<ul className="list-disc pl-6 mb-4 text-gray-700 space-y-2">
@@ -64,12 +64,12 @@ export default function PrivacyPage() {
<ul className="list-disc pl-6 mb-4 text-gray-700 space-y-2">
<li><strong>Usage Data:</strong> QR code scans and analytics</li>
<li><strong>Technical Data:</strong> IP address, browser type, and device information</li>
<li><strong>Cookies:</strong> Essential cookies for authentication and optional analytics cookies (PostHog) with your consent</li>
<li><strong>Cookies:</strong> Essential cookies for authentication and optional analytics cookies (PostHog, Microsoft Clarity) with your consent</li>
</ul>
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-gray-900 mb-4">4. How We Use Your Information</h2>
<h2 className="text-2xl font-bold text-gray-900 mb-4">4. How We Use Your Information</h2>
<p className="text-gray-700 mb-4">We use your data to:</p>
<ul className="list-disc pl-6 mb-4 text-gray-700 space-y-2">
<li>Provide and maintain our QR code services</li>
@@ -85,11 +85,12 @@ export default function PrivacyPage() {
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-gray-900 mb-4">5. Data Sharing</h2>
<h2 className="text-2xl font-bold text-gray-900 mb-4">5. Data Sharing</h2>
<p className="text-gray-700 mb-4">We may share your data with:</p>
<ul className="list-disc pl-6 mb-4 text-gray-700 space-y-2">
<li><strong>Stripe:</strong> Payment processing</li>
<li><strong>PostHog:</strong> Analytics (only with your consent, respects Do Not Track)</li>
<li><strong>Microsoft Clarity:</strong> Session recordings and heatmaps (only with your consent)</li>
<li><strong>Vercel:</strong> Cloud hosting provider</li>
<li><strong>Legal Requirements:</strong> When required by law</li>
</ul>
@@ -99,7 +100,7 @@ export default function PrivacyPage() {
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-gray-900 mb-4">6. Your Rights (GDPR)</h2>
<h2 className="text-2xl font-bold text-gray-900 mb-4">6. Your Rights (GDPR)</h2>
<p className="text-gray-700 mb-4">You have the right to:</p>
<ul className="list-disc pl-6 mb-4 text-gray-700 space-y-2">
<li><strong>Access:</strong> Request a copy of your personal data</li>
@@ -122,7 +123,7 @@ export default function PrivacyPage() {
</section>
<section className="mb-8">
<h2 className="text-2xl font-bold text-gray-900 mb-4">7. Contact Us</h2>
<h2 className="text-2xl font-bold text-gray-900 mb-4">7. Contact Us</h2>
<p className="text-gray-700 mb-4">
If you have questions about this privacy policy, please contact us:
</p>

View File

@@ -5,6 +5,7 @@ import '@/styles/globals.css';
import { Providers } from '@/components/Providers';
import AdSenseScript from '@/components/ads/AdSenseScript';
import FacebookPixel from '@/components/analytics/FacebookPixel';
import MicrosoftClarity from '@/components/analytics/MicrosoftClarity';
const isIndexable = process.env.NEXT_PUBLIC_INDEXABLE === 'true';
@@ -65,6 +66,7 @@ export default function RootLayout({
<Suspense fallback={null}>
<FacebookPixel />
</Suspense>
<MicrosoftClarity />
{children}
{process.env.NEXT_PUBLIC_UMAMI_SRC && process.env.NEXT_PUBLIC_UMAMI_ID && (
<Script

View File

@@ -5,6 +5,7 @@ import { Providers } from '@/components/Providers';
import MarketingDeLayout from '@/components/marketing/MarketingDeLayout';
import { organizationSchema, websiteSchema } from '@/lib/schema';
import FacebookPixel from '@/components/analytics/FacebookPixel';
import MicrosoftClarity from '@/components/analytics/MicrosoftClarity';
export const metadata: Metadata = {
title: {
@@ -68,6 +69,7 @@ export default function MarketingDeGroupLayout({
<Suspense fallback={null}>
<Providers>
<FacebookPixel />
<MicrosoftClarity />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema()) }}

View File

@@ -5,6 +5,7 @@ import { Providers } from '@/components/Providers';
import MarketingDeLayout from '@/components/marketing/MarketingDeLayout';
import { organizationSchema, websiteSchema } from '@/lib/schema';
import FacebookPixel from '@/components/analytics/FacebookPixel';
import MicrosoftClarity from '@/components/analytics/MicrosoftClarity';
export const metadata: Metadata = {
title: {
@@ -60,6 +61,7 @@ export default function GermanRootLayout({
<Suspense fallback={null}>
<Providers>
<FacebookPixel />
<MicrosoftClarity />
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema()) }}

View File

@@ -67,7 +67,7 @@ export default function CookieBanner() {
<svg className="w-3.5 h-3.5 text-primary-600 mr-1.5" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
</svg>
<span className="text-gray-700"><strong>Analytics:</strong> PostHog & Google Analytics</span>
<span className="text-gray-700"><strong>Analytics:</strong> PostHog, Microsoft Clarity & Google Analytics</span>
</div>
</div>
</div>

View File

@@ -0,0 +1,27 @@
'use client';
import { useEffect, useState } from 'react';
import Script from 'next/script';
export default function MicrosoftClarity() {
const [consented, setConsented] = useState(false);
const projectId = process.env.NEXT_PUBLIC_CLARITY_PROJECT_ID;
useEffect(() => {
// Check consent (same gate as PostHog / Facebook Pixel)
const cookieConsent = localStorage.getItem('cookieConsent');
if (cookieConsent === 'accepted') setConsented(true);
}, []);
if (!projectId || !consented) return null;
return (
<Script id="ms-clarity" strategy="afterInteractive">
{`(function(c,l,a,r,i,t,y){
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "${projectId}");`}
</Script>
);
}