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(); );
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
public function getEngagementReport($dateRange = 'last30') $apiUrl = $this->matomoUrl . '/index.php'; $params = [ 'module' => 'API', 'method' => 'CustomEvents.getCustomEvent', 'idSite' => $this->siteId, 'period' => 'range', 'date' => $dateRange, 'format' => 'json', 'filter_limit' => -1 ]; if ($this->tokenAuth) $params['token_auth'] = $this->tokenAuth; $url = $apiUrl . '?' . http_build_query($params); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); $ch = curl_init()
<!-- Heartbeat Tracker --> <script src="matomo-heartbeat.js"></script> $response = curl_exec($ch)
// Example usage in your tracking endpoint if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_GET['action']) && $_GET['action'] === 'heartbeat') $handler = new MatomoHeartbeatHandler( 'https://your-matomo-domain.com', 1, // Your site ID 'your-token-auth' // Optional for API access );
$input = json_decode(file_get_contents('php://input'), true); $result = $handler->processHeartbeat($input);
log(message, data = null) if (this.options.debug)