Matomo Heartbeat - 'link'

sendBeacon(data) // Use sendBeacon for reliable final tracking if (navigator.sendBeacon) const formData = new FormData(); Object.keys(data).forEach(key => formData.append(key, data[key]); ); navigator.sendBeacon('/matomo.php', formData);

startIdleMonitoring() this.idleCheckId = setInterval(() => const idleTime = (Date.now() - this.lastActivity) / 1000; if (idleTime >= this.options.idleTimeout && this.isActive) this.stopHeartbeat(); this.log(`User idle for $idleTime seconds, stopping heartbeat`); , 1000);

sendHeartbeat(type) const now = Date.now(); const timeSinceLastHeartbeat = (now - this.lastHeartbeatTime) / 1000; // Don't send heartbeat if too short if (timeSinceLastHeartbeat < this.options.minVisitLength && type === 'ongoing') return; const heartbeatData = action_name: 'Heartbeat', e_c: 'Engagement', e_a: type, e_n: 'User Activity', e_v: Math.floor(timeSinceLastHeartbeat), _cvar: JSON.stringify( heartbeat_interval: this.options.heartbeatInterval, time_on_page: Math.floor((now - this.visitStartTime) / 1000), total_engaged_time: this.totalEngagedTime + Math.floor((now - this.lastHeartbeatTime) / 1000) ) ; // Send to Matomo if (window._paq) window._paq.push(['trackEvent', heartbeatData.e_c, heartbeatData.e_a, heartbeatData.e_n, heartbeatData.e_v]); // Optional: track custom variable window._paq.push(['setCustomVariable', 1, 'HeartbeatType', type, 'page']); this.log(`Heartbeat sent: $type`, heartbeatData); this.lastHeartbeatTime = now; matomo heartbeat

bindEvents() // Track user activity events const activityEvents = ['mousedown', 'mousemove', 'keydown', 'scroll', 'touchstart', 'click']; activityEvents.forEach(event => document.addEventListener(event, () => this.resetIdleTimer()); ); // Page visibility API document.addEventListener('visibilitychange', () => if (document.hidden) this.stopHeartbeat(); this.log('Page hidden, stopping heartbeat'); else this.startHeartbeat(); this.log('Page visible, starting heartbeat'); ); // Before page unload window.addEventListener('beforeunload', () => this.sendFinalHeartbeat(); );

<!-- Heartbeat Tracker --> <script src="matomo-heartbeat.js"></script> JavaScript Heartbeat Tracker // matomo-heartbeat

I'll help you develop a Matomo Heartbeat feature. This feature tracks user engagement time more accurately by sending periodic heartbeats to Matomo analytics. 1. JavaScript Heartbeat Tracker // matomo-heartbeat.js class MatomoHeartbeat { constructor(options = {}) this.options = heartbeatInterval: 15, // seconds minVisitLength: 5, // minimum seconds for a valid visit idleTimeout: 30, // seconds of inactivity to stop heartbeat debug: false, ...options ; this.intervalId = null; this.idleCheckId = null; this.lastActivity = Date.now(); this.visitStartTime = null; this.totalEngagedTime = 0; this.isActive = false; this.lastHeartbeatTime = null; this.init();

private function createNewSession($sessionId, $visitorId, $pageUrl) $now = new DateTime(); $stmt = $this->db->prepare(" INSERT INTO matomo_heartbeat_sessions (session_id, visitor_id, page_url, start_time, last_heartbeat, total_engaged_time, heartbeat_count) VALUES (?, ?, ?, ?, ?, ?, 1) "); $stmt->execute([ $sessionId, $visitorId, $pageUrl, $now->format('Y-m-d H:i:s'), $now->format('Y-m-d H:i:s'), 0 ]); return ['status' => 'created', 'session_id' => $this->db->lastInsertId()]; // seconds minVisitLength: 5

// Example API endpoint if ($_SERVER['REQUEST_METHOD'] === 'POST') $pdo = new PDO('mysql:host=localhost;dbname=matomo', 'user', 'password'); $tracker = new MatomoEngagementTracker($pdo);