Every guide we publish sits under one of these. Pick the one closest to what’s costing you margin right now.
Cost tracking, BOQ margin discipline and the reporting that tells you where a project is actually bleeding.
Why margin discipline has to start at the bill of quantities, not the monthly report.
Getting work-in-progress numbers that match what's actually happened on site.
The quiet cost leaks that never show up as a single line item.
The recurring reasons budgets slip, and where to catch them earliest.
A working method for reading margin site by site, not just at project close.
Getting the right trade, in the right number, on the right site — and keeping subcontractor crews accountable once they arrive.
What has to be confirmed before a subcontractor crew mobilises to site.
What multi-site crew deployment actually demands from a system.
Keeping planned maintenance crews on schedule across scattered sites.
What happens when nobody owns a single record of who's deployed where.
Turning site punches into numbers finance can trust, and catching overtime before it becomes an unplanned cost.
Attendance and workforce complexity is the part most CAFM comparisons skip.
Making crew accountability provable when an SLA is on the line.
Why labour cost tracking looks different across hard and soft FM contracts.
What sits between attendance and a payslip — and the compliance work most contractors underestimate.
Getting attendance data clean enough that payroll stops being a monthly fire drill.
How different billing methods change what your finance team needs from site data.
Where structured billing pays for itself against manual reconciliation.
Most labour cost problems trace back to the same handful of gaps. Here's how JobsNext.ai closes them.
Profit drains that never show up as a single line item — caught early with site-level margin tracking.
See the 7 hidden drains →When nobody owns a single record of who's deployed where, costs go untracked. One connected source of truth fixes it.
Read the ₹1.2 Cr case study →Manual reconciliation quietly burns margin. Structured billing pays for itself fast.
See how ₹50 Lakh was saved →Dirty attendance data turns payroll into a monthly scramble. Clean site punches end the chaos.
Cut the payroll chaos →', …),
// where dollar-quote and dollar-amp are special replace tokens; and it lives in a
// JS template literal that eats backslash escapes. So keep this block free of the
// dollar sign and of backslash escapes: exact-match CTA texts (no regex end-anchor)
// plus a space-only collapse regex.
var cnxCtaTexts = ['book a demo','request a demo','get a demo','book demo','schedule a demo','talk to sales','talk to us','talk to the team','get in touch','contact us','contact sales','contact the team','contact'];
function cnxIsContactCta(el){
if (el.id && el.id.indexOf('cnx-') === 0) return false;
if (el.hasAttribute && el.hasAttribute('data-cnx-contact')) return true;
var raw = ((el.getAttribute && el.getAttribute('href')) || '').toLowerCase();
var hh = raw.split('?')[0].split('#')[0];
if (raw === '#contact' || hh === '/contact' || hh === 'contact' || hh === 'contact.html'
|| (hh.length >= 8 && hh.lastIndexOf('/contact') === hh.length - 8)
|| (hh.length >= 13 && hh.lastIndexOf('/contact.html') === hh.length - 13)) return true;
var t = (el.textContent || '').replace(/ +/g, ' ').trim().toLowerCase();
if (t.length > 24) return false;
for (var k = 0; k < cnxCtaTexts.length; k++) { if (t === cnxCtaTexts[k]) return true; }
return false;
}
document.addEventListener('click', function (e) {
var el = e.target;
while (el && el !== document) {
if (el.tagName === 'A' || el.tagName === 'BUTTON') break;
el = el.parentNode;
}
if (!el || el === document) return;
if (cnxIsContactCta(el)) {
e.preventDefault();
e.stopPropagation();
openModal();
}
}, true);
if (closeBtn) closeBtn.addEventListener('click', closeModal);
if (scrim) scrim.addEventListener('click', function(e){ if(e.target === scrim) closeModal(); });
if (form) form.addEventListener('submit', function(e){
e.preventDefault();
var note = document.getElementById('cnx-note'), err = document.getElementById('cnx-err'), btn = document.getElementById('cnx-submit');
note.style.display='none'; err.style.display='none';
if (form.website_url && form.website_url.value){ note.style.display='block'; return; } // honeypot
var payload = {
name: form.name.value, email: form.email.value, company: form.company.value,
phone: form.phone.value, message: form.message.value,
subscribe_newsletter: form.subscribe_newsletter && form.subscribe_newsletter.checked,
turnstile_token: form.turnstile_token ? form.turnstile_token.value : '',
_token_ts: tsEl ? tsEl.value : tokenTs()
};
if (!payload.name || !payload.email || !payload.company || !payload.phone || !payload.message){ err.textContent='Please fill in all required fields.'; err.style.display='block'; return; }
if (payload.phone.replace(/[^0-9]/g, '').length < 7){ err.textContent='Please enter a valid phone number.'; err.style.display='block'; return; }
btn.disabled = true; btn.textContent = 'Sending…';
post(payload).then(function(d){
if (d && d.success){ form.style.display='none'; note.style.display='block'; }
else { err.textContent = (d && d.message) || 'Something went wrong — please try again.'; err.style.display='block'; btn.disabled=false; btn.textContent='Send message'; }
}).catch(function(){ err.textContent='Network error — please try again.'; err.style.display='block'; btn.disabled=false; btn.textContent='Send message'; });
});
// --- Progressive enhancement: wire a site's OWN contact form to the CRM ---
// Targets forms that look like contact forms (have an email field AND a
// textarea/message field), aren't ours, and aren't opted out. Field mapping is
// heuristic; company falls back to the entered name so the CRM never rejects.
function pick(f, res){ for (var i=0;i