Website-Analyse für webklar.com: Sie-Fassung des Banners, fester Messdienst-Eintrag, Auswertung fürs WOMS

- Messskript: data-variant="eigen" zeigt eine eigene Banner-Fassung (Sie-Form, WEBklar misst selbst,
  BANNER_VERSION_EIGEN 2026-10-17); Kunden-Websites bleiben bei der Fassung 2026-10-02.
- config.analyse.eigeneWebsite: fester Schlüssel und Domains von webklar.com; ensureEigeneWebsite zieht den
  Eintrag im Messdienst täglich nach (aktiv: false schaltet ab). Kein Kunde, kein Abo, keine Tickets.
- /api/admin/analyse-eigen (jeder Mitarbeiter): Kennzahlen 7/30/90 Tage und Heatmap-Link auf webklar.com.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-17 18:34:06 +00:00
1 parent f3f8ac3777
commit 9ed295946c
10 files changed
+294 -20

No files matched your search

+50 -3
View File
@@ -7,7 +7,7 @@ import { dirname, join } from 'node:path';
import {
vpClass, cleanPath, refHost, cssPath, contactKind, readConsent, contrastOk, escapeHtml,
} from '../client/core.js';
import { BANNER_VERSION, BANNER_TEXT, BANNER_LINK_LABEL, BANNER_ARIA, SETTINGS_LABEL } from '../client/core.js';
import { BANNER_VERSION, BANNER_TEXT, BANNER_LINK_LABEL, BANNER_ARIA, SETTINGS_LABEL, BANNER_VERSION_EIGEN, BANNER_TEXT_EIGEN, bannerFor } from '../client/core.js';
import { buildAll } from '../client/build.js';
const BV = '2026-10-02';
@@ -170,12 +170,12 @@ function findAll(root, pred) { const out = []; walk(root, (n) => { if (pred(n))
const btn = (root, label) => findAll(root, (n) => n.tagName === 'BUTTON' && n.textContent === label)[0];
const settingsBtn = (h) => findAll(h.body, (n) => n.tagName === 'BUTTON' && n.attrs['aria-label'] === SETTINGS_LABEL)[0];
function harness({ gpc, dnt, stored, search = '', src = 'https://project.webklar.com/a/w.js', withConsentLink = false, bannerHeight = 0, bodyPad } = {}) {
function harness({ gpc, dnt, stored, search = '', src = 'https://project.webklar.com/a/w.js', withConsentLink = false, bannerHeight = 0, bodyPad, variant } = {}) {
const sent = []; const reads = { referrer: 0, innerWidth: 0 }; const beacon = []; const fetches = []; const store = {}; let now = 1_700_000_000_000;
if (stored) store['wk-consent'] = JSON.stringify(stored);
const body = makeEl('body'); if (bodyPad !== undefined) body.style.paddingBottom = bodyPad; const html = makeEl('html');
const timers = [];
const script = makeEl('script'); script.setAttribute('src', src); script.setAttribute('data-site', 'abcdef0123456789abcd'); script.setAttribute('data-color', '#0a5a8a'); script.src = src;
const script = makeEl('script'); script.setAttribute('src', src); script.setAttribute('data-site', 'abcdef0123456789abcd'); script.setAttribute('data-color', '#0a5a8a'); if (variant !== undefined) script.setAttribute('data-variant', variant); script.src = src;
const docL = {}; const winL = {};
const link = withConsentLink ? makeEl('a') : null; if (link) link.setAttribute('data-webklar-consent', '');
const injected = [];
@@ -641,3 +641,50 @@ test('w.js: ohne Einwilligung oder nach Widerruf kein fruehes en', () => {
g.ck(lnk('/kontakt'));
assert.equal(enCount(g), 0);
});
// ---------- Variante "eigen" (WEBklars eigene Websites, z. B. webklar.com) ----------
test('core: bannerFor und readConsent je Fassung', () => {
assert.deepEqual(bannerFor('eigen'), { version: BANNER_VERSION_EIGEN, text: BANNER_TEXT_EIGEN });
for (const v of ['', 'kunde', 'EIGEN', 'x', undefined]) assert.deepEqual(bannerFor(v), { version: BANNER_VERSION, text: BANNER_TEXT });
assert.equal(BANNER_VERSION_EIGEN, '2026-10-17');
assert.notEqual(BANNER_VERSION_EIGEN, BANNER_VERSION);
const now = 1_700_000_000_000;
const st = (o) => ({ getItem: () => JSON.stringify(o) });
assert.equal(readConsent(st({ v: 1, a: 'accept', bv: BV, t: now }), now, BANNER_VERSION_EIGEN), null, 'Kunden-Fassung gilt nicht fuer eigen');
assert.equal(readConsent(st({ v: 1, a: 'accept', bv: BANNER_VERSION_EIGEN, t: now }), now, BANNER_VERSION_EIGEN).a, 'accept');
assert.equal(readConsent(st({ v: 1, a: 'accept', bv: BANNER_VERSION_EIGEN, t: now }), now), null, 'ohne Fassung gilt die Kunden-Fassung');
});
test('core: Banner-Text eigen (Sie-Form, ohne Auftragsverarbeiter)', () => {
assert.match(BANNER_TEXT_EIGEN, /^Um unsere Website zu verbessern, zählen wir Seitenaufrufe mit Land und Gerätetyp, ohne Kennung\./);
assert.match(BANNER_TEXT_EIGEN, /Wir messen selbst auf unserem Server in Deutschland, ohne Cookies und ohne Werbung\./);
assert.match(BANNER_TEXT_EIGEN, /Nach „Ablehnen“ zählen wir nur noch, dass Sie abgelehnt haben\./);
assert.match(BANNER_TEXT_EIGEN, /über „Datenschutz-Einstellungen“ mit Wirkung für die Zukunft widerrufen\. Details: $/);
assert.doesNotMatch(BANNER_TEXT_EIGEN, /\b(Du|Dein|Deine|Deiner|Dich|Dir)\b/);
assert.doesNotMatch(BANNER_TEXT_EIGEN, /betreibt für uns/);
});
test('w.js: data-variant="eigen" => Sie-Text, eigene Fassung im Speicher', () => {
const h = harness({ variant: 'eigen' });
const host = hostEl(h);
const p = findAll(host.shadow, (n) => n.tagName === 'P')[0];
assert.ok(p.textContent.startsWith(BANNER_TEXT_EIGEN));
assert.ok(!p.textContent.startsWith(BANNER_TEXT));
btn(host.shadow, 'Annehmen').click();
assert.deepEqual(JSON.parse(h.store['wk-consent']), { v: 1, a: 'accept', bv: BANNER_VERSION_EIGEN, t: 1_700_000_000_000 });
assert.deepEqual(h.types(), ['pv', 'bn:shown', 'bn:accept', 'cx']);
});
test('w.js: eigen fragt neu bei Wahl aus der Kunden-Fassung, gilt mit eigener Fassung', () => {
const alt = harness({ variant: 'eigen', stored: { v: 1, a: 'accept', bv: BV, t: 1_700_000_000_000 - 1000 } });
assert.ok(hostEl(alt), 'Banner erscheint erneut');
const ok = harness({ variant: 'eigen', stored: { v: 1, a: 'reject', bv: BANNER_VERSION_EIGEN, t: 1_700_000_000_000 - 1000 } });
assert.equal(hostEl(ok), undefined);
assert.deepEqual(ok.types(), []);
});
test('w.js: unbekannte Variante => Kunden-Fassung', () => {
const h = harness({ variant: 'sonstwas' });
const p = findAll(hostEl(h).shadow, (n) => n.tagName === 'P')[0];
assert.ok(p.textContent.startsWith(BANNER_TEXT));
});