Add low-friction 3-step lead form to contact section (posts to n8n)
Soft conversion path alongside booking; SW steel/Georgia styling. Posts JSON to https://n8n.shopwisdom.ca/webhook/sw-lead, honeypot-protected, email fallback. Staging branch only. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+84
@@ -271,6 +271,37 @@
|
||||
<h2>Start with a conversation</h2>
|
||||
<p>No pitch. No proposal until we've had a real conversation. Describe the friction — even roughly. The more context you share, the more useful our first conversation will be.</p>
|
||||
<p>I read every message personally and usually reply within one business day. If your problem isn't something I can help with, I'll tell you honestly — and point you somewhere that can.</p>
|
||||
|
||||
<form class="lf" data-endpoint="https://n8n.shopwisdom.ca/webhook/sw-lead" data-source="shopwisdom" novalidate>
|
||||
<div class="lf-progress" aria-hidden="true"><span class="lf-dot is-active"></span><span class="lf-dot"></span><span class="lf-dot"></span></div>
|
||||
<fieldset class="lf-step is-active" data-step="1">
|
||||
<legend class="lf-q">What's the situation in your shop?</legend>
|
||||
<div class="lf-choices">
|
||||
<label class="lf-choice"><input type="radio" name="topic" value="A key person is retiring soon" required> A key person is retiring soon</label>
|
||||
<label class="lf-choice"><input type="radio" name="topic" value="Know-how lives in a few heads"> Know-how lives in just a few heads</label>
|
||||
<label class="lf-choice"><input type="radio" name="topic" value="A process or tool needs building"> A process or tool needs building</label>
|
||||
<label class="lf-choice"><input type="radio" name="topic" value="Just exploring"> Just exploring for now</label>
|
||||
</div>
|
||||
<div class="lf-nav"><button type="button" class="btn lf-next" data-next>Continue →</button></div>
|
||||
</fieldset>
|
||||
<fieldset class="lf-step" data-step="2">
|
||||
<legend class="lf-q">Anything you want me to know? <span class="lf-opt">(optional)</span></legend>
|
||||
<textarea class="lf-input" name="detail" rows="3" placeholder="Even a rough sentence helps."></textarea>
|
||||
<div class="lf-nav"><button type="button" class="btn ghost lf-back" data-back>← Back</button><button type="button" class="btn lf-next" data-next>Continue →</button></div>
|
||||
</fieldset>
|
||||
<fieldset class="lf-step" data-step="3">
|
||||
<legend class="lf-q">Where do I reach you?</legend>
|
||||
<input class="lf-input" type="text" name="name" placeholder="Your name" required autocomplete="name">
|
||||
<input class="lf-input" type="email" name="email" placeholder="Email" required autocomplete="email">
|
||||
<input class="lf-input" type="tel" name="phone" placeholder="Phone (optional)" autocomplete="tel">
|
||||
<input type="text" name="company_website" class="lf-hp" tabindex="-1" autocomplete="off" aria-hidden="true">
|
||||
<div class="lf-nav"><button type="button" class="btn ghost lf-back" data-back>← Back</button><button type="submit" class="btn lf-submit">Send it →</button></div>
|
||||
<p class="lf-err" hidden>Hmm — that didn't go through. Please <a href="mailto:michael@opencommunications.consulting">email me directly</a> and I'll get right back to you.</p>
|
||||
</fieldset>
|
||||
<div class="lf-done" hidden><p class="lf-done-msg">Got it — thanks. I read every message personally and usually reply within a business day.</p></div>
|
||||
</form>
|
||||
|
||||
<p class="lf-alt">Prefer to reach out directly?</p>
|
||||
<p class="contact-action">
|
||||
<a class="btn" href="mailto:michael@opencommunications.consulting?subject=Fit%20call%20—%20Shop%20Wisdom">Email Michael</a>
|
||||
<a class="btn ghost tel" data-p1="778" data-p2="985" data-p3="6736" href="mailto:michael@opencommunications.consulting">Call 778‑985‑OPEN (6736)</a>
|
||||
@@ -320,6 +351,59 @@
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- Lead form: 3-step navigation + submit to the n8n webhook (honeypot-protected) -->
|
||||
<script>
|
||||
(function () {
|
||||
document.querySelectorAll('form.lf').forEach(function (form) {
|
||||
var steps = [].slice.call(form.querySelectorAll('.lf-step'));
|
||||
var dots = [].slice.call(form.querySelectorAll('.lf-dot'));
|
||||
var done = form.querySelector('.lf-done');
|
||||
var err = form.querySelector('.lf-err');
|
||||
var progress = form.querySelector('.lf-progress');
|
||||
var cur = 0;
|
||||
function show(i) {
|
||||
steps.forEach(function (s, k) { s.classList.toggle('is-active', k === i); });
|
||||
dots.forEach(function (d, k) { d.classList.toggle('is-active', k <= i); });
|
||||
cur = i;
|
||||
var fld = steps[i].querySelector('input:not([type=radio]),textarea'); if (fld) { try { fld.focus(); } catch (e) {} }
|
||||
}
|
||||
function valid(i) {
|
||||
var reqs = steps[i].querySelectorAll('[required]');
|
||||
for (var j = 0; j < reqs.length; j++) { if (!reqs[j].checkValidity()) { reqs[j].reportValidity(); return false; } }
|
||||
return true;
|
||||
}
|
||||
form.addEventListener('click', function (e) {
|
||||
if (e.target.closest('[data-next]')) { if (valid(cur)) show(Math.min(cur + 1, steps.length - 1)); }
|
||||
else if (e.target.closest('[data-back]')) { show(Math.max(cur - 1, 0)); }
|
||||
});
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
if (!valid(cur)) return;
|
||||
var hp = form.querySelector('.lf-hp');
|
||||
if (hp && hp.value) { return; }
|
||||
if (err) err.hidden = true;
|
||||
var data = {};
|
||||
new FormData(form).forEach(function (v, k) { if (k !== 'company_website') data[k] = v; });
|
||||
data.source = form.getAttribute('data-source') || location.hostname;
|
||||
data.submittedAt = new Date().toISOString();
|
||||
var btn = form.querySelector('.lf-submit'); var label = btn.textContent;
|
||||
btn.disabled = true; btn.textContent = 'Sending…';
|
||||
fetch(form.getAttribute('data-endpoint'), {
|
||||
method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data)
|
||||
}).then(function (r) {
|
||||
if (!r.ok) throw new Error('status ' + r.status);
|
||||
steps.forEach(function (s) { s.style.display = 'none'; });
|
||||
if (progress) progress.style.display = 'none';
|
||||
if (done) done.hidden = false;
|
||||
}).catch(function () {
|
||||
btn.disabled = false; btn.textContent = label;
|
||||
if (err) err.hidden = false;
|
||||
});
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!-- Cal.com booking embed (opens the booking popup on-brand; href is the no-JS fallback) -->
|
||||
<script>
|
||||
(function (C, A, L) { let p = function (a, ar) { a.q.push(ar); }; let d = C.document; C.Cal = C.Cal || function () { let cal = C.Cal; let ar = arguments; if (!cal.loaded) { cal.ns = {}; cal.q = cal.q || []; d.head.appendChild(d.createElement("script")).src = A; cal.loaded = true; } if (ar[0] === L) { const api = function () { p(api, arguments); }; const namespace = ar[1]; api.q = api.q || []; if (typeof namespace === "string") { cal.ns[namespace] = cal.ns[namespace] || api; p(cal.ns[namespace], ar); p(cal, ["initNamespace", namespace]); } else p(cal, ar); return; } p(cal, ar); }; })(window, "https://cal.shopwisdom.ca/embed/embed.js", "init");
|
||||
|
||||
Reference in New Issue
Block a user