TikTok V6
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
# QR Master: Decision-Content + Market-Proof Implementation Plan
|
||||
|
||||
> **For Hermes:** Execute only after Timo explicitly asks to implement. Do not create a page cluster before the hub has real search/conversion signals.
|
||||
|
||||
**Goal:** Ship one German decision page for the *static vs. dynamic QR code* decision, instrument it with existing analytics, then test the exact message with real DACH restaurants/cafés before expanding SEO content.
|
||||
|
||||
**Architecture:** Reuse the existing localized, data-driven use-case route `src/app/de/[slug]/page.tsx` and `UseCasePageTemplate`. Add one German content object to `src/lib/growth-pages-de.ts`; the route already creates static params, self-canonical metadata, hreflang pairs, Breadcrumb/FAQ schema and CTA tracking. Do not touch the English restaurant page: it already owns the restaurant-menu intent at `/restaurants`, and the old English use-case route redirects there.
|
||||
|
||||
**Tech Stack:** Next.js App Router, TypeScript, existing `UseCasePageTemplate`, PostHog (`MarketingPageTracker` / `TrackedCtaLink`), npm.
|
||||
|
||||
---
|
||||
|
||||
## Current repo facts
|
||||
|
||||
- German localized use-cases are generated from `src/lib/growth-pages-de.ts:29` through `src/app/de/[slug]/page.tsx:14-108`.
|
||||
- The route gives each item a self-canonical and creates static params from the data object (`src/app/de/[slug]/page.tsx:14-38`).
|
||||
- The existing template already tracks page views as `landing_page_viewed` and CTA clicks as `cta_clicked` (`src/components/marketing/MarketingAnalytics.tsx:28-93`). Do **not** create parallel events until the funnel’s actual setup/signup events are located.
|
||||
- `/use-cases/restaurant-menu-qr-codes` is a permanent redirect to `/restaurants` (`next.config.mjs:89-92`). The `/restaurants` page already owns English menu/PDF/reprint copy (`src/app/(main)/(marketing)/restaurants/page.tsx:34-69`).
|
||||
- No German restaurant/speisekarte page exists in `src/lib/growth-pages-de.ts` today.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- No ten-page pSEO rollout.
|
||||
- No bespoke template, calculator, schema type, A/B framework, or new tracking architecture.
|
||||
- No claim of guaranteed savings, GDPR compliance, or “instant” changes unless product behaviour and legal wording are verified.
|
||||
- No customer-story or dashboard screenshot presented as proof until it is real.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Lock the positioning and page boundary
|
||||
|
||||
**Objective:** Ensure this page wins a new decision query instead of competing with generic generator or restaurant-menu pages.
|
||||
|
||||
**Files:**
|
||||
- No code change.
|
||||
- Review: `src/app/(marketing-de)/qr-code-erstellen/page.tsx:26-87`
|
||||
- Review: `src/app/(main)/(marketing)/restaurants/page.tsx:34-170`
|
||||
- Review: `next.config.mjs:63-97`
|
||||
|
||||
**Step 1: Adopt the exact target user and job**
|
||||
|
||||
- Segment: DACH restaurant/café operators with printed table tents, menus, takeaway flyers, or window signs.
|
||||
- Job: Decide *before printing* whether a QR destination needs to stay editable.
|
||||
- Primary query family: `statischer oder dynamischer qr code`, `unterschied statischer dynamischer qr code`, `qr code link später ändern`.
|
||||
- Explicit exclusion: do not target the generic “free QR generator” query or try to become a restaurant POS/menu-builder page.
|
||||
|
||||
**Step 2: Define the content angle**
|
||||
|
||||
Use this hero content:
|
||||
|
||||
- H1: `Statischer oder dynamischer QR-Code? Entscheide vor dem Druck.`
|
||||
- Intro: `Wenn sich dein Link, Menü, PDF oder Angebot später ändern könnte, brauchst du einen QR-Code, dessen Ziel du ohne Neudruck aktualisieren kannst.`
|
||||
- Primary CTA: `Dynamischen QR-Code erstellen`
|
||||
- Secondary CTA: `Zum QR-Code-Generator`
|
||||
|
||||
**Step 3: Define the one-sentence decision rule**
|
||||
|
||||
`Bleibt das Ziel garantiert unverändert, reicht ein statischer QR-Code. Kann sich Ziel, PDF, Menü, Aktion oder Platzierung ändern, ist ein dynamischer QR-Code die sichere Wahl vor dem Druck.`
|
||||
|
||||
**Acceptance criteria:** The page is clearly a decision hub, not another restaurant-menu landing page; it contains the decision within the first viewport.
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Add one localized use-case record
|
||||
|
||||
**Objective:** Publish exactly one data-backed German page at `/de/statischer-vs-dynamischer-qr-code` through the current route/template.
|
||||
|
||||
**Files:**
|
||||
- Modify: `src/lib/growth-pages-de.ts` (inside `useCasePagesDe`, before the closing object)
|
||||
|
||||
**Step 1: Add the record shape**
|
||||
|
||||
Add a `UseCasePageContentDe` record with:
|
||||
|
||||
```ts
|
||||
'statischer-vs-dynamischer-qr-code': {
|
||||
enSlug: 'dynamic-qr-code-generator',
|
||||
slug: 'statischer-vs-dynamischer-qr-code',
|
||||
href: '/de/statischer-vs-dynamischer-qr-code',
|
||||
title: 'Statischer oder dynamischer QR-Code?',
|
||||
cluster: 'qr-code-basics',
|
||||
parentHref: '/dynamic-qr-code-generator',
|
||||
parentTitle: 'Dynamischer QR-Code-Generator',
|
||||
ctaLabel: 'Dynamischen QR-Code erstellen',
|
||||
eyebrow: 'Vor dem Druck entscheiden',
|
||||
titleSuffix: 'vor dem Druck',
|
||||
metaDescription: 'Statischer oder dynamischer QR-Code? Vergleiche Änderbarkeit, Druckrisiko und Tracking – und entscheide vor Flyer, Speisekarte oder Tischaufsteller.',
|
||||
// remaining template fields in the following steps
|
||||
}
|
||||
```
|
||||
|
||||
**Step 2: Write unique decision content—not token substitutions**
|
||||
|
||||
Populate the template fields with these content requirements:
|
||||
|
||||
- `answer`: the exact decision rule from Task 1.
|
||||
- `whenToUse`: three observable conditions: destination cannot change; a PDF/menu/offer might change; scans must be measured by placement.
|
||||
- `comparisonItems`: only concrete trade-offs, e.g. destination after print, response to a changed PDF, scan measurement. Validate the template’s left/right presentation before wording the boolean values.
|
||||
- `howToSteps`: create a dynamic code → print it once → change the destination later in the dashboard.
|
||||
- `workflowCards`: one realistic café example (30 table tents, new menu PDF), one flyer/event example, one separate-placement tracking example.
|
||||
- `checklist`: test print size/contrast, use a descriptive scan CTA, point to a mobile target, keep a dynamic target when it can change.
|
||||
- `supportLinks`: `/dynamic-qr-code-generator`, `/qr-code-tracking`, `/reprint-calculator`, `/qr-code-print-size-guide` after verifying every target resolves.
|
||||
- `faq`: 3–4 factual FAQs such as “Kann ich den Link eines statischen QR-Codes später ändern?” and “Wann lohnt sich ein dynamischer QR-Code für eine Speisekarte?”
|
||||
|
||||
**Step 3: Avoid fictional proof**
|
||||
|
||||
Set no `heroImage` unless a real product/dashboard or verified purpose-built illustration exists. If the template needs an image visually, use a clearly labelled product workflow asset—not a fake customer outcome or fabricated dashboard state.
|
||||
|
||||
**Acceptance criteria:** `generateStaticParams` includes the slug; the page has unique German title, description, H1, intro, FAQ and internal-link context.
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Verify rendered SEO and conversion path
|
||||
|
||||
**Objective:** Confirm the new route is indexable, non-cannibalizing, and sends users into a working generator flow.
|
||||
|
||||
**Files:**
|
||||
- Verify: `src/app/de/[slug]/page.tsx:18-52`
|
||||
- Verify: `src/components/marketing/UseCasePageTemplate.tsx:440-526`
|
||||
- Verify: `src/app/sitemap.ts`
|
||||
|
||||
**Step 1: Run static checks**
|
||||
|
||||
Run from repository root:
|
||||
|
||||
```bash
|
||||
npm run lint
|
||||
npm run build
|
||||
```
|
||||
|
||||
Expected: both commands exit `0`.
|
||||
|
||||
**Step 2: Run the local smoke test**
|
||||
|
||||
Start the app with `npm run dev`, then inspect:
|
||||
|
||||
- `http://localhost:3050/de/statischer-vs-dynamischer-qr-code`
|
||||
- page source/rendered HTML contains one H1
|
||||
- canonical is `https://www.qrmaster.net/de/statischer-vs-dynamischer-qr-code`
|
||||
- page has language alternates generated by `buildLanguageAlternates`
|
||||
- primary CTA reaches the German setup/generator flow actually intended for conversion
|
||||
- all related-resource URLs return a valid page (not redirects to irrelevant pages or 404)
|
||||
- mobile: H1, decision rule, and primary CTA fit/appear before excessive scrolling; comparison is readable
|
||||
|
||||
**Step 3: Verify tracking rather than inventing event names**
|
||||
|
||||
Use the existing PostHog events first:
|
||||
|
||||
- `landing_page_viewed` with `landing_page_slug=/de/statischer-vs-dynamischer-qr-code`
|
||||
- `cta_clicked` with `cta_location=hero_primary` and this use case slug
|
||||
|
||||
Before adding `qr_setup_started` or `signup_completed`, locate their real implementation. If no downstream events exist, add them only after documenting the actual generator/signup handoff and preserving no-PII tracking.
|
||||
|
||||
**Acceptance criteria:** build passes, canonical and CTA are correct, events appear in PostHog (or the tracking limitation is explicitly documented), and there is no new page aimed at `/restaurants`’ restaurant-menu keyword set.
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Run a 7-day manual market test in parallel
|
||||
|
||||
**Objective:** Test whether the language describes a costly current problem, not merely whether people say they like the page.
|
||||
|
||||
**Files:**
|
||||
- No product code required.
|
||||
- Create a local working sheet only if Timo asks; do not automate outreach first.
|
||||
|
||||
**Step 1: Build a 20-prospect list (45 minutes max)**
|
||||
|
||||
Collect 20 independent restaurants/cafés in one local area. Criteria:
|
||||
|
||||
- visible printed menu/table-tent/window QR in Google photos, Instagram, or own site;
|
||||
- a current menu PDF, ordering page, seasonal offer, or booking link;
|
||||
- reachable email, Instagram, or contact form.
|
||||
|
||||
**Step 2: Send 10 short research-first messages**
|
||||
|
||||
Use this wording, adapted with the venue’s name and observed QR use:
|
||||
|
||||
> Hi [Name], kurze Frage – ich schaue mir gerade an, wie Restaurants QR-Codes auf Tischaufstellern und Speisekarten nutzen. Musstet ihr den Link, die PDF-Speisekarte oder Preise nach dem Druck schon einmal ändern? Was habt ihr dann gemacht? Ich verkaufe dir gerade nichts; ich will den Ablauf verstehen.
|
||||
|
||||
Do not pitch QR Master in the first message.
|
||||
|
||||
**Step 3: Follow up only with a relevant offer**
|
||||
|
||||
If they mention an actual recent issue, reply:
|
||||
|
||||
> Danke, genau diesen Fall untersuche ich. Ich baue ein Setup, bei dem der gedruckte QR-Code bleibt und du nur das Ziel aktualisierst. Wenn du willst, richte ich dir den nächsten Code testweise ein und prüfe vorher kostenlos, ob euer aktueller Code überhaupt update-sicher ist.
|
||||
|
||||
**Step 4: Record proof, not compliments**
|
||||
|
||||
For every reply capture: last incident, workaround, print/time cost, current QR tool, decision-maker, and whether they agree to a test/pilot. Strong evidence is a real past case, a follow-up call, a current QR audit, or a pilot—not “klingt gut”.
|
||||
|
||||
**Acceptance criteria:** at least 10 contacts sent and one of these evidence types captured: concrete past incident, audit request, pilot, call, trial, or explicit rejection with reason.
|
||||
|
||||
---
|
||||
|
||||
### Task 5: Make the expansion/kill decision after 7–14 days
|
||||
|
||||
**Objective:** Prevent a content factory before a signal exists.
|
||||
|
||||
**Decision table:**
|
||||
|
||||
| Signal | Decision |
|
||||
| --- | --- |
|
||||
| Search impressions/query relevance + CTA clicks | Build exactly one follow-up: `/de/qr-code-nach-druck-aendern` focused on recovery intent. |
|
||||
| At least 2 concrete restaurant incidents or 1 pilot | Improve the restaurant-specific proof/CTA or ship a German restaurant page only after title/canonical mapping against `/restaurants`. |
|
||||
| No relevant queries, replies, CTA clicks, or incidents | Do not create more pages. Change segment/message (e.g. flyers/events/real-estate) and repeat outreach. |
|
||||
|
||||
**Do not expand to** flyer, business-card, event, packaging, PDF, and restaurant subpages simultaneously. One successful page/message earns one sibling.
|
||||
|
||||
---
|
||||
|
||||
## Final Definition of Done
|
||||
|
||||
1. One live, unique German decision page—not a page cluster.
|
||||
2. `npm run lint` and `npm run build` pass.
|
||||
3. Canonical, hreflang, CTA and tracking are verified on the rendered route.
|
||||
4. Ten manual research contacts are sent.
|
||||
5. A seven-day review contains real proof: Search Console query data, PostHog CTA data, replies, calls, audits, trials, or payments.
|
||||
6. Only then decide whether `/de/qr-code-nach-druck-aendern` deserves implementation.
|
||||
Reference in New Issue
Block a user