Public Access
perf(bootcamp): fix CLS/LCP + a11y on EN/DE/ES; add the missing footer-form handler
PageSpeed pass on /odoo-erp-automation-bootcamp/ (EN + DE + ES):
- CLS: /style.css was deferred via media="print" onload=... → unstyled first paint
shifted BODY 0.31 (live CLS 0.326). Now a normal <link rel="stylesheet">; the two
hero webp files are preloaded (fetchpriority=high) by viewport.
- a11y: footer <h4> → <h3> (heading-order), a lighter brass + underline for links
inside on-dark notes (color-contrast, link-in-text-block), .fcopy 3.2:1 → 5.17:1.
- best-practices: the footer contact forms and the waiting-list form now post to the
CRM webhook instead of action="mailto:", which Lighthouse flags as an insecure
request (is-on-https 0 → 1). No Google Ads tag on these pages (no consent gate).
- regression fix: these pages do NOT load /script.js, so after the action change the
footer form had no JS handler and a submit navigated the visitor to the webhook's raw
JSON reply. static/bootcamp-waitlist.js now carries a footer-form handler mirroring
/script.js one-for-one (same webhook, payload { email, requirements, area:'message' }
in UTM.inject, success/failure behaviour); its two strings are read from the form's
own data-ok / data-err attributes so each language keeps its own text. ENDPOINT
hoisted to module scope so both handlers share it.
- no-JS path: a <noscript> footer line with support@ODOO4projects.com as a plain
mailto link. Verified it does not re-trigger is-on-https (unlike a mailto FORM action).
Guards held: Buy forms still post product_id 17; exactly one [data-bc-seats];
waitlist still posts area:'message'; plausible snippet present; competitor QC exit 0.
This commit is contained in:
1 parent
bc942cdb7c
commit
2aa9b19c3c
4 files changed
+203
-32
No files matched your search
@@ -14,6 +14,8 @@
|
||||
* A 200 from the webhook means the workflow accepted the request, not that a CRM record
|
||||
* exists (the workflow answers before it runs) — same as the site's other forms.
|
||||
*/
|
||||
var ENDPOINT = 'https://n8n.odoo4projects.com/webhook/ODOO4projects/crm';
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
@@ -71,8 +73,6 @@
|
||||
window.UTM.parse();
|
||||
|
||||
/* ---- Waiting list ---- */
|
||||
var ENDPOINT = 'https://n8n.odoo4projects.com/webhook/ODOO4projects/crm';
|
||||
|
||||
function run() {
|
||||
var form = document.getElementById('bcWaitlistForm');
|
||||
if (!form) return;
|
||||
@@ -121,3 +121,66 @@
|
||||
run();
|
||||
}
|
||||
})();
|
||||
|
||||
/* ---- Footer contact form ------------------------------------------------------------
|
||||
* These pages do NOT load /script.js, so its footer-form handler does not run here. This
|
||||
* mirrors /script.js's handler one-for-one — same webhook, same payload shape
|
||||
* ({ email, requirements, area:'message' } wrapped in UTM.inject), same success/failure
|
||||
* behaviour — but reads its two strings from the form's own data-ok / data-err attributes
|
||||
* so the message is in the page's language. Without it a submit would navigate the visitor
|
||||
* to the webhook's raw JSON reply.
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function runFooter() {
|
||||
var form = document.getElementById('footerContactForm');
|
||||
if (!form) return;
|
||||
var emailInput = document.getElementById('footerContactEmail');
|
||||
var textInput = document.getElementById('footerContactText');
|
||||
var submitBtn = form.querySelector('.footer-send-btn');
|
||||
var status = document.getElementById('footerFormStatus');
|
||||
var okText = form.getAttribute('data-ok') || "Thanks! We'll get back to you shortly.";
|
||||
var errText = form.getAttribute('data-err') || 'Something went wrong. Please try again.';
|
||||
|
||||
function showStatus(message, isError) {
|
||||
status.textContent = message;
|
||||
status.classList.toggle('error', !!isError);
|
||||
status.classList.add('visible');
|
||||
}
|
||||
|
||||
form.addEventListener('submit', function (e) {
|
||||
e.preventDefault();
|
||||
var email = emailInput.value.trim();
|
||||
var text = textInput.value.trim();
|
||||
if (!email || !text) return;
|
||||
|
||||
submitBtn.disabled = true;
|
||||
status.classList.remove('visible');
|
||||
|
||||
fetch(ENDPOINT, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(window.UTM.inject({
|
||||
email: email,
|
||||
requirements: text,
|
||||
area: 'message'
|
||||
}))
|
||||
}).then(function (r) {
|
||||
if (!r.ok) throw new Error('bad status ' + r.status);
|
||||
form.reset();
|
||||
submitBtn.disabled = false;
|
||||
showStatus(okText, false);
|
||||
}).catch(function () {
|
||||
submitBtn.disabled = false;
|
||||
showStatus(errText, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', runFooter);
|
||||
} else {
|
||||
runFooter();
|
||||
}
|
||||
})();
|
||||
Reference in new issue
Block a user