forlage
This commit is contained in:
287
SHK-Scorecard.dc.html
Normal file
287
SHK-Scorecard.dc.html
Normal file
@@ -0,0 +1,287 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<script src="./support.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<x-dc>
|
||||
<helmet>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="crossorigin" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+3:wght@400;600;700&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
*, *::before, *::after { box-sizing: border-box; }
|
||||
body { margin: 0; background: #F4F6F8; color: #1A1D21; font-family: 'Source Sans 3', 'Segoe UI', system-ui, sans-serif; font-size: 17px; line-height: 1.55; -webkit-font-smoothing: antialiased; }
|
||||
a { color: #0B4F6C; text-decoration: underline; text-underline-offset: 3px; }
|
||||
a:hover { color: #08384D; }
|
||||
:focus-visible { outline: 3px solid #C9451C; outline-offset: 2px; }
|
||||
p { text-wrap: pretty; }
|
||||
h1, h2, h3 { text-wrap: balance; }
|
||||
</style>
|
||||
</helmet>
|
||||
|
||||
<div style="background:#F4F6F8;min-height:100vh">
|
||||
|
||||
<header style="background:#0B4F6C;color:#FFFFFF;padding:clamp(24px,3.5vw,44px) clamp(16px,3vw,32px)">
|
||||
<div style="max-width:1280px;margin:0 auto">
|
||||
<p style="margin:0 0 10px;font-size:14px;letter-spacing:.12em;text-transform:uppercase;color:#9FC0CF;font-weight:700">Akquise-Werkzeug · SHK-Website-Analyse</p>
|
||||
<h1 style="margin:0 0 12px;font-size:clamp(1.75rem,3.4vw,2.5rem);line-height:1.14;font-weight:700;letter-spacing:-0.02em">Scorecard: 40 Kriterien, 80 Punkte</h1>
|
||||
<p style="margin:0 0 22px;font-size:18px;color:#C6DAE4;max-width:52em">Für das Erstgespräch: Bestandsseite des Interessenten durchgehen, Punkte vergeben, Ergebnis zeigen. Der Branchenschnitt liegt bei 24 Prozent — die meisten Gespräche verkaufen sich hier von selbst.</p>
|
||||
<div style="display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end">
|
||||
<label style="display:flex;flex-direction:column;gap:5px;font-size:14px;color:#9FC0CF;font-weight:600">Geprüfte Website
|
||||
<input type="text" value="{{ domain }}" onChange="{{ setzeDomain }}" placeholder="beispiel-shk.de" style="padding:10px 13px;border:1px solid rgba(255,255,255,.3);border-radius:3px;background:rgba(255,255,255,.12);color:#FFFFFF;font-size:17px;font-weight:600;min-width:240px" />
|
||||
</label>
|
||||
<label style="display:flex;flex-direction:column;gap:5px;font-size:14px;color:#9FC0CF;font-weight:600">Geprüft am
|
||||
<input type="text" value="{{ datum }}" onChange="{{ setzeDatum }}" placeholder="16.08.2026" style="padding:10px 13px;border:1px solid rgba(255,255,255,.3);border-radius:3px;background:rgba(255,255,255,.12);color:#FFFFFF;font-size:17px;font-weight:600;min-width:150px" />
|
||||
</label>
|
||||
<button type="button" onClick="{{ zuruecksetzen }}" style="padding:11px 20px;border-radius:3px;border:1.5px solid rgba(255,255,255,.5);background:none;color:#FFFFFF;font-size:16px;font-weight:600;cursor:pointer" style-hover="background:rgba(255,255,255,.14)">Alles zurücksetzen</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div style="max-width:1280px;margin:0 auto;padding:clamp(24px,3vw,40px) clamp(16px,3vw,32px) clamp(40px,5vw,72px);display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:clamp(20px,3vw,32px);align-items:start">
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:20px;min-width:0">
|
||||
<sc-for list="{{ bloecke }}" as="b" hint-placeholder-count="6">
|
||||
<section style="background:#FFFFFF;border:1px solid #DDE2E7;border-radius:5px;overflow:hidden">
|
||||
<div style="padding:16px 20px;background:#F4F6F8;border-bottom:1px solid #DDE2E7;display:flex;justify-content:space-between;gap:16px;align-items:baseline;flex-wrap:wrap">
|
||||
<div>
|
||||
<p style="margin:0;font-size:19px;font-weight:700">{{ b.titel }}</p>
|
||||
<p style="margin:0;font-size:15px;color:#5A6169">{{ b.unter }}</p>
|
||||
</div>
|
||||
<p style="margin:0;font-size:17px;font-weight:700;color:#0B4F6C;font-variant-numeric:tabular-nums;white-space:nowrap">{{ b.stand }}</p>
|
||||
</div>
|
||||
<sc-for list="{{ b.zeilen }}" as="z" hint-placeholder-count="8">
|
||||
<div style="display:flex;gap:16px;align-items:center;justify-content:space-between;padding:12px 20px;border-bottom:1px solid #EDF1F4;flex-wrap:wrap">
|
||||
<p style="margin:0;font-size:16px;flex:1 1 260px;min-width:0"><strong style="color:#5A6169;font-variant-numeric:tabular-nums">{{ z.id }}</strong> {{ z.text }}</p>
|
||||
<div style="display:flex;gap:6px;flex:none">
|
||||
<sc-for list="{{ z.optionen }}" as="o" hint-placeholder-count="3">
|
||||
<button type="button" onClick="{{ o.waehlen }}" aria-label="{{ o.aria }}" style="{{ o.stil }}">{{ o.label }}</button>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</section>
|
||||
</sc-for>
|
||||
</div>
|
||||
|
||||
<aside style="position:sticky;top:20px;display:flex;flex-direction:column;gap:16px">
|
||||
<div style="background:#FFFFFF;border:1px solid #DDE2E7;border-radius:5px;padding:24px">
|
||||
<p style="margin:0 0 4px;font-size:14px;letter-spacing:.1em;text-transform:uppercase;color:#5A6169;font-weight:700">Gesamtergebnis</p>
|
||||
<p style="margin:0 0 2px;font-size:clamp(2.5rem,6vw,3.5rem);font-weight:700;line-height:1;color:#0B4F6C;font-variant-numeric:tabular-nums">{{ gesamt }}</p>
|
||||
<p style="margin:0 0 18px;font-size:17px;color:#5A6169">von 80 Punkten · {{ prozent }}</p>
|
||||
<div style="height:10px;background:#EDF1F4;border-radius:100px;overflow:hidden;margin-bottom:8px">
|
||||
<div style="height:10px;background:{{ bandFarbe }};width:{{ balken }};transition:width .3s ease"></div>
|
||||
</div>
|
||||
<p style="margin:0 0 18px;font-size:18px;font-weight:700;color:{{ bandFarbe }}">{{ bandTitel }}</p>
|
||||
<p style="margin:0;font-size:16px;color:#3D4650">{{ bandText }}</p>
|
||||
</div>
|
||||
|
||||
<div style="background:#FFFFFF;border:1px solid #DDE2E7;border-radius:5px;padding:24px">
|
||||
<p style="margin:0 0 16px;font-size:14px;letter-spacing:.1em;text-transform:uppercase;color:#5A6169;font-weight:700">Nach Bereich</p>
|
||||
<div style="display:flex;flex-direction:column;gap:14px">
|
||||
<sc-for list="{{ bloecke }}" as="b" hint-placeholder-count="6">
|
||||
<div>
|
||||
<div style="display:flex;justify-content:space-between;gap:12px;font-size:16px;margin-bottom:5px">
|
||||
<span style="font-weight:600">{{ b.kurz }}</span>
|
||||
<span style="font-variant-numeric:tabular-nums;color:#5A6169">{{ b.stand }}</span>
|
||||
</div>
|
||||
<div style="height:7px;background:#EDF1F4;border-radius:100px;overflow:hidden">
|
||||
<div style="height:7px;background:#0B4F6C;width:{{ b.balken }};transition:width .3s ease"></div>
|
||||
</div>
|
||||
</div>
|
||||
</sc-for>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<sc-if value="{{ hatKo }}" hint-placeholder-val="{{ false }}">
|
||||
<div style="background:#FBF0F0;border:1px solid #E8B9BD;border-left:4px solid #C1121F;border-radius:0 5px 5px 0;padding:22px">
|
||||
<p style="margin:0 0 8px;font-size:18px;font-weight:700;color:#B0111D">K.-o.-Punkte im Bereich Recht</p>
|
||||
<p style="margin:0 0 12px;font-size:16px;color:#3D4650">Diese Punkte sind keine Optimierung, sondern Abmahnrisiko. Sie gehören ins Angebot, egal wie der Rest ausfällt.</p>
|
||||
<ul style="margin:0;padding-left:20px;display:flex;flex-direction:column;gap:7px;font-size:16px">
|
||||
<sc-for list="{{ koListe }}" as="k" hint-placeholder-count="3">
|
||||
<li>{{ k.text }}</li>
|
||||
</sc-for>
|
||||
</ul>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<sc-if value="{{ hatLuecken }}" hint-placeholder-val="{{ false }}">
|
||||
<div style="background:#FFFFFF;border:1px solid #DDE2E7;border-radius:5px;padding:24px">
|
||||
<p style="margin:0 0 6px;font-size:14px;letter-spacing:.1em;text-transform:uppercase;color:#5A6169;font-weight:700">Gesprächsstoff</p>
|
||||
<p style="margin:0 0 14px;font-size:16px;color:#3D4650">{{ lueckenZahl }} Kriterien stehen auf null. Die ersten fünf sind meist die, bei denen der Interessent im Gespräch selbst nickt.</p>
|
||||
<ol style="margin:0;padding-left:20px;display:flex;flex-direction:column;gap:8px;font-size:16px">
|
||||
<sc-for list="{{ luecken }}" as="l" hint-placeholder-count="5">
|
||||
<li><strong style="color:#5A6169;font-variant-numeric:tabular-nums">{{ l.id }}</strong> {{ l.text }}</li>
|
||||
</sc-for>
|
||||
</ol>
|
||||
</div>
|
||||
</sc-if>
|
||||
|
||||
<p style="margin:0;font-size:15px;color:#5A6169">Eingaben bleiben in diesem Browser gespeichert — Sie können das Fenster während des Termins schließen. <a href="SHK-Startseite.dc.html">Zur Muster-Website</a> · <a href="SHK-Pitch.dc.html">Zum Pitch-Deck</a></p>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</x-dc>
|
||||
<script type="text/x-dc" data-dc-script data-props="{}">
|
||||
class Component extends DCLogic {
|
||||
state = { p: {}, domain: '', datum: '' };
|
||||
|
||||
katalog = [
|
||||
{ kurz: 'A · Trust', titel: 'A · Erster Eindruck & Trust', unter: 'max. 16 Punkte', zeilen: [
|
||||
['A1', 'Sterne und Bewertungsanzahl oberhalb der Falzkante sichtbar'],
|
||||
['A2', 'Gesicht: Inhaber- oder Teamfoto im oberen Seitendrittel'],
|
||||
['A3', 'Headline nennt Nutzen und Ort, nicht nur den Firmennamen'],
|
||||
['A4', 'Echte eigene Fotos statt Stock — Baustelle, Team, Fahrzeug'],
|
||||
['A5', 'Mindestens drei namentliche Kundenstimmen mit Ort'],
|
||||
['A6', 'Siegel und Zertifikate mit Erklärung, was sie bedeuten'],
|
||||
['A7', 'Konkrete Zahlen statt Adjektive: Projekte, Jahre, Reaktionszeit'],
|
||||
['A8', 'Externe Validierung: Award, Presse, prüfbare Registriernummer']
|
||||
] },
|
||||
{ kurz: 'B · Conversion', titel: 'B · Erreichbarkeit & Conversion', unter: 'max. 16 Punkte', zeilen: [
|
||||
['B1', 'Telefonnummer als tel:-Link, sticky auf Mobil'],
|
||||
['B2', 'Öffnungszeiten sichtbar, idealerweise mit Live-Status'],
|
||||
['B3', 'Notdienst-Kanal getrennt und prominent, mit ehrlichen Zeiten'],
|
||||
['B4', 'WhatsApp-Kanal vorhanden'],
|
||||
['B5', 'Rückrufformular mit Feld „Wann sind Sie erreichbar?"'],
|
||||
['B6', 'Getrennte Anfragestrecken je Gewerk statt Universalformular'],
|
||||
['B7', 'Mehrstufiger Konfigurator oder Rechner als eigener CTA'],
|
||||
['B8', 'Echte Online-Terminbuchung — Kalender, nicht Formular']
|
||||
] },
|
||||
{ kurz: 'C · Inhalt', titel: 'C · Inhalt & Struktur', unter: 'max. 16 Punkte', zeilen: [
|
||||
['C1', 'Eigene URL je Leistung, nicht nur Startseiten-Sektionen'],
|
||||
['C2', 'Navigation in Laiensprache, höchstens sieben Hauptpunkte'],
|
||||
['C3', 'Wärmepumpe als eigenes Themencluster inklusive Förderung'],
|
||||
['C4', 'Eigene Förderseite mit Standdatum und Disclaimer'],
|
||||
['C5', 'Referenzen mit Vorher/Nachher'],
|
||||
['C6', 'FAQ, das echte Kundenfragen beantwortet'],
|
||||
['C7', 'Kosten- oder Preisorientierung in irgendeiner Form vorhanden'],
|
||||
['C8', 'Standortseiten mit ortsspezifischer Substanz']
|
||||
] },
|
||||
{ kurz: 'D · Karriere', titel: 'D · Karriere', unter: 'max. 8 Punkte', zeilen: [
|
||||
['D1', 'Karriere im Hauptmenü'],
|
||||
['D2', '„Ausbildung" getrennt von „Jobs", in eigener Ansprache'],
|
||||
['D3', 'Konkrete offene Stellen statt „Initiativbewerbung willkommen"'],
|
||||
['D4', 'Quick-Bewerbung: höchstens vier Felder, keine Anschreiben-Pflicht']
|
||||
] },
|
||||
{ kurz: 'E · Technik', titel: 'E · Technik & Auffindbarkeit', unter: 'max. 12 Punkte', zeilen: [
|
||||
['E1', 'Core Web Vitals mobil grün: LCP ≤ 2,5 s · INP ≤ 200 ms · CLS ≤ 0,1'],
|
||||
['E2', 'Alle Assets lokal gehostet — Fonts, Icons, JavaScript'],
|
||||
['E3', 'Schema Plumber + HVACBusiness, Service je Leistung, BreadcrumbList'],
|
||||
['E4', 'Google-Unternehmensprofil vollständig, NAP identisch zur Website'],
|
||||
['E5', 'Title und H1 mit Leistung und Ort auf jeder Leistungsseite'],
|
||||
['E6', 'Barrierefreiheits-Baseline: Kontrast, Tastatur, Alt-Texte, Fokus']
|
||||
] },
|
||||
{ kurz: 'F · Recht', titel: 'F · Recht — jedes Kriterium ist K.o.', unter: 'max. 12 Punkte', ko: true, zeilen: [
|
||||
['F1', 'OS-Plattform-Link entfernt (Pflicht seit 20.07.2025)'],
|
||||
['F2', 'Impressum vollständig inkl. HWK, Berufsbezeichnung, HwO-Link, USt-IdNr.'],
|
||||
['F3', 'Consent-Banner mit gleichwertigem Ablehnen-Button auf erster Ebene'],
|
||||
['F4', 'Kein einwilligungspflichtiges Skript vor der Einwilligung'],
|
||||
['F5', 'Bewertungen mit Hinweis zur Echtheitsprüfung (§ 5b Abs. 3 UWG)'],
|
||||
['F6', 'Preise brutto inkl. MwSt., Förderaussagen mit Disclaimer und Standdatum']
|
||||
] }
|
||||
];
|
||||
|
||||
stufen = [
|
||||
{ w: 0, label: '0', aria: 'fehlt', farbe: '#C1121F' },
|
||||
{ w: 1, label: '1', aria: 'teilweise', farbe: '#A9760F' },
|
||||
{ w: 2, label: '2', aria: 'gut gelöst', farbe: '#0F6B33' }
|
||||
];
|
||||
|
||||
componentDidMount() {
|
||||
try {
|
||||
const roh = window.localStorage.getItem('shk-scorecard-v1');
|
||||
if (roh) this.setState(JSON.parse(roh));
|
||||
} catch (e) { /* kein Speicher verfügbar */ }
|
||||
}
|
||||
|
||||
sichern(next) {
|
||||
try { window.localStorage.setItem('shk-scorecard-v1', JSON.stringify(next)); } catch (e) { /* ignorieren */ }
|
||||
}
|
||||
|
||||
setzen(id, wert) {
|
||||
this.setState(s => {
|
||||
const p = Object.assign({}, s.p);
|
||||
if (p[id] === wert) { delete p[id]; } else { p[id] = wert; }
|
||||
const next = { p: p, domain: s.domain, datum: s.datum };
|
||||
this.sichern(next);
|
||||
return { p: p };
|
||||
});
|
||||
}
|
||||
|
||||
feld(name, wert) {
|
||||
this.setState(s => {
|
||||
const next = { p: s.p, domain: s.domain, datum: s.datum };
|
||||
next[name] = wert;
|
||||
this.sichern(next);
|
||||
return { [name]: wert };
|
||||
});
|
||||
}
|
||||
|
||||
knopf(aktiv, farbe) {
|
||||
return aktiv
|
||||
? 'width:40px;height:38px;border-radius:3px;border:1.5px solid ' + farbe + ';background:' + farbe + ';color:#FFFFFF;font-size:16px;font-weight:700;cursor:pointer'
|
||||
: 'width:40px;height:38px;border-radius:3px;border:1.5px solid #DDE2E7;background:#FFFFFF;color:#8A939C;font-size:16px;font-weight:700;cursor:pointer';
|
||||
}
|
||||
|
||||
renderVals() {
|
||||
const p = this.state.p;
|
||||
let gesamt = 0, maxGesamt = 0;
|
||||
const ko = [], luecken = [];
|
||||
|
||||
const bloecke = this.katalog.map(b => {
|
||||
let punkte = 0;
|
||||
const max = b.zeilen.length * 2;
|
||||
const zeilen = b.zeilen.map(z => {
|
||||
const id = z[0], text = z[1];
|
||||
const wert = p[id];
|
||||
if (typeof wert === 'number') punkte += wert;
|
||||
if (wert === 0) {
|
||||
if (b.ko) ko.push({ text: id + ' — ' + text });
|
||||
else luecken.push({ id: id, text: text });
|
||||
}
|
||||
return {
|
||||
id: id, text: text,
|
||||
optionen: this.stufen.map(st => ({
|
||||
label: st.label,
|
||||
aria: id + ': ' + st.aria,
|
||||
stil: this.knopf(wert === st.w, st.farbe),
|
||||
waehlen: () => this.setzen(id, st.w)
|
||||
}))
|
||||
};
|
||||
});
|
||||
gesamt += punkte; maxGesamt += max;
|
||||
return { kurz: b.kurz, titel: b.titel, unter: b.unter, zeilen: zeilen,
|
||||
stand: punkte + ' / ' + max, balken: Math.round((punkte / max) * 100) + '%' };
|
||||
});
|
||||
|
||||
let band = { titel: 'Branchendurchschnitt', farbe: '#C1121F', text: 'Hier liegt der Median der 500 im Webseiten-Check Handwerk 2025 getesteten Seiten. Diese Website leistet aktuell nichts, was ein Wettbewerber nicht auch hätte — der Neubau rechnet sich am schnellsten.' };
|
||||
if (gesamt > 20) band = { titel: 'Solide, aber ohne Wettbewerbsvorteil', farbe: '#A9760F', text: 'Das Handwerkliche stimmt, es fehlt der Grund, warum jemand hier anfragt statt beim Nachbarbetrieb. Meist reichen drei bis fünf gezielte Ergänzungen statt eines Relaunches.' };
|
||||
if (gesamt > 40) band = { titel: 'Unter den besten 10 % der Nische', farbe: '#0F6B33', text: 'Diese Seite ist besser als fast alles im Wettbewerbsumfeld. Sinnvoll sind jetzt Conversion-Details: Erreichbarkeitslogik, Rechner, Terminbuchung — und die Rechtspunkte.' };
|
||||
if (gesamt > 60) band = { titel: 'Zielkorridor der Vorlage', farbe: '#0F6B33', text: 'Sehr gut. Ab hier bringt Wartung mehr als Umbau: Fördersätze, Zertifikatslaufzeiten, Stellenanzeigen und Bewertungsakquise aktuell halten.' };
|
||||
|
||||
return {
|
||||
bloecke: bloecke,
|
||||
gesamt: gesamt,
|
||||
prozent: Math.round((gesamt / maxGesamt) * 100) + ' %',
|
||||
balken: Math.round((gesamt / maxGesamt) * 100) + '%',
|
||||
bandTitel: band.titel, bandFarbe: band.farbe, bandText: band.text,
|
||||
hatKo: ko.length > 0, koListe: ko,
|
||||
hatLuecken: luecken.length > 0,
|
||||
lueckenZahl: luecken.length + ko.length,
|
||||
luecken: luecken.slice(0, 5),
|
||||
domain: this.state.domain,
|
||||
datum: this.state.datum,
|
||||
setzeDomain: e => this.feld('domain', e.target.value),
|
||||
setzeDatum: e => this.feld('datum', e.target.value),
|
||||
zuruecksetzen: () => { this.sichern({ p: {}, domain: '', datum: '' }); this.setState({ p: {}, domain: '', datum: '' }); }
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user