feat(marketing): Saving-Section + Landingpages + Pipeline Lessons-Learned [split-required]
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 35s
CI / test-python-voice (push) Successful in 33s
CI / test-bqas (push) Successful in 35s
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-consent (push) Successful in 35s
CI / test-python-voice (push) Successful in 33s
CI / test-bqas (push) Successful in 35s
Marketing-Website - Neue SavingsSection auf Homepage: "Compliance entdeckt sechsstellige Einsparungen". Pitch-Position der Cookie-Audit-Cost-Optimization-Story fuer DAX-Konzern-Sales (BMW-Case-Style: 90 Vendors -> 25 nach Konsolidierung, EUR 500k-3M / Jahr). - /savings-scan: Kostenloser 5-Min-Saving-Scan-Form (URL + E-Mail). Form-Submit ist Placeholder, soll an Compliance-Backend gehaengt werden. - /savings-methodik: 4-Stufen-Erklaerung der Cookie-Tier-Inferenz + ehrliche Caveats (Listpreise != Vertragspreise, Media-Spend nicht enthalten) + Datenquellen. - Content-de + Content-en in content.ts beide um savings-Block ergaenzt und Section-Numerierung angepasst (03=Savings, 04=Deterministic). - LOC-Split: savings-Inhalte (DE+EN, ~100 LOC) in content.savings.ts ausgelagert damit content.ts unter 500-LOC-Hard-Cap bleibt. Control-Pipeline - LESSONS-LEARNED-mc-check-types.md fuer die parallele CRA-MC-Generation. Erklaert die TEXT/PROCESS/REVIEW-Klassifikation die im Compliance-Repo retrofitted wurde. Verhindert dass CRA-MCs denselben Defekt bekommen. Mapping-Heuristik fuer verification_method -> check_type, plus Backfill-Workflow fuer ~62 ambiguous Eintraege. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
# Lessons Learned — MC `check_type` Klassifikation (KRITISCH fuer CRA + alle neuen Frameworks)
|
||||
|
||||
Datum: 2026-05-17
|
||||
Auslöser: Compliance-Check BMW lieferte 0/381 Cookie-MCs, 3/75 Impressum-MCs, 43/571 DSE-MCs — alle Doc-Typen unter 20%.
|
||||
|
||||
## TL;DR
|
||||
|
||||
**Die heutigen Master-Controls (MCs) vermischen drei strukturell unterschiedliche Klassen von Pruefungen in einer einzigen Tabelle (`compliance.doc_check_controls`). Nur eine der drei Klassen lässt sich gegen Dokument-Text matchen. Die anderen zwei werden faelschlich als "failed" gezaehlt, weil sie ueberhaupt nicht ueber Text-Matching gepruefbar sind.**
|
||||
|
||||
Bei der CRA-MC-Generierung (laeuft jetzt im Pass 0a mit Haiku) **MUSS** jeder MC ein **`check_type`-Feld** bekommen, bevor er in die Datenbank geht. Sonst wiederholt sich das Problem.
|
||||
|
||||
## Die drei Klassen
|
||||
|
||||
| `check_type` | Pruefungsfrage-Pattern | Beispiel | Wie pruefbar? |
|
||||
|---|---|---|---|
|
||||
| **`text`** | "Enthaelt das Dokument...", "Wird im X die Y benannt?", "Ist im Text aufgelistet..." | "Wird im Impressum die Aufsichtsbehoerde benannt?" | Regex / Embedding-Match gegen Doc-Text |
|
||||
| **`process`** | "Ist sichergestellt...", "Ist implementiert...", "Wird durchgefuehrt..." | "Ist sichergestellt, dass Cookies erst nach Einwilligung gespeichert werden?" | Evidence/TOM-Check — kein Doc-Text vorhanden |
|
||||
| **`review`** | "Sind ALLE / Werden ALLE / Stimmt X mit Y ueberein?" | "Sind alle Verarbeitungszwecke vollstaendig erfasst?" | Mensch (DSB) — Checkliste, nicht automatisch |
|
||||
|
||||
## Befund aus den BMW-Daten
|
||||
|
||||
| Doc-Type | TEXT (matchbar) | PROCESS | UNKLAR/REVIEW | Total | % TEXT |
|
||||
|---|---|---|---|---|---|
|
||||
| cookie | 30 | 49 | 302 | 381 | **8%** |
|
||||
| dse | 72 | 139 | 359 | 571 | **13%** |
|
||||
| impressum | 14 | 14 | 47 | 75 | **19%** |
|
||||
| agb | 24 | 20 | 69 | 113 | 21% |
|
||||
| widerruf | 29 | 26 | 96 | 153 | 19% |
|
||||
| loeschkonzept | 38 | 39 | 232 | 309 | 12% |
|
||||
|
||||
**Selbst mit perfektem Matching liegt die Obergrenze fuer doc_check bei 8-20%**, weil 80-92% der MCs nicht ueber Text-Matching pruefbar sind. Es sind keine "schlechten MCs" — sie sind in der falschen Schublade.
|
||||
|
||||
## Konsequenzen fuer CRA-Generation (Pass 0a)
|
||||
|
||||
### 1. Prompt-Aenderung (Hauptmassnahme)
|
||||
|
||||
Der Pass-0a-Prompt fuer Haiku/Sonnet MUSS pro generiertem Control ein `check_type`-Feld erzwingen. Vorschlag:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"control_id": "CRA-...-A01",
|
||||
"title": "...",
|
||||
"check_question": "...",
|
||||
"check_type": "text" | "process" | "review", // PFLICHT
|
||||
"rationale_for_check_type": "..."
|
||||
}
|
||||
```
|
||||
|
||||
Klassifikations-Regel im Prompt:
|
||||
|
||||
> Wenn deine `check_question` mit "Enthaelt", "Wird … genannt/aufgelistet/erwaehnt", "Steht im Text" beginnt -> `text`.
|
||||
> Wenn sie mit "Ist sichergestellt", "Ist implementiert", "Wird durchgefuehrt", "Existiert ein Prozess" beginnt -> `process`.
|
||||
> Wenn sie mit "Sind ALLE", "Werden ALLE", "Stimmt X mit Y ueberein" beginnt -> `review`.
|
||||
> Im Zweifel: lieber `review` als `text`.
|
||||
|
||||
### 2. Doc-Type-Zuordnung kritisch validieren
|
||||
|
||||
Bei den heutigen MCs sind viele falsch zugeordnet (z.B. "Bestellbestätigung implementieren" landet im `impressum`-doc_type, gehoert aber zu AGB/Widerruf). Fuer CRA:
|
||||
|
||||
- **`doc_type` darf nur Werte aus einer expliziten Liste annehmen** — pro Regulation festlegen.
|
||||
- Fuer CRA z.B.: `produkt_konformitaetserklaerung`, `risiko_management_dossier`, `sbom`, `cra_dse`, `meldepflichten_doku`.
|
||||
- Falsche Zuordnung im Prompt explizit verbieten: "Wenn der Control nicht eindeutig zu EINEM dieser Doc-Typen passt, setze `doc_type: 'unassigned'` und `check_type: 'review'`."
|
||||
|
||||
### 3. Zwei Tabellen statt einer
|
||||
|
||||
Heutige Architektur:
|
||||
- `compliance.doc_check_controls` <- alle 1874 MCs (mit allem vermischt)
|
||||
|
||||
Empfohlen fuer CRA + Refactor:
|
||||
- `compliance.text_check_controls` <- nur `check_type='text'`
|
||||
- `compliance.process_check_controls` <- nur `check_type='process'`, gepruefte via Evidence/TOM
|
||||
- `compliance.review_checklist_controls` <- nur `check_type='review'`, gepruefte via DSB-Workflow
|
||||
|
||||
Falls Schema-Aenderung nicht moeglich (CLAUDE.md: DB ist frozen), Sidecar-SQLite mit `mc_classification.db` oder neue Spalte als Add-only-Migration.
|
||||
|
||||
### 4. Dedupe-Phase respektieren
|
||||
|
||||
In Pass 0b (Dedup) muss `check_type` ein **Pflicht-Dedupe-Key** sein:
|
||||
- Zwei MCs mit gleicher Aussage aber unterschiedlichem `check_type` sind **nicht** Duplikate — sie pruefen verschiedene Dinge ("ist im Text genannt" vs "ist technisch implementiert").
|
||||
- Heute werden solche faelschlich gemerged → noch mehr Vermischung.
|
||||
|
||||
### 5. Matching-Engine danach umbauen
|
||||
|
||||
Das eigentliche doc-check-Match-System muss nur noch `check_type='text'`-MCs verarbeiten. Andere werden in ihre eigenen Module geroutet:
|
||||
|
||||
- `text` MCs -> `rag_document_checker` (Regex + spaeter Embedding)
|
||||
- `process` MCs -> neuer `evidence_check_runner` (Kunde lieferte Nachweise/TOM hoch)
|
||||
- `review` MCs -> neuer `review_checklist_ui` (DSB beantwortet manuell)
|
||||
|
||||
## Checkliste fuer CRA-Session
|
||||
|
||||
- [ ] Pass-0a-Prompt um `check_type`-Pflichtfeld erweitert (Wortlaut-Regel + Beispiele)
|
||||
- [ ] Pass-0a-Prompt zwingt `doc_type` aus expliziter Whitelist
|
||||
- [ ] Pass-0b-Dedup-Key enthaelt `check_type`
|
||||
- [ ] Output-Validator weist MCs ohne `check_type` zurueck
|
||||
- [ ] DB-Schema (oder Sidecar) hat `check_type`-Spalte mit Default `review` (sicherer Fallback)
|
||||
- [ ] Stichprobe von 50 generierten CRA-MCs vor Bulk-Run: TEXT-Anteil sollte 30-50% sein (mehr als bei den alten DSGVO-MCs, weil CRA stark dokument-fokussiert ist).
|
||||
|
||||
## Update 2026-05-17 — Parallel-CRA-Session-Findings
|
||||
|
||||
Die laufende CRA-Generation hat ein Feld `verification_method` (document/tool/hybrid/code_review/empty), das **NICHT identisch** mit `check_type` ist:
|
||||
|
||||
- `verification_method` fragt: **WAS schaust du dir an?** (Dokument, Tool-Output, Code)
|
||||
- `check_type` fragt: **KANN das per Text-Match geprueft werden?** (text/process/review)
|
||||
|
||||
Ein Control kann `verification_method=document` haben UND trotzdem `check_type=process` sein. Beispiel: "Wird die SBOM regelmaessig (mindestens monatlich) aktualisiert?" — Du schaust ins Dokument SBOM-Historie, prüfst aber einen Prozess. Text-Match findet das nie.
|
||||
|
||||
**Mapping-Heuristik (gut genug fuer 80% der Faelle, Rest LLM):**
|
||||
|
||||
| `verification_method` | Auto-Mapping `check_type` | LLM noetig? |
|
||||
|---|---|---|
|
||||
| `tool` | `process` | nein |
|
||||
| `code_review` | `process` | nein |
|
||||
| empty/null | `review` (sicherer Default) | nein |
|
||||
| `document` | erstmal `text`, Stichprobe pruefen | 10-20% sampling |
|
||||
| `hybrid` | LLM klassifizieren | ja, alle |
|
||||
|
||||
**Idealfall (fuer alle KUENFTIGEN Pass-0a-Generationen — auch CRA falls man nochmal generiert):** Beide Felder gleichzeitig generieren, nicht eins aus dem anderen ableiten.
|
||||
|
||||
## Backfill-Workflow fuer die laufende CRA-Generation
|
||||
|
||||
1. Aktueller Haiku-Job laeuft fertig (kein Restart, kein Verlust)
|
||||
2. Nach Job-Ende: Auto-Mapping fuer eindeutige Buckets (tool/code_review/empty)
|
||||
3. Sonnet-Klassifikation nur fuer `document`+`hybrid` Subset (~62 Calls fuer 1500 Controls, ~$0.05 statt $2)
|
||||
4. Wiederverwenden: `breakpilot-compliance/backend-compliance/scripts/classify_mc_check_type.py` — nur DB-Query anpassen (Source-Tabelle + WHERE-Filter)
|
||||
5. Validierung: TEXT-Anteil bei CRA sollte 40-60% sein (CRA ist dokument-zentrierter als DSGVO-Cookie)
|
||||
|
||||
## Quervewweise
|
||||
|
||||
- BMW-Run-Befund: `breakpilot-compliance` E-Mail vom 2026-05-17, check_id `08bcc9dd`
|
||||
- Bestehender Klassifikations-Skript fuer Retrofit der alten 1874: `backend-compliance/scripts/classify_mc_check_type.py`
|
||||
- Doc-Type-Audit-Query: dieselbe Datei, am Ende
|
||||
@@ -3,6 +3,7 @@ import Footer from '@/components/layout/Footer'
|
||||
import ChatFAB from '@/components/layout/ChatFAB'
|
||||
import HeroSection from '@/components/sections/HeroSection'
|
||||
import ProblemFlowSection from '@/components/sections/ProblemFlowSection'
|
||||
import SavingsSection from '@/components/sections/SavingsSection'
|
||||
import UseCaseCards from '@/components/sections/UseCaseCards'
|
||||
import TrustBar from '@/components/sections/TrustBar'
|
||||
|
||||
@@ -13,6 +14,7 @@ export default function HomePage() {
|
||||
<main>
|
||||
<HeroSection />
|
||||
<ProblemFlowSection />
|
||||
<SavingsSection />
|
||||
<UseCaseCards />
|
||||
<TrustBar />
|
||||
</main>
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
import Navbar from '@/components/layout/Navbar'
|
||||
import Footer from '@/components/layout/Footer'
|
||||
import ChatFAB from '@/components/layout/ChatFAB'
|
||||
import PageHeader from '@/components/ui/PageHeader'
|
||||
import GlassCard from '@/components/ui/GlassCard'
|
||||
import FadeInView from '@/components/ui/FadeInView'
|
||||
import { Database, Layers, Calculator, AlertTriangle, Globe, Cookie } from 'lucide-react'
|
||||
|
||||
export default function SavingsMethodikPage() {
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<main>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<PageHeader
|
||||
tag="METHODIK"
|
||||
title="Wie Cookies"
|
||||
titleHighlight="Marketing-Budgets entlarven"
|
||||
subtitle="4-Stufen-Analyse: vom rohen Cookie-Footprint zur fundierten Saving-Schaetzung. Jede Stufe nachvollziehbar, jede Zahl mit Quelle, jede Annahme transparent."
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 4 Stufen */}
|
||||
<section className="py-12 sm:py-16">
|
||||
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 space-y-8">
|
||||
<FadeInView>
|
||||
<GlassCard>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-12 h-12 rounded-xl bg-emerald-500/10 flex items-center justify-center flex-shrink-0">
|
||||
<Cookie className="w-6 h-6 text-emerald-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="mono-label text-emerald-400 mb-1">STUFE 1</div>
|
||||
<h3 className="text-xl font-bold mb-2">Cookie-Footprint extrahieren</h3>
|
||||
<p className="text-sm text-white/60 mb-3">
|
||||
Playwright laedt die Webseite vollstaendig (inkl. JavaScript-Rendering)
|
||||
und erfasst jeden gesetzten Cookie + jeden CMP-Payload
|
||||
(ePaaS, OneTrust, Usercentrics, Cookiebot, Didomi, TrustArc).
|
||||
</p>
|
||||
<ul className="text-sm text-white/50 space-y-1">
|
||||
<li>• Cookie-Namen, Werte, Domains, Lifetimes</li>
|
||||
<li>• IAB TCF v2.2 Vendor-Liste auswerten (Vendor-IDs zur eindeutigen Zuordnung)</li>
|
||||
<li>• Drittanbieter-Quote pro Cookie</li>
|
||||
<li>• Premium-Feature-Cookies erkennen (z.B. <code className="text-emerald-300">s_target_qa</code> = Adobe Target Enterprise)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</GlassCard>
|
||||
</FadeInView>
|
||||
|
||||
<FadeInView delay={0.1}>
|
||||
<GlassCard>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-12 h-12 rounded-xl bg-emerald-500/10 flex items-center justify-center flex-shrink-0">
|
||||
<Database className="w-6 h-6 text-emerald-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="mono-label text-emerald-400 mb-1">STUFE 2</div>
|
||||
<h3 className="text-xl font-bold mb-2">Wissens-Datenbank-Abgleich</h3>
|
||||
<p className="text-sm text-white/60 mb-3">
|
||||
Jeder Cookie wird gegen unsere kuratierte Wissens-DB mit derzeit
|
||||
~50 Top-Vendors abgeglichen. Pro Cookie wissen wir:
|
||||
</p>
|
||||
<ul className="text-sm text-white/50 space-y-1">
|
||||
<li>• Setzender Anbieter + Sitzland</li>
|
||||
<li>• Exakter funktionaler Zweck (nicht nur Kategorie)</li>
|
||||
<li>• Welche Datenfelder gesammelt werden (Client-ID, IP, etc.)</li>
|
||||
<li>• Re-Identifikations-Risiko (low/medium/high)</li>
|
||||
<li>• §25(2) TDDDG technische Notwendigkeit</li>
|
||||
<li>• Schrems-II-Status + relevante EuGH-/CNIL-Urteile</li>
|
||||
<li>• Konkreter EU-Alternativ-Cookie + EU-Alternativ-Vendor</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</GlassCard>
|
||||
</FadeInView>
|
||||
|
||||
<FadeInView delay={0.2}>
|
||||
<GlassCard>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-12 h-12 rounded-xl bg-emerald-500/10 flex items-center justify-center flex-shrink-0">
|
||||
<Layers className="w-6 h-6 text-emerald-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="mono-label text-emerald-400 mb-1">STUFE 3</div>
|
||||
<h3 className="text-xl font-bold mb-2">Tier-Inferenz + Funktionale Kategorisierung</h3>
|
||||
<p className="text-sm text-white/60 mb-3">
|
||||
Pro Vendor leiten wir das Pricing-Tier aus dem Cookie-Footprint ab:
|
||||
</p>
|
||||
<ul className="text-sm text-white/50 space-y-1">
|
||||
<li>• <strong className="text-white/80"><10 Cookies</strong> = Starter-Plan</li>
|
||||
<li>• <strong className="text-white/80">10-30 Cookies</strong> = Professional / Mid-Market</li>
|
||||
<li>• <strong className="text-white/80">30-60 Cookies</strong> = Enterprise</li>
|
||||
<li>• <strong className="text-white/80">>60 Cookies + Premium-Features</strong> = Premier-Tier</li>
|
||||
</ul>
|
||||
<p className="text-sm text-white/60 mt-3 mb-2">
|
||||
Parallel werden alle Vendors funktional klassifiziert (Web-Analytics,
|
||||
Werbung, CDN, Marketing-Automation, …). Mehrere Vendors in
|
||||
derselben Kategorie = Konsolidierungs-Kandidat.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</GlassCard>
|
||||
</FadeInView>
|
||||
|
||||
<FadeInView delay={0.3}>
|
||||
<GlassCard>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="w-12 h-12 rounded-xl bg-emerald-500/10 flex items-center justify-center flex-shrink-0">
|
||||
<Calculator className="w-6 h-6 text-emerald-400" />
|
||||
</div>
|
||||
<div>
|
||||
<div className="mono-label text-emerald-400 mb-1">STUFE 4</div>
|
||||
<h3 className="text-xl font-bold mb-2">Kosten-Schaetzung + EU-Konsolidierung</h3>
|
||||
<p className="text-sm text-white/60 mb-3">
|
||||
Pro Tier multiplizieren wir mit unseren Pricing-Lookups
|
||||
(Gartner/Forrester 2025 + oeffentliche Listpreise).
|
||||
Ergebnis: jaehrlicher Kostenbereich pro Vendor.
|
||||
</p>
|
||||
<ul className="text-sm text-white/50 space-y-1">
|
||||
<li>• Master-Vertrag-Dedupe (1 Adobe-Lizenz, viele Features)</li>
|
||||
<li>• EU-Alternative mit gleicher Funktion + Listpreis</li>
|
||||
<li>• Multi-Funktions-Tools die mehrere Kategorien gleichzeitig ersetzen</li>
|
||||
<li>• Sparpotenzial = Aktuelle Listpreise − EU-Tool-Listpreis</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</GlassCard>
|
||||
</FadeInView>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Caveats — ehrlich */}
|
||||
<section className="py-12 sm:py-16 bg-amber-500/[0.03]">
|
||||
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-2xl font-bold mb-6 flex items-center gap-3">
|
||||
<AlertTriangle className="w-6 h-6 text-amber-400" />
|
||||
Was wir NICHT versprechen
|
||||
</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<GlassCard>
|
||||
<h3 className="font-bold mb-2">Listpreise ≠ Vertragspreise</h3>
|
||||
<p className="text-sm text-white/60">
|
||||
Konzern-Konditionen liegen ueblicherweise 30–50% unter Listpreis.
|
||||
Wir geben Bereiche an, nicht exakte Zahlen. Verifikation mit dem
|
||||
eigenen Einkauf ist Pflicht.
|
||||
</p>
|
||||
</GlassCard>
|
||||
<GlassCard>
|
||||
<h3 className="font-bold mb-2">Funktionale Redundanz ≠ Strategische Redundanz</h3>
|
||||
<p className="text-sm text-white/60">
|
||||
Mehrere Analytics-Tools koennen legitim sein (A/B-Test, regional split,
|
||||
Marketing vs Produkt). Wir nennen die bekannten Gruende explizit.
|
||||
</p>
|
||||
</GlassCard>
|
||||
<GlassCard>
|
||||
<h3 className="font-bold mb-2">Media-Spend nicht enthalten</h3>
|
||||
<p className="text-sm text-white/60">
|
||||
Google-Ads-/Meta-Ads-/Programmatic-Budget ist NICHT in der Saving-
|
||||
Schaetzung. Nur Tool-Lizenzen. Media-Optimierung ist ein separates
|
||||
Thema.
|
||||
</p>
|
||||
</GlassCard>
|
||||
<GlassCard>
|
||||
<h3 className="font-bold mb-2">Migrations-Kosten nicht abgezogen</h3>
|
||||
<p className="text-sm text-white/60">
|
||||
Tool-Wechsel kostet Zeit + interne Implementation. Faustregel:
|
||||
3-6 Monate Amortisation einrechnen. Saving-Schaetzung ist Brutto.
|
||||
</p>
|
||||
</GlassCard>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Datenquellen */}
|
||||
<section className="py-12 sm:py-16">
|
||||
<div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<h2 className="text-2xl font-bold mb-6 flex items-center gap-3">
|
||||
<Globe className="w-6 h-6 text-emerald-400" />
|
||||
Datenquellen + Updates
|
||||
</h2>
|
||||
<GlassCard>
|
||||
<ul className="text-sm text-white/60 space-y-3">
|
||||
<li>
|
||||
<strong className="text-white/90">Cookie-Wissen:</strong>{' '}
|
||||
Cookiepedia, IAB Europe TCF v2.2 Vendor-Liste, Cookiebot Public DB,
|
||||
Vendor-eigene Dokumentation
|
||||
</li>
|
||||
<li>
|
||||
<strong className="text-white/90">Pricing:</strong>{' '}
|
||||
Gartner Hype Cycle 2025, Forrester Wave MarTech 2025, oeffentliche
|
||||
Pricing-Pages, anonymisierte Kundengespraeche
|
||||
</li>
|
||||
<li>
|
||||
<strong className="text-white/90">Regulatorik:</strong>{' '}
|
||||
EDPB Cookie Guidelines 2/2023, DSK-Orientierungshilfe Telemedien 2024,
|
||||
CNIL Cookies-Recommendations
|
||||
</li>
|
||||
<li>
|
||||
<strong className="text-white/90">Updates:</strong>{' '}
|
||||
DB wird kontinuierlich gepflegt. Neue Kunden geben uns Ground-Truth
|
||||
fuer Kalibrierung.
|
||||
</li>
|
||||
</ul>
|
||||
</GlassCard>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
<ChatFAB />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import Navbar from '@/components/layout/Navbar'
|
||||
import Footer from '@/components/layout/Footer'
|
||||
import ChatFAB from '@/components/layout/ChatFAB'
|
||||
import PageHeader from '@/components/ui/PageHeader'
|
||||
import GlassCard from '@/components/ui/GlassCard'
|
||||
import FadeInView from '@/components/ui/FadeInView'
|
||||
import { Cookie, ShieldCheck, Mail, ArrowRight, CheckCircle2 } from 'lucide-react'
|
||||
|
||||
export default function SavingsScanPage() {
|
||||
const [url, setUrl] = useState('')
|
||||
const [email, setEmail] = useState('')
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
const [done, setDone] = useState(false)
|
||||
|
||||
async function handleSubmit(e: React.FormEvent) {
|
||||
e.preventDefault()
|
||||
if (!url || !email) return
|
||||
setSubmitting(true)
|
||||
try {
|
||||
// TODO: wire to compliance-check backend
|
||||
// For now: send to contact form / placeholder
|
||||
await new Promise(r => setTimeout(r, 800))
|
||||
setDone(true)
|
||||
} finally {
|
||||
setSubmitting(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
<main>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<PageHeader
|
||||
tag="KOSTENLOSER SAVING-SCAN"
|
||||
title="In 5 Minuten zur"
|
||||
titleHighlight="sechsstelligen Saving-Schaetzung"
|
||||
subtitle="URL eingeben — wir analysieren alle Cookies, identifizieren redundante Anbieter und schaetzen jaehrliche Einsparung. Kostenlos, ohne Login, ohne Vertrieb-Termin."
|
||||
/>
|
||||
</div>
|
||||
|
||||
<section className="py-12 sm:py-16">
|
||||
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
{!done ? (
|
||||
<GlassCard>
|
||||
<form onSubmit={handleSubmit} className="space-y-5">
|
||||
<div>
|
||||
<label htmlFor="url" className="block text-sm font-medium text-white/70 mb-2">
|
||||
Website-URL <span className="text-red-400">*</span>
|
||||
</label>
|
||||
<input
|
||||
id="url"
|
||||
type="url"
|
||||
required
|
||||
placeholder="https://www.ihre-firma.de"
|
||||
value={url}
|
||||
onChange={e => setUrl(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-lg bg-white/[0.04] border border-white/10
|
||||
text-white placeholder-white/30 focus:border-emerald-400 focus:outline-none"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-white/40">
|
||||
Wir crawlen die Startseite + automatisch erkennbare Unterseiten
|
||||
(DSI, Impressum, Cookie-Richtlinie).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium text-white/70 mb-2">
|
||||
E-Mail fuer den Bericht <span className="text-red-400">*</span>
|
||||
</label>
|
||||
<input
|
||||
id="email"
|
||||
type="email"
|
||||
required
|
||||
placeholder="ihr.name@firma.de"
|
||||
value={email}
|
||||
onChange={e => setEmail(e.target.value)}
|
||||
className="w-full px-4 py-3 rounded-lg bg-white/[0.04] border border-white/10
|
||||
text-white placeholder-white/30 focus:border-emerald-400 focus:outline-none"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-white/40">
|
||||
Bericht kommt als PDF + JSON. Die Mailadresse wird ausschliesslich
|
||||
fuer diesen Scan verwendet.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={submitting}
|
||||
className="inline-flex items-center gap-2 px-6 py-3 rounded-full
|
||||
bg-emerald-500 hover:bg-emerald-400 transition-colors
|
||||
text-enterprise-dark font-semibold disabled:opacity-50"
|
||||
>
|
||||
{submitting ? 'Wird gestartet …' : 'Saving-Scan starten'}
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</button>
|
||||
|
||||
<p className="text-xs text-white/40 pt-2">
|
||||
Wir analysieren ausschliesslich oeffentlich abrufbare Daten Ihrer Website.
|
||||
Keine Anmeldung, keine Daten werden gespeichert. Ergebnis innerhalb von
|
||||
~5 Minuten per E-Mail.
|
||||
</p>
|
||||
</form>
|
||||
</GlassCard>
|
||||
) : (
|
||||
<GlassCard>
|
||||
<div className="text-center py-6">
|
||||
<CheckCircle2 className="w-12 h-12 text-emerald-400 mx-auto mb-4" />
|
||||
<h3 className="text-xl font-bold mb-2">Scan gestartet</h3>
|
||||
<p className="text-white/60 mb-4">
|
||||
Wir analysieren Ihre Website jetzt. Der Bericht kommt in
|
||||
den naechsten 5 Minuten per E-Mail an <strong className="text-white/90">{email}</strong>.
|
||||
</p>
|
||||
<p className="text-xs text-white/40">
|
||||
Pruefen Sie auch Ihren Spam-Ordner.
|
||||
</p>
|
||||
</div>
|
||||
</GlassCard>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="py-16">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<FadeInView>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
<GlassCard>
|
||||
<Cookie className="w-8 h-8 text-emerald-400 mb-4" />
|
||||
<h3 className="text-lg font-bold mb-2">Was wir analysieren</h3>
|
||||
<ul className="text-sm text-white/60 space-y-2">
|
||||
<li>• Alle Cookies + Vendor-Identifikation</li>
|
||||
<li>• Funktionale Kategorisierung (Analytics, Werbung, CDN, …)</li>
|
||||
<li>• Redundanz-Detection ueber Kategorien</li>
|
||||
<li>• Cookie-Tiefenanalyse mit Tier-Inferenz</li>
|
||||
</ul>
|
||||
</GlassCard>
|
||||
<GlassCard delay={0.1}>
|
||||
<ShieldCheck className="w-8 h-8 text-emerald-400 mb-4" />
|
||||
<h3 className="text-lg font-bold mb-2">Was Sie bekommen</h3>
|
||||
<ul className="text-sm text-white/60 space-y-2">
|
||||
<li>• Geschaetzte jaehrliche Tooling-Kosten (Listpreis-Range)</li>
|
||||
<li>• Sparpotenzial pro Konsolidierungs-Kandidat</li>
|
||||
<li>• EU-Alternative pro US-Vendor</li>
|
||||
<li>• Schrems-II-Risiko-Bewertung</li>
|
||||
</ul>
|
||||
</GlassCard>
|
||||
<GlassCard delay={0.2}>
|
||||
<Mail className="w-8 h-8 text-emerald-400 mb-4" />
|
||||
<h3 className="text-lg font-bold mb-2">Was es kostet</h3>
|
||||
<ul className="text-sm text-white/60 space-y-2">
|
||||
<li>• <strong className="text-white">Erster Scan: kostenlos</strong></li>
|
||||
<li>• Kein Login, kein Vertriebs-Termin</li>
|
||||
<li>• Daten werden nicht gespeichert</li>
|
||||
<li>• PDF + JSON zum Download</li>
|
||||
</ul>
|
||||
</GlassCard>
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<Footer />
|
||||
<ChatFAB />
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
'use client'
|
||||
|
||||
import { TrendingDown, Cookie, Scale, AlertTriangle, ArrowRight } from 'lucide-react'
|
||||
import { t } from '@/lib/content'
|
||||
import { useApp } from '@/lib/context'
|
||||
import SectionHeading from '@/components/ui/SectionHeading'
|
||||
import GlassCard from '@/components/ui/GlassCard'
|
||||
import FadeInView from '@/components/ui/FadeInView'
|
||||
import GradientText from '@/components/ui/GradientText'
|
||||
|
||||
const pillarIcons = [Cookie, Scale, AlertTriangle]
|
||||
|
||||
export default function SavingsSection() {
|
||||
const { lang } = useApp()
|
||||
const i = t(lang)
|
||||
const s = (i as unknown as { savings: typeof i.problem & { promise: string; caseStudy: { label: string; headline: string; bullets: string[]; saving: string; side: string }; pillars: { title: string; description: string }[]; cta: string; ctaSecondary: string } }).savings
|
||||
|
||||
return (
|
||||
<section id="savings" className="py-24 sm:py-32 relative">
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-emerald-500/[0.02] to-transparent" />
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<SectionHeading
|
||||
tag={s.tag}
|
||||
title={s.title}
|
||||
titleHighlight={s.titleHighlight}
|
||||
subtitle={s.subtitle}
|
||||
/>
|
||||
|
||||
{/* PROMISE — high-impact one-liner */}
|
||||
<FadeInView>
|
||||
<div className="text-center mb-16">
|
||||
<div className="inline-flex items-center gap-3 px-6 py-3 rounded-full
|
||||
border border-emerald-400/30 bg-emerald-500/[0.08]">
|
||||
<TrendingDown className="w-5 h-5 text-emerald-400" />
|
||||
<span className="text-lg font-semibold text-emerald-300">
|
||||
{s.promise}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* CASE STUDY card */}
|
||||
<FadeInView>
|
||||
<div className="rounded-2xl border border-emerald-400/20 bg-gradient-to-br
|
||||
from-emerald-500/[0.06] to-white/[0.02] p-8 mb-16">
|
||||
<div className="mono-label text-emerald-400 mb-3 tracking-widest">
|
||||
{s.caseStudy.label}
|
||||
</div>
|
||||
<h3 className="text-2xl sm:text-3xl font-bold mb-6">
|
||||
{s.caseStudy.headline}
|
||||
</h3>
|
||||
<ul className="space-y-3 mb-8">
|
||||
{s.caseStudy.bullets.map((b: string, idx: number) => (
|
||||
<li key={idx} className="flex items-start gap-3 text-white/70">
|
||||
<span className="mt-1 w-1.5 h-1.5 rounded-full bg-emerald-400 flex-shrink-0" />
|
||||
<span className="text-sm">{b}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 pt-6 border-t border-white/10">
|
||||
<div>
|
||||
<div className="mono-label text-white/40 mb-1">JAEHRLICHES SPARPOTENZIAL</div>
|
||||
<div className="text-3xl font-bold">
|
||||
<GradientText>{s.caseStudy.saving}</GradientText>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="mono-label text-white/40 mb-1">PLUS</div>
|
||||
<div className="text-sm text-white/70">{s.caseStudy.side}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FadeInView>
|
||||
|
||||
{/* Pillars: HOW we do it */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-16">
|
||||
{s.pillars.map((p: { title: string; description: string }, idx: number) => {
|
||||
const Icon = pillarIcons[idx] || Cookie
|
||||
return (
|
||||
<GlassCard key={idx} delay={idx * 0.1}>
|
||||
<div className="w-12 h-12 rounded-xl bg-emerald-500/10 flex items-center justify-center mb-4">
|
||||
<Icon className="w-6 h-6 text-emerald-400" />
|
||||
</div>
|
||||
<h3 className="text-lg font-bold mb-2">{p.title}</h3>
|
||||
<p className="text-sm text-white/50">{p.description}</p>
|
||||
</GlassCard>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
{/* CTA */}
|
||||
<FadeInView>
|
||||
<div className="text-center">
|
||||
<a
|
||||
href="/savings-scan"
|
||||
className="inline-flex items-center gap-2 px-6 py-3 rounded-full
|
||||
bg-emerald-500 hover:bg-emerald-400 transition-colors
|
||||
text-enterprise-dark font-semibold"
|
||||
>
|
||||
{s.cta}
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</a>
|
||||
<a
|
||||
href="/savings-methodik"
|
||||
className="inline-flex items-center gap-2 px-6 py-3 ml-3
|
||||
text-white/60 hover:text-white transition-colors text-sm"
|
||||
>
|
||||
{s.ctaSecondary}
|
||||
</a>
|
||||
</div>
|
||||
</FadeInView>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Savings-Section content (DE + EN) — ausgelagert aus content.ts,
|
||||
* damit content.ts unter dem 500-LOC-Hard-Cap bleibt.
|
||||
*/
|
||||
|
||||
export const savingsDE = {
|
||||
tag: '03 / NEBENEFFEKT: COST-OPTIMIZATION',
|
||||
title: 'Compliance entdeckt',
|
||||
titleHighlight: 'sechsstellige Einsparungen.',
|
||||
subtitle:
|
||||
'Beim Cookie-Audit identifizieren wir Anbieter, die das Gleiche tun. ' +
|
||||
'Pro Anbieter eine Kosten-Schaetzung auf Basis von Tier-Inferenz ' +
|
||||
'(Cookie-Anzahl, Premium-Feature-Detection, Drittanbieter-Quote).',
|
||||
promise: 'Software bezahlt sich beim ERSTEN Scan.',
|
||||
caseStudy: {
|
||||
label: 'CASE-STUDY: DAX-Automotive-Konzern',
|
||||
headline: '90 Cookie-Anbieter → 25 nach Konsolidierung',
|
||||
bullets: [
|
||||
'5 Web-Analytics-Tools (Adobe Analytics, Content Square, Dynatrace, …) → 1 Matomo Pro',
|
||||
'10 Retargeting-Pixel (Criteo, Adform, Outbrain, Taboola, Meta, …) → 3 Kern-Kanaele',
|
||||
'5 CDN/Speed-Tools (Akamai, AWS, Baqend, Speedkit, SpeedCurve) → IONOS Cloud + Bunny',
|
||||
],
|
||||
saving: '€500k–€3M / Jahr',
|
||||
side: 'Plus 100% DSGVO-Konformitaet ohne Schrems-II-Risiko',
|
||||
},
|
||||
pillars: [
|
||||
{
|
||||
title: 'Tier-Inferenz aus Cookie-Footprint',
|
||||
description:
|
||||
'>30 Cookies = Enterprise. Premium-Feature-Cookies (s_target_qa, _ab_test, ' +
|
||||
'aam_uuid) markieren Add-on-Module. Drittanbieter-Quote + Lebensdauer ' +
|
||||
'verraten Tracking-Intensitaet.',
|
||||
},
|
||||
{
|
||||
title: 'Konsolidierungs-Vorschlaege',
|
||||
description:
|
||||
'Pro Funktions-Kategorie (Analytics, Werbung, CDN, …) ein konkreter ' +
|
||||
'EU-Ersatz inkl. Listpreis. Multi-Funktions-Tools (SAP CX, Matomo Pro, ' +
|
||||
'IONOS Cloud) ersetzen mehrere Anbieter gleichzeitig.',
|
||||
},
|
||||
{
|
||||
title: 'Ehrliche Caveats',
|
||||
description:
|
||||
'Bekannte Gruende fuer Mehrfach-Einsatz (Saisonal, A/B-Test, Regional) ' +
|
||||
'werden explizit aufgefuehrt — kein Pseudo-Saving. Konzern-Konditionen ' +
|
||||
'liegen ueblicherweise 30-50% unter Listpreis (transparent ausgewiesen).',
|
||||
},
|
||||
],
|
||||
cta: 'Kostenlosen 5-Min-Saving-Scan starten',
|
||||
ctaSecondary: 'Methodik ansehen',
|
||||
}
|
||||
|
||||
export const savingsEN = {
|
||||
tag: '03 / SIDE EFFECT: COST OPTIMIZATION',
|
||||
title: 'Compliance reveals',
|
||||
titleHighlight: 'six-figure savings.',
|
||||
subtitle:
|
||||
'During the cookie audit we identify vendors that do the same thing. ' +
|
||||
'Per vendor we infer the pricing tier from cookie footprint (count, ' +
|
||||
'premium-feature detection, third-party ratio).',
|
||||
promise: 'The software pays for itself with the FIRST scan.',
|
||||
caseStudy: {
|
||||
label: 'CASE STUDY: DAX automotive group',
|
||||
headline: '90 cookie vendors → 25 after consolidation',
|
||||
bullets: [
|
||||
'5 Web-Analytics tools (Adobe Analytics, Content Square, Dynatrace, …) → 1 Matomo Pro',
|
||||
'10 retargeting pixels (Criteo, Adform, Outbrain, Taboola, Meta, …) → 3 core channels',
|
||||
'5 CDN/Speed tools (Akamai, AWS, Baqend, Speedkit, SpeedCurve) → IONOS Cloud + Bunny',
|
||||
],
|
||||
saving: '€500k–€3M / year',
|
||||
side: 'Plus 100% GDPR-compliant without Schrems II risk',
|
||||
},
|
||||
pillars: [
|
||||
{
|
||||
title: 'Tier inference from cookie footprint',
|
||||
description:
|
||||
'>30 cookies = enterprise. Premium-feature cookies (s_target_qa, _ab_test, ' +
|
||||
'aam_uuid) mark add-on modules. Third-party share + lifetime reveal ' +
|
||||
'tracking intensity.',
|
||||
},
|
||||
{
|
||||
title: 'Consolidation suggestions',
|
||||
description:
|
||||
'Per functional category (analytics, advertising, CDN, …) a concrete ' +
|
||||
'EU substitute incl. list price. Multi-function tools (SAP CX, Matomo Pro, ' +
|
||||
'IONOS Cloud) replace multiple vendors at once.',
|
||||
},
|
||||
{
|
||||
title: 'Honest caveats',
|
||||
description:
|
||||
'Known reasons for multi-vendor use (seasonal, A/B testing, regional) ' +
|
||||
'are stated explicitly — no pseudo-savings. Group discounts typically ' +
|
||||
'30–50% below list price (transparently disclosed).',
|
||||
},
|
||||
],
|
||||
cta: 'Run the free 5-min savings scan',
|
||||
ctaSecondary: 'See the methodology',
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import { savingsDE, savingsEN } from './content.savings'
|
||||
|
||||
type Lang = 'de' | 'en'
|
||||
type TerminalType = 'input' | 'output' | 'signal'
|
||||
type Status = 'neutral' | 'success' | 'warning'
|
||||
@@ -64,8 +66,9 @@ const de = {
|
||||
{ label: 'Status', value: 'Aktionsplan erstellt', status: 'success' as Status },
|
||||
],
|
||||
},
|
||||
savings: savingsDE,
|
||||
deterministic: {
|
||||
tag: '03 / VERTRAUENSWÜRDIG DURCH DESIGN',
|
||||
tag: '04 / VERTRAUENSWÜRDIG DURCH DESIGN',
|
||||
title: 'Keine Halluzinationen.',
|
||||
titleHighlight: 'Konstruktionsbedingt.',
|
||||
subtitle: 'Jede Compliance-Entscheidung ist auf eine konkrete Rechtsquelle rückführbar.',
|
||||
@@ -296,8 +299,9 @@ const en = {
|
||||
{ label: 'Status', value: 'Action plan created', status: 'success' as Status },
|
||||
],
|
||||
},
|
||||
savings: savingsEN,
|
||||
deterministic: {
|
||||
tag: '03 / TRUSTWORTHY BY DESIGN',
|
||||
tag: '04 / TRUSTWORTHY BY DESIGN',
|
||||
title: 'No hallucinations.',
|
||||
titleHighlight: 'By design.',
|
||||
subtitle: 'Every compliance decision is traceable to a concrete legal source.',
|
||||
|
||||
Reference in New Issue
Block a user