Overview
This guide helps you diagnose and resolve common Matomo (formerly Piwik) tracking issues. Matomo provides privacy-focused analytics with full data ownership, making proper configuration essential.
Debug Mode
Enable JavaScript Tracker Debugging
Enable debug mode to see detailed tracking information:
// Enable debug mode
_paq.push(['enableDebug']);
// Or configure Matomo object directly
var _paq = window._paq = window._paq || [];
_paq.push(['enableDebug']);
_paq.push(['trackPageView']);
Check Matomo Loading
Verify Matomo is loaded correctly:
// Check if Matomo tracker exists
if (typeof _paq !== 'undefined') {
console.log('Matomo tracker loaded');
console.log('_paq queue:', _paq);
} else {
console.error('Matomo tracker not loaded');
}
// Check Matomo object
if (typeof Matomo !== 'undefined') {
console.log('Matomo object loaded');
console.log('Trackers:', Matomo.getAsyncTrackers());
} else {
console.log('Matomo object not yet loaded (may load async)');
}
Common Issues
No Data in Reports
Symptoms: Tracking code installed but no data appears in Matomo.
Solutions:
- Verify tracking code installation:
<!-- Matomo tracking code should be before </head> or </body> -->
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//matomo.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>
- Check Site ID:
// Verify Site ID is correct
_paq.push(['setSiteId', '1']); // Should match your Matomo site ID
// Log current tracker configuration
_paq.push([function() {
var tracker = this;
console.log('Tracker URL:', tracker.getTrackerUrl());
console.log('Site ID:', tracker.getSiteId());
}]);
// Check tracker URL points to your Matomo installation
_paq.push(['setTrackerUrl', 'https://matomo.example.com/matomo.php']);
// Test if matomo.php is accessible
// Visit: https://matomo.example.com/matomo.php
// Should return: GIF89a (1x1 tracking pixel)
Check network requests:
- Open DevTools → Network tab
- Filter by "matomo"
- Look for requests to
matomo.php - Status should be 200 or 204
- Response should be 1x1 GIF or empty
Verify archiving is working:
- For self-hosted Matomo, ensure cron job is running
- Check System → General Settings → Archive Reports
- Configure auto-archiving if not already set
Events Not Tracking
Symptoms: Custom events aren't appearing in Matomo.
Solutions:
- Verify event tracking syntax:
// Track event
_paq.push(['trackEvent', 'Category', 'Action', 'Name', Value]);
// Examples:
_paq.push(['trackEvent', 'Videos', 'Play', 'Product Demo']);
_paq.push(['trackEvent', 'Downloads', 'PDF', 'Whitepaper', 1]);
_paq.push(['trackEvent', 'Engagement', 'Button Click', 'Signup']);
Check event appears in reports:
- Go to Behavior → Events
- May take a few minutes to appear
- Check correct date range
Enable debug mode to verify:
_paq.push(['enableDebug']);
_paq.push(['trackEvent', 'Test', 'Click', 'Debug Test']);
// Check browser console for tracking details
- Verify _paq is loaded before tracking:
// Wait for _paq to be ready
function trackMatomoEvent(category, action, name, value) {
if (typeof _paq !== 'undefined') {
_paq.push(['trackEvent', category, action, name, value]);
} else {
console.error('Matomo not loaded - event not tracked');
}
}
trackMatomoEvent('Button', 'Click', 'CTA');
Goals Not Recording
Symptoms: Goal conversions not showing in reports.
Solutions:
Verify goal is defined:
- Go to Administration → Websites → Manage Goals
- Check goal is active
- Verify goal conditions are correct
Track manual goal conversion:
// Trigger goal conversion manually
_paq.push(['trackGoal', 1]); // Goal ID 1
// With revenue
_paq.push(['trackGoal', 1, 99.99]);
// Verify in console with debug mode
_paq.push(['enableDebug']);
_paq.push(['trackGoal', 1]);
Check goal matching:
- For URL-based goals, verify pattern matches
- Test URL patterns in goal configuration
- Check case sensitivity
Verify timing:
- Goals appear within minutes
- Check correct date range in reports
Ecommerce Tracking Not Working
Symptoms: Ecommerce data not appearing.
Solutions:
Enable ecommerce in Matomo:
- Go to Administration → Websites → Manage
- Enable "Ecommerce" for the website
Track ecommerce order:
// Add product to cart
_paq.push(['addEcommerceItem',
'SKU123', // Product SKU
'Product Name', // Product name
'Category', // Product category
99.99, // Price
1 // Quantity
]);
// Track ecommerce order
_paq.push(['trackEcommerceOrder',
'ORDER-123', // Order ID (required, unique)
109.99, // Grand Total
99.99, // Sub total
8.00, // Tax
5.00, // Shipping
false // Discount
]);
- Track cart update:
// Track abandoned cart
_paq.push(['addEcommerceItem', 'SKU123', 'Product', 'Category', 99.99, 1]);
_paq.push(['trackEcommerceCartUpdate', 99.99]);
- Verify in reports:
- Go to Ecommerce → Overview
- Check Orders, Revenue tabs
- May take a few minutes to appear
User ID Not Working
Symptoms: User ID not being set or tracked.
Solutions:
- Set User ID:
// Set User ID before trackPageView
_paq.push(['setUserId', 'user@example.com']);
_paq.push(['trackPageView']);
// Verify it's set
_paq.push([function() {
console.log('User ID:', this.getUserId());
}]);
- Reset User ID:
// Reset User ID (e.g., on logout)
_paq.push(['resetUserId']);
_paq.push(['trackPageView']);
- Enable User ID reporting:
- Go to Administration → Privacy → Users opt-out
- Configure User ID settings
Cross-Domain Tracking Issues
Symptoms: Sessions breaking across domains.
Solutions:
- Configure cross-domain linking:
// Enable cross-domain linking
_paq.push(['enableCrossDomainLinking']);
// Set domains to track
_paq.push(['setDomains', ['*.example.com', '*.example.org']]);
- Verify link decoration:
// Links to other domains should have pk_vid parameter
// Example: https://example.org/page?pk_vid=...
// Test cross-domain tracking
_paq.push(['enableDebug']);
// Click link to other domain
// Check URL has pk_vid parameter
- Whitelist domains:
// Specify which domains to include
_paq.push(['setDomains', [
'*.example.com',
'subdomain.example.org',
'checkout.example.net'
]]);
Debugging Techniques
Comprehensive Health Check
// Complete Matomo diagnostic
function matomoHealthCheck() {
console.group('Matomo Health Check');
// 1. Check if _paq exists
if (typeof _paq === 'undefined') {
console.error('❌ _paq not defined');
console.groupEnd();
return;
}
console.log('✓ _paq loaded');
// 2. Get tracker info
_paq.push([function() {
var tracker = this;
console.log('Tracker URL:', tracker.getTrackerUrl());
console.log('Site ID:', tracker.getSiteId());
console.log('User ID:', tracker.getUserId() || 'Not set');
console.log('Visitor ID:', tracker.getVisitorId());
}]);
// 3. Send test page view
_paq.push(['trackPageView', 'Health Check Test']);
console.log('✓ Test page view sent');
console.groupEnd();
}
matomoHealthCheck();
Monitor Tracking Requests
// Log all tracking requests
function monitorMatomoRequests() {
const observer = new PerformanceObserver((list) => {
list.getEntries().forEach((entry) => {
if (entry.name.includes('matomo.php')) {
console.log('Matomo tracking request:', entry.name);
console.log('Duration:', entry.duration, 'ms');
}
});
});
observer.observe({ entryTypes: ['resource'] });
}
monitorMatomoRequests();
Test Custom Dimensions
// Set and verify custom dimensions
_paq.push(['setCustomDimension', 1, 'Value 1']);
_paq.push(['setCustomDimension', 2, 'Value 2']);
// Log custom dimensions
_paq.push([function() {
var customDimensions = this.getCustomDimension(1);
console.log('Custom Dimension 1:', customDimensions);
}]);
_paq.push(['trackPageView']);
Browser-Specific Issues
Safari ITP (Intelligent Tracking Prevention)
// Matomo uses first-party cookies, less affected by ITP
// But consider server-side tracking for better persistence
// Set cookie domain explicitly
_paq.push(['setCookieDomain', '*.example.com']);
_paq.push(['setDomains', ['*.example.com']]);
Content Security Policy (CSP)
<!-- Add Matomo domains to CSP -->
<meta http-equiv="Content-Security-Policy"
content="script-src 'self' https://matomo.example.com 'unsafe-inline';
img-src 'self' https://matomo.example.com;
connect-src 'self' https://matomo.example.com;">
Do Not Track (DNT)
// Check if DNT is respected
_paq.push([function() {
console.log('Respecting DNT:', this.isUserOptedOut());
}]);
// Disable DNT support if needed
_paq.push(['setDoNotTrack', false]);
Self-Hosted Matomo Issues
Archiving Not Running
Symptoms: Reports not updating, old data.
Solutions:
- Check cron job:
# Verify cron job is configured
crontab -l | grep matomo
# Should have something like:
# */5 * * * * /usr/bin/php /path/to/matomo/console core:archive --url=https://matomo.example.com
- Run manual archiving:
# SSH to server and run
cd /path/to/matomo
php console core:archive --url=https://matomo.example.com
- Configure auto-archiving:
- Go to System → General Settings
- Under "Archive Reports" set to "Yes"
- Configure cron to run every 5-15 minutes
Database Performance Issues
// Check if tracking is slow
_paq.push([function() {
var start = Date.now();
this.trackPageView();
var duration = Date.now() - start;
console.log('Tracking took:', duration, 'ms');
if (duration > 1000) {
console.warn('Slow Matomo tracking - check database');
}
}]);
Memory Limit Errors
# Increase PHP memory limit in php.ini
memory_limit = 256M
# Or in .htaccess
php_value memory_limit 256M
Data Quality Issues
Bot Filtering
// Matomo has built-in bot filtering
// Configure in Settings → Websites → Manage
// Check "Exclude visits based on user agent"
// Additional bot detection
_paq.push([function() {
if (/bot|crawler|spider/i.test(navigator.userAgent)) {
console.log('Bot detected - may not track');
}
}]);
Duplicate Tracking
// Prevent duplicate page views
var pageTracked = false;
function trackPageOnce() {
if (!pageTracked) {
_paq.push(['trackPageView']);
pageTracked = true;
}
}
trackPageOnce();
GDPR Compliance
// Require consent before tracking
_paq.push(['requireConsent']);
// After user gives consent
_paq.push(['setConsentGiven']);
// Or require cookie consent
_paq.push(['requireCookieConsent']);
_paq.push(['setCookieConsentGiven']);
// Check consent status
_paq.push([function() {
console.log('Has consent:', this.hasConsent());
}]);
Getting Help
Check Matomo System Check
For self-hosted Matomo:
- Go to Administration → System Check
- Review all system requirements
- Fix any warnings or errors
Diagnostic Report
// Generate comprehensive diagnostic
function matomoDiagnostics() {
console.group('Matomo Diagnostics');
if (typeof _paq === 'undefined') {
console.error('_paq not loaded');
console.groupEnd();
return;
}
_paq.push([function() {
var tracker = this;
console.log('Configuration:');
console.log('- Tracker URL:', tracker.getTrackerUrl());
console.log('- Site ID:', tracker.getSiteId());
console.log('- Cookie Domain:', tracker.getCookieDomain());
console.log('\nUser:');
console.log('- User ID:', tracker.getUserId() || 'Not set');
console.log('- Visitor ID:', tracker.getVisitorId());
console.log('\nSettings:');
console.log('- Link Tracking:', tracker.isLinkTrackingEnabled());
console.log('- Cookie Enabled:', tracker.isCookieEnabled());
console.log('- Has Cookies:', tracker.hasCookies());
}]);
console.groupEnd();
}
matomoDiagnostics();
Contact Support
Matomo Forums:
- forum.matomo.org
- Community support
- Search existing topics
Matomo Documentation:
- matomo.org/docs
- Comprehensive guides
- Developer documentation
Professional Support:
- For self-hosted: Matomo On-Premise Support
- For cloud: Matomo Cloud Support
- Email: support@matomo.org (paid plans)
Best Practices
Regular Testing
// Create test suite
function runMatomoTests() {
console.group('Matomo Tests');
// 1. Test page view
_paq.push(['trackPageView', 'Test Page']);
console.log('✓ Page view tracked');
// 2. Test event
_paq.push(['trackEvent', 'Test', 'Click', 'Test Event']);
console.log('✓ Event tracked');
// 3. Test custom dimension
_paq.push(['setCustomDimension', 1, 'Test Value']);
console.log('✓ Custom dimension set');
// 4. Test user ID
_paq.push(['setUserId', 'test_user']);
console.log('✓ User ID set');
console.groupEnd();
}
runMatomoTests();
Monitor in Production
// Log Matomo errors
window.addEventListener('error', function(e) {
if (e.message && (e.message.includes('matomo') || e.message.includes('piwik'))) {
console.error('Matomo error:', e);
// Send to error tracking service
}
});
// Monitor Matomo availability
setInterval(function() {
if (typeof _paq === 'undefined') {
console.error('Matomo tracker unavailable');
// Alert monitoring service
}
}, 60000); // Check every minute
Testing Checklist
- Matomo script loaded successfully
- Site ID is correct
- Tracker URL is correct and accessible
- Page views tracking
- Events tracking correctly
- Goals recording (if configured)
- Ecommerce tracking (if enabled)
- User ID being set (if applicable)
- Custom dimensions working (if used)
- No console errors
- Network requests successful
- Data appearing in reports