QR-Links
Zweck
QrLink modelliert einen brandbaren, getrackten QR-Code. Pro Link werden ein eindeutiger Slug (URL-ID), eine Ziel-URL, ein optionales Logo und ein vollständig editierbarer Style (Punkt-/Eck-Stil, Farben, Hintergrund, Fußtext) gepflegt. Anwender (Vertrieb, Marketing, Innendienst) erzeugen QR-Codes z. B. für:
- Marketing-Kampagnen mit einheitlicher Optik (Sommer-Aktion, Messe-Stand)
- Aufkleber an Geräten / Anlagen mit Link zur Anlagen-Doku oder Wartungs-Portal
- Druck-QR-Codes auf Briefpapier / Rechnungen für schnelle Selbstbedienung
- Event-Codes mit Konversions-Tracking (Anmeldung, Lead-Capture)
Beim Scan landet der Nutzer auf einer Public-Landing-Page unter /q/{slug}, sieht den QR-Code nochmals zur Verifikation und ein „Fortfahren"-Button. Erst der Klick auf „Fortfahren" leitet auf die Ziel-URL weiter — und löst die getrackte Confirmed-Conversion aus (anonym + DSGVO-freundlich, siehe QR-Link-Tracking).
Voraussetzungen
Berechtigungen (CASL)
| Action | Subject | Wirkung |
|---|---|---|
view | FE_QrLink, QrLink | Liste und Editor aufrufbar |
create | QrLink | Neuen QR-Link anlegen (Slug optional, sonst auto-generiert) |
update | QrLink | Felder ändern (Slug ist nach Anlage unveränderlich) |
delete | QrLink | Soft-Delete (Scans bleiben erhalten) |
view | QrLinkScan | Statistiken lesen |
view | QrLinkTemplate | Template-Picker im Editor |
view | Document | Custom-Logo auswählen |
Datenmodell
| Feld | Pflicht | Typ | Wirkung |
|---|---|---|---|
slug | optional bei Create, unique pro Mandant | String 3–64, Regex ^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$ | URL-Teil hinter /q/. Auto-generiert (8-Zeichen-Mix) wenn leer. Unveränderlich nach Anlage. |
name | nein | String (255) | Interner Label (Listen-Anzeige), nicht öffentlich. |
targetUrl | nein (Pflicht bei targetType = url) | String (2048) | Ziel-URL, auf die nach Bestätigung weitergeleitet wird. Wird ignoriert bei targetType = businessCard. |
targetType (seit Welle 137) | ja | ENUM (url | businessCard) | Steuert das Ziel: externe URL (Default) oder eine Visitenkarte. |
targetBusinessCardId (seit Welle 137) | nur bei targetType = businessCard | UUID → BusinessCard | Pflicht-Feld bei BC-Ziel. Beim Scan wird auf /c/{bc.slug} weitergeleitet. |
active | ja | Boolean | false → Public-Resolve liefert 404. |
withLogo | nein | Boolean | Logo in QR-Code-Mitte einbetten. |
logoDocumentId | nein | UUID → Document | Custom-Logo. Fallback: Mandanten-Logo aus UiConfig. |
textBelow | nein | String (255) | Fußtext unterhalb des QR-Codes (Export + Landing). |
textSize | nein | Integer | Schriftgröße des Fußtextes in Punkten. Default 12, erlaubt 6–72. |
styleJson | nein | JSON (QrStyleConfig) | Custom-Style. Bei null greift der Mandanten-Standard aus UiConfig. |
templateId | nein | UUID → QrLinkTemplate | Referenz auf zuletzt angewandtes Template (Audit). |
ownerEmployeeId | nein (auto) | UUID → Employee | Ersteller — wird beim Create aus dem Token gesetzt. |
sequenceId | auto | Integer | Lesbare Nummer (z. B. für RefLinks). |
styleJson (QrStyleConfig)
{
"dotsType": "rounded",
"dotsColor": "#1a202c",
"cornersSquareType": "extra-rounded",
"cornersSquareColor": "#1a202c",
"cornersDotType": "dot",
"cornersDotColor": "#1a202c",
"backgroundColor": "#ffffff",
"backgroundTransparent": false,
"logoSize": 0.3,
"textColor": "#1a202c",
"textSize": 12
}
dotsType:square|dots|rounded|classy|classy-rounded|extra-roundedcornersSquareType:square|dot|extra-roundedcornersDotType:square|dotbackgroundTransparent: aktiviert Alpha-Channel im PNG-Export (JPEG bleibt immer weiß)
Schritt-für-Schritt-Anleitung
QR-Link anlegen
- QR-Links (
/qr-links) öffnen → + Hinzufügen. - SpeamCore generiert automatisch einen Slug (z. B.
kvj8m21h). Der Slug ist anschließend nicht mehr änderbar, daher bei Bedarf vor dem Speichern überschreiben. - Name + Weiterleitung (Ziel-URL) eintragen.
- Optional Template anwenden (Quick-Branding) oder Style manuell pflegen (siehe unten).
- Active auf
truesetzen, sobald der Link veröffentlicht werden soll.
Style konfigurieren
Im Editor stehen zwei Modi zur Verfügung:
- Mandanten-Standard verwenden (Default-Toggle aktiv) — der Link erbt die Farben/Stile aus UiConfig. Praktisch für Kampagnen mit unified Look.
- Custom Style — alle Style-Felder werden sichtbar. Punkt-/Eck-Stil, Farben, Hintergrund (auch transparent), Fußtext + Schriftgröße.
Mit Template anwenden wird ein vorgespeichertes Style-Set übernommen (siehe QR-Link-Templates).
Logo einbetten
- Logo verwenden aktivieren.
- Optional ein Custom-Logo hochladen (
Documentüber das Dokumenten-Modul) und alslogoDocumentIdzuweisen. - Ohne Custom-Logo greift automatisch das Mandanten-Logo aus UiConfig.
Live-Vorschau + Export
Der Editor zeigt rechts neben den Formular-Feldern eine Live-Vorschau, die bei jeder Änderung neu rendert. Mit den Export-Buttons stehen drei Formate bereit:
| Format | Eignung |
|---|---|
| PNG | Web-Use, optional mit transparentem Hintergrund |
| JPEG | Druck, weißer Hintergrund (kein Alpha) |
| SVG | Druck-/Plot-Use, skalierbar, Fußtext im SVG eingebettet |
Statistik-Tab
Wechsel auf /qr-links/:id/stats (Tab Statistiken) öffnet die Scan-Auswertung:
| Anzeige | Inhalt |
|---|---|
| Impressions | Anonyme Landing-Page-Aufrufe (Tracking ohne Cookie) |
| Scans (Confirmed) | User klickte „Fortfahren" — wurde auf Ziel-URL weitergeleitet |
| Unique Devices | Distinct deviceCookieId der Confirmed-Scans (1-Jahres-Cookie) |
| Daily Line-Chart | Impressions vs. Confirmed pro Tag im Range |
| By Country | Top-Länder (Cloudflare-Header CF-IPCountry) |
| By UA-Family | Chrome / Safari / Firefox / Edge / Other |
| By Device-Type | mobile / tablet / desktop |
Range über Date-Picker einstellbar — Default 30 Tage zurück.
Details zum Tracking-Modell und der Datenschutz-Architektur: QR-Link-Tracking.
QR-Link mit Visitenkarte als Ziel (Welle 137)
Statt einer externen URL kann ein QR-Link auch eine Visitenkarte als Ziel haben:
| Feld | Wert |
|---|---|
targetType | businessCard |
targetBusinessCardId | UUID der BusinessCard |
targetUrl | wird ignoriert |
Scan-Verhalten unterscheidet sich von targetType = url:
- SpeamCore resolved beim Scan direkt den BC-Slug und leitet auf
/c/{slug}weiter. - Kein Bestätigungs-Screen — Tracking-Modus wird intern auf
anonymousforciert. - Impressions werden im
BusinessCardEvent(kind = impression) der BC geloggt, nicht imQrLinkScan. Die Statistik liegt also bei der Visitenkarte. - Wird die
BusinessCarddeaktiviert oder gelöscht, liefert der QR-Link404.
Anwendungsfall: Druck-Aufkleber an Servicewagen oder Anlagen-Schildern, die direkt zur Visitenkarte des Außendienst-Mitarbeiters führen — statt zu einer Marketing-URL.
Workflows und Zustände
active = false und Soft-Delete führen beide zu 404 auf der Public-Route — Scans werden nicht mehr getrackt. Bestehende QrLinkScan-Datensätze bleiben für historische Statistiken erhalten.
Verknüpfungen zu anderen Modulen
- QR-Link-Templates — wiederverwendbare Style-Vorlagen.
- QR-Link-Tracking — Konzept zu Impression vs. Confirmed, Cookie-Lebenszeit, IP-Hashing.
- Customization / Allgemein — Mandanten-weite Standard-Farben + Standard-Logo für QR-Codes (
uiConfig.color.qrCode*,uiConfig.document.qrCodeLogoDocumentId). - Dokumente — Custom-Logo-Upload.
- Mitarbeiter —
ownerEmployeeIdfür Audit.
Häufige Fehler und Lösungen
| Fehler | Lösung |
|---|---|
| Public-Landing zeigt 404 | active = false oder Link ist gelöscht (Soft-Delete). Im Editor reaktivieren oder neu anlegen. |
| Slug-Eingabe ist disabled | Slug ist nach Anlage unveränderlich. Bei Bedarf neuen Link mit gewünschtem Slug anlegen und alten deaktivieren. |
Vorschau ohne Logo trotz withLogo = true | Weder Custom-Logo noch Mandanten-Logo in UiConfig gepflegt — eines hinterlegen. |
| JPEG-Export hat weißen statt transparenten Hintergrund | JPEG unterstützt keinen Alpha-Channel — PNG-Export wählen. |
| Style-Felder sind versteckt | Toggle Mandanten-Standard verwenden ist aktiv. Deaktivieren, um Custom-Style zu pflegen. |
| KPI „Unique Devices" wirkt zu niedrig | Zählt nur Confirmed-Scans (mit Cookie). Pure Impressions bleiben außen vor — das ist Absicht (Privacy-by-Design). |
| Stats-Tab leer trotz Scans | Range-Filter prüfen — Default-Range geht 30 Tage zurück. |
API/Schnittstellen
Authentifiziert
| Methode | Endpoint | Zweck | CASL |
|---|---|---|---|
GET | /api/qr-links | Liste (paginiert, filterbar, sortierbar) | view QrLink |
POST | /api/qr-links | Anlegen — Slug optional (Auto-Gen mit 8 Zeichen, Retry-Logik) | create QrLink |
GET | /api/qr-links/:id | Detail | view QrLink |
PATCH | /api/qr-links/:id | Update — Slug-Änderung wird mit 400 abgelehnt | update QrLink |
DELETE | /api/qr-links/:id | Soft-Delete | delete QrLink |
GET | /api/qr-links/:id/stats?from=YYYY-MM-DD&to=YYYY-MM-DD | Aggregierte Statistik | view QrLinkScan |
Public (keine Auth)
| Methode | Endpoint | Tracking | Zweck |
|---|---|---|---|
GET | /api/qr-public/:slug | — | Resolve (slug → name, targetUrl, style); 404 bei inactive/deleted |
POST | /api/qr-public/:slug/impression | kind=impression, neue UUID, kein IP-Hash | Anonymer Landing-Aufruf |
POST | /api/qr-public/:slug/confirm | kind=confirmed, persistente UUID, IP-Hash (täglich rotierend) | User-Bestätigung → Redirect zur Ziel-URL |
Versionshinweise
- 2026-05-20 (Welle 130): Initiale Veröffentlichung. Quelle: BE-Commit
2813f706(Service + 8 Migrationen), FE-Commit8972bf94(Editor, Stats-Panel, Public-Page). 3 BE-Modelle (QrLink,QrLinkScan,QrLinkTemplate), 9 API-Endpoints (5 auth + 3 public + Stats), 4 FE-Komponenten (QrLinkEditor971 Z.,QrLinkPreview149 Z.,QrLinkStatsPanel364 Z.,QrLinkPublicPage426 Z.), Style-Cascade (QrLink → UiConfig → Default), Privacy-orientiertes Tracking-Modell (siehe Konzept). - 2026-05-21 (Welle 137): Neue Felder
targetType(url|businessCard) undtargetBusinessCardId— ein QR-Link kann jetzt direkt auf eine Visitenkarte zeigen statt auf eine externe URL. Beim BC-Ziel: kein Bestätigungs-Screen, Tracking läuft als anonymerBusinessCardEventmitkind = impression. Public-Page-Shell wird gemeinsam mit dem Visitenkarten-Modul verwendet (PublicPageShell-Komponente). Quelle: FE6430804b, BE179f8adc.