Overview
Matomo supports both client-side (browser JavaScript) and server-side (Tracking HTTP API) data collection. Understanding when to use each approach - and how to combine them effectively - is essential for accurate, comprehensive analytics.
Client-Side Collection
When to Use
- Pageviews and navigation: Standard page loads and SPA route changes
- User interactions: Clicks, scrolls, video plays, form engagements
- Browser context data: Screen resolution, viewport, user agent, referrer
- Real-time visitor insights: Live dashboards and session recordings
- Consent management: Capturing user consent states and preferences
Implementation
<!-- Standard Matomo JavaScript Tracker -->
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://analytics.example.com/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '1']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();
</script>
Advantages
- Full browser context automatically captured
- Real-time visitor flow visibility
- Session recordings and heatmaps available
- Lower implementation complexity
- Works with Matomo Tag Manager
Limitations
- Subject to ad blockers and privacy extensions
- Relies on JavaScript execution
- Cannot capture server-only events (webhooks, backend processes)
- Potential for data loss on navigation or page unload
Server-Side Collection
When to Use
- Authoritative transactions: Orders, payments, refunds, subscriptions
- Backend events: Webhook callbacks, API interactions, cron jobs
- Sensitive data: Events requiring server-side validation before tracking
- Ad blocker bypass: Critical conversions that must not be blocked
- Offline or async events: Email opens, push notification interactions
Matomo Tracking HTTP API
Send events directly from your server:
# Basic pageview via HTTP API
curl "https://analytics.example.com/matomo.php?idsite=1&rec=1&action_name=Order%20Confirmation&url=https://example.com/order/12345&_id=abc123xyz&rand=12345"
PHP SDK Example
use MatomoTracker;
$tracker = new MatomoTracker($siteId, 'https://analytics.example.com/');
$tracker->setTokenAuth('your_token_auth');
$tracker->setUserId('user_12345');
$tracker->setVisitorId('abc123xyz789012'); // From client cookie
// Track ecommerce order
$tracker->addEcommerceItem('SKU-123', 'Product Name', 'Category', 79.99, 1);
$tracker->doTrackEcommerceOrder('ORD-98765', 92.38, 79.99, 6.40, 5.99, 10.00);
Required Parameters
| Parameter | Description | Example |
|---|---|---|
idsite |
Matomo Site ID | 1 |
rec |
Required, always set to 1 |
1 |
url |
Full URL of the action | https://example.com/checkout |
action_name |
Page title or event name | Order Confirmation |
_id |
Visitor ID (16 hex characters) | abc123def456789 |
token_auth |
API authentication token | xyz789... |
Advantages
- Immune to ad blockers and browser restrictions
- Server-validated data (no client manipulation)
- Access to backend-only events
- Guaranteed delivery with retry logic
- Works for non-browser contexts (apps, IoT, APIs)
Limitations
- No automatic browser context (must pass manually)
- No session recordings or heatmaps
- Requires more implementation effort
- Must manage visitor ID correlation carefully
Hybrid Architecture
Most implementations benefit from combining both approaches:
┌─────────────────┐ ┌─────────────────┐
│ Browser │ │ Server │
│ (Client-Side) │ │ (Server-Side) │
├─────────────────┤ ├─────────────────┤
│ • Pageviews │ │ • Orders │
│ • Clicks │ │ • Refunds │
│ • Scroll depth │ │ • Webhooks │
│ • Video plays │ │ • API events │
│ • Form starts │ │ • Backend jobs │
└────────┬────────┘ └────────┬────────┘
│ │
└───────────┬───────────┘
│
┌──────▼──────┐
│ Matomo │
│ Server │
└─────────────┘
Visitor ID Correlation
The critical factor for hybrid tracking is maintaining visitor identity:
- Client captures visitor ID: Extract the Matomo
_pk_idcookie value - Pass to server: Include visitor ID in form submissions, AJAX calls, or session storage
- Server uses same ID: Pass the visitor ID in server-side API calls
// Client: Get visitor ID
var visitorId = Matomo.getTracker().getVisitorId();
// Pass to server in checkout form
document.getElementById('visitorId').value = visitorId;
// Server: Use the same visitor ID
$visitorId = $_POST['visitorId'];
$tracker->setVisitorId($visitorId);
$tracker->doTrackEcommerceOrder($orderId, $total, ...);
Deduplication Strategies
When both client and server might report the same event:
Option 1: Server-Only for Conversions
Configure client-side to skip conversion events entirely; server handles all orders/transactions.
// Client: Track checkout start, but not completion
_paq.push(['trackEvent', 'Checkout', 'start']);
// Server handles order completion tracking
Option 2: Client with Server Validation
Client fires immediately; server validates and sends authoritative version:
- Client tracks conversion with
action_nameprefix:[pending] Order - Server validates and tracks:
Order Confirmed - Reporting filters for confirmed orders only
Option 3: Server-Side Deduplication
Use unique transaction IDs to prevent duplicates:
// Check if order already tracked before sending
if (!$this->isOrderTracked($orderId)) {
$tracker->doTrackEcommerceOrder($orderId, ...);
$this->markOrderTracked($orderId);
}
Performance Considerations
Client-Side
- Use async script loading to prevent render blocking
- Batch events where possible to reduce HTTP requests
- Consider
navigator.sendBeacon()for unload events
Server-Side
- Implement queue-based sending for high-volume events
- Use bulk tracking API for batch imports
- Set appropriate timeouts and retry logic
- Monitor tracking endpoint latency
// Bulk tracking example
$tracker->enableBulkTracking();
foreach ($orders as $order) {
$tracker->doTrackEcommerceOrder(...);
}
$tracker->doBulkTrack();
Security Considerations
Token Authentication
Server-side tracking requires token_auth for write access:
- Store tokens securely (environment variables, secrets manager)
- Use tokens with minimal required permissions
- Rotate tokens periodically
- Never expose tokens in client-side code
Input Validation
Validate all data before sending to Matomo:
- Sanitize user-provided values
- Validate numeric fields (prices, quantities)
- Reject suspicious visitor ID formats
- Log validation failures for monitoring
Decision Matrix
| Scenario | Recommended Approach |
|---|---|
| Standard pageviews | Client-side |
| User interactions (clicks, scrolls) | Client-side |
| Ecommerce orders | Server-side (authoritative) |
| Payment confirmations | Server-side |
| Form submissions | Client start, server complete |
| Webhook events | Server-side only |
| Subscription renewals | Server-side only |
| Ad blocker critical conversions | Server-side |