Site is Loading, Please wait...
Skip to content
Katch Kan
  • Toggle website search
Menu Close
  • Toggle website search
  • View:
  • 12
  • 24
  • All
  • Industrial Vacuum System – Rig SafetyIndustrial Vacuum System – Rig Safety Quick View
    • Industrial Vacuum System – Rig SafetyIndustrial Vacuum System – Rig Safety Quick View
    • Systems
    • Industrial Vacuum System – Rig Safety

    • Easily transportable, they can collect both fluids and semi-fluids. Specially design to operate with low maintenance
    • Add to cart
    Add to quote
    This product is already in your quote request list.
    Quote Now
© Copyright - Get in shape with OceanWP
Classic Car Rental Service Request
Your Name(Required)
This field is hidden when viewing the form
Kan Klean Service Request
Your Name(Required)

 

Request Quote Popup

Your list is empty, add products to the list to send a request

Return to Shop

Performance Studio Service Request
Your Name(Required)
This field is hidden when viewing the form

 

Performance Creative Design Service Request
Your Name(Required)
This field is hidden when viewing the form
This field is for validation purposes and should be left unchanged.

 

Performance Content Creation Service Request
Your Name(Required)
This field is hidden when viewing the form

 

Performance Marketing Agency Service Request
Your Name(Required)
This field is hidden when viewing the form

 

service request
Your Name(Required)
This field is hidden when viewing the form
This field is for validation purposes and should be left unchanged.

 

✕
(function() { const ajaxUrl = 'https://www.katchkan.com/wp-admin/admin-ajax.php'; // --- visitor id (localStorage) --- let visitorId = localStorage.getItem('visitor_id'); let returning = 0; if (!visitorId) { // create stable id for this browser visitorId = 'visitor_' + (crypto.randomUUID ? crypto.randomUUID() : (Date.now().toString(36) + Math.random().toString(36).slice(2))); localStorage.setItem('visitor_id', visitorId); returning = 0; } else { returning = 1; } // --- metrics --- const startTime = Date.now(); let engagementTime = 0; // seconds counted as "active" let lastActiveTs = Date.now(); let lastTickTs = Date.now(); const ACTIVE_THRESHOLD_MS = 15000; // if interaction happened within last 15s, consider active let maxScroll = 0; function markActive() { lastActiveTs = Date.now(); } // mark activity on common interactive events ['click','scroll','mousemove','keydown','touchstart','touchmove'].forEach(evt => { document.addEventListener(evt, markActive, {passive: true}); }); // scroll tracker: update maxScroll function updateScroll() { const docHeight = document.documentElement.scrollHeight - window.innerHeight; const scrolled = docHeight > 0 ? (window.scrollY / docHeight) * 100 : 0; const rounded = Math.round(scrolled); if (rounded > maxScroll) maxScroll = rounded; } window.addEventListener('scroll', updateScroll, {passive: true}); // accumulate engagement time every 1s (adds elapsed seconds if user considered active) setInterval(() => { const now = Date.now(); const elapsedMs = now - lastTickTs; lastTickTs = now; // Convert elapsed to seconds (may be <1s if interval drift; we add fractional seconds by rounding) const elapsedSec = Math.round(elapsedMs / 1000); // Consider user active if last interaction within ACTIVE_THRESHOLD_MS and the page is visible if (!document.hidden && (Date.now() - lastActiveTs) < ACTIVE_THRESHOLD_MS) { engagementTime += elapsedSec > 0 ? elapsedSec : 1; // ensure at least +1s per tick } }, 1000); // helper: fetch POST function sendFetch(data) { fetch(ajaxUrl, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: new URLSearchParams(data) }).catch(e => { /* silent fail; analytics should not break UX */ }); } // helper: send via beacon (used on pagehide/unload) function sendBeacon(data) { // sendBeacon requires a Blob or string; we'll pass x-www-form-urlencoded bytes const params = new URLSearchParams(data).toString(); const blob = new Blob([params], { type: 'application/x-www-form-urlencoded' }); navigator.sendBeacon(ajaxUrl, blob); } // --- send initial page_visit --- sendFetch({ action: 'log_visitor_event', visitor_id: visitorId, returning: returning, event_type: 'page_visit', page_url: window.location.href, page_title: document.title || '' }); // --- click tracking (send event_value + target) --- document.addEventListener('click', function(e) { const el = e.target; if (!el) return; if (el.tagName === 'HTML' || el.tagName === 'BODY') return; const tag = el.tagName.toLowerCase(); const id = el.id ? '#' + el.id : ''; const classes = (el.className && typeof el.className === 'string') ? '.' + el.className.trim().split(/\s+/).join('.') : ''; const text = (el.textContent || '').trim().substring(0, 200); const targetDesc = `${tag}${id}${classes}`; // event_value: href for links, value for inputs/buttons, or text fallback let value = ''; if (tag === 'a' && el.href) { value = el.href; } else if ((tag === 'input' || tag === 'button') && el.value) { value = el.value; } else { value = text; } sendFetch({ action: 'log_visitor_event', visitor_id: visitorId, returning: returning, event_type: 'click', page_url: window.location.href, page_title: document.title || '', event_target: targetDesc, event_value: value }); markActive(); }, {passive: true}); // --- periodic heartbeat (optional, safe) --- // Uncomment if you want periodic server updates so you don't lose everything on abrupt exits. /* setInterval(() => { const timeSpent = Math.round((Date.now() - startTime) / 1000); sendFetch({ action: 'log_visitor_event', visitor_id: visitorId, returning: returning, event_type: 'heartbeat', page_url: window.location.href, page_title: document.title || '', event_value: JSON.stringify({ time_spent: timeSpent, engagement_time: engagementTime, max_scroll: maxScroll }) }); }, 30000); // every 30s */ // --- final metrics sender: pagehide and beforeunload (robust) --- function sendFinalMetrics() { const timeSpent = Math.round((Date.now() - startTime) / 1000); const metrics = { time_spent: timeSpent, engagement_time: engagementTime, max_scroll: maxScroll }; // prefer sendBeacon (reliable during unload) if (navigator && navigator.sendBeacon) { sendBeacon({ action: 'log_visitor_event', visitor_id: visitorId, returning: returning, event_type: 'session_end', page_url: window.location.href, page_title: document.title || '', event_value: JSON.stringify(metrics) }); } else { // fallback (best effort) sendFetch({ action: 'log_visitor_event', visitor_id: visitorId, returning: returning, event_type: 'session_end', page_url: window.location.href, page_title: document.title || '', event_value: JSON.stringify(metrics) }); } } // pagehide covers unload in many browsers (more reliable on mobile) window.addEventListener('pagehide', sendFinalMetrics); // beforeunload as an extra fallback window.addEventListener('beforeunload', sendFinalMetrics); })();
×