feat(leads): submit contact requests to native platform intake

This commit is contained in:
Raffael Sheikh committed 2026-07-16 12:33:08 +02:00
1 parent 41664c3d0d
commit 079764d93d
12 files changed
+760 -154

No files matched your search

+7 -6
View File
@@ -425,11 +425,11 @@
<div class="form-grid">
<div class="form-row">
<label for="f-vorname">Vorname <span>*</span></label>
<input id="f-vorname" name="vorname" type="text" autocomplete="given-name" required />
<input id="f-vorname" name="vorname" type="text" autocomplete="given-name" maxlength="120" required />
</div>
<div class="form-row">
<label for="f-nachname">Nachname <span>*</span></label>
<input id="f-nachname" name="nachname" type="text" autocomplete="family-name" required />
<input id="f-nachname" name="nachname" type="text" autocomplete="family-name" maxlength="120" required />
</div>
</div>
<div class="form-grid">
@@ -445,16 +445,16 @@
<div class="form-grid">
<div class="form-row">
<label for="f-email">E-Mail <span>*</span></label>
<input id="f-email" name="email" type="email" autocomplete="email" required />
<input id="f-email" name="email" type="email" autocomplete="email" maxlength="320" required />
</div>
<div class="form-row">
<label for="f-telefon">Telefonnummer</label>
<input id="f-telefon" name="telefon" type="tel" autocomplete="tel" />
<input id="f-telefon" name="telefon" type="tel" autocomplete="tel" maxlength="80" />
</div>
</div>
<div class="form-row">
<label for="f-nachricht">Worum geht es Ihnen? <span>*</span></label>
<textarea id="f-nachricht" name="nachricht" rows="4" required
<textarea id="f-nachricht" name="nachricht" rows="4" maxlength="4000" required
placeholder="Kurz Ihr Anliegen, wir kümmern uns um die Details."></textarea>
</div>
<!-- Honeypot gegen Spam -->
@@ -507,6 +507,7 @@
</div>
</footer>
<script src="/script.js?v=20260610"></script>
<script src="/submission-id.js?v=20260716"></script>
<script src="/script.js?v=20260716"></script>
</body>
</html>
+27 -7
View File
@@ -31,6 +31,8 @@
/* ---- Lead-Formular ---- */
var form = document.getElementById("lead-form");
var status = document.getElementById("form-status");
var pendingSubmission = null;
var submissionIds = window.ToolCtrlSubmission;
if (!form) return;
function setStatus(msg, kind) {
@@ -69,22 +71,39 @@
}
var btn = form.querySelector("button[type=submit]");
if (!submissionIds) {
setStatus("Formular konnte nicht initialisiert werden. Bitte laden Sie die Seite neu.", "err");
return;
}
var vorname = form.vorname.value.trim();
var nachname = form.nachname.value.trim();
var firmenname = form.firmenname.value.trim();
var branche = form.branche.value.trim();
var payload = {
var leadInput = {
name: (vorname + " " + nachname).trim(),
vorname: vorname,
nachname: nachname,
firma: firmenname + (branche ? " (" + branche + ")" : ""),
firmenname: firmenname,
branche: branche,
email: form.email.value.trim(),
telefon: form.telefon.value.trim(),
nachricht: form.nachricht.value.trim(),
nachricht: form.nachricht.value.trim()
};
pendingSubmission = submissionIds.bindSubmissionId(
pendingSubmission,
submissionIds.createLeadFingerprint(leadInput),
function () { return submissionIds.createSubmissionId(window.crypto); }
);
var payload = {
name: leadInput.name,
vorname: vorname,
nachname: nachname,
firma: leadInput.firma,
firmenname: firmenname,
branche: branche,
email: leadInput.email,
telefon: leadInput.telefon,
nachricht: leadInput.nachricht,
website: form.website.value.trim(), // Honeypot
quelle: "Landing Page"
quelle: "Landing Page",
submissionId: pendingSubmission.id
};
if (btn) { btn.disabled = true; btn.textContent = "Wird gesendet …"; }
@@ -102,6 +121,7 @@
})
.then(function (r) {
if (r.ok) {
pendingSubmission = null;
form.reset();
setStatus(
"Vielen Dank — Ihre Anfrage ist bei uns eingegangen. Wir melden uns zeitnah.",
+49
View File
@@ -0,0 +1,49 @@
(function (root, factory) {
"use strict";
var api = factory();
if (typeof module === "object" && module.exports) module.exports = api;
if (root) root.ToolCtrlSubmission = api;
})(typeof globalThis === "object" ? globalThis : this, function () {
"use strict";
function createSubmissionId(cryptoApi) {
if (!cryptoApi || typeof cryptoApi.getRandomValues !== "function") {
throw new Error("Secure browser randomness is unavailable");
}
if (typeof cryptoApi.randomUUID === "function") {
return cryptoApi.randomUUID();
}
var bytes = new Uint8Array(16);
cryptoApi.getRandomValues(bytes);
return "web-" + Array.from(bytes, function (value) {
return value.toString(16).padStart(2, "0");
}).join("");
}
function normalizedName(value) {
return String(value || "").trim().replace(/\s+/g, " ");
}
function createLeadFingerprint(input) {
return JSON.stringify({
name: normalizedName(input.name),
company: String(input.firma || "").trim(),
email: String(input.email || "").trim().toLowerCase(),
phone: String(input.telefon || "").trim(),
message: String(input.nachricht || "").trim(),
formId: "contact-form",
consent: true
});
}
function bindSubmissionId(pending, fingerprint, createId) {
if (pending && pending.fingerprint === fingerprint) return pending;
return { id: createId(), fingerprint: fingerprint };
}
return {
bindSubmissionId: bindSubmissionId,
createLeadFingerprint: createLeadFingerprint,
createSubmissionId: createSubmissionId
};
});