Overview
StatCounter is exclusively a client-side analytics platform. It relies entirely on JavaScript executed in the user's browser to collect and transmit data. There is no server-side SDK or tracking option available.
What This Means
Client-side tracking means:
- JavaScript code runs in the visitor's browser
- Data is collected from the user's session
- Tracking depends on JavaScript being enabled
- Browser environment provides the data context
Server-side tracking (not available in StatCounter):
- Code would run on your web server
- Data would be sent from server to analytics platform
- Would work regardless of browser settings
- Server environment would provide data context
Client-Side Tracking
How It Works
- User visits your page
- Browser loads HTML and StatCounter JavaScript
- JavaScript executes in the browser
- Script collects data (page URL, referrer, browser info, screen size)
- Data sent to StatCounter servers via HTTP request
- StatCounter processes and stores the data
Implementation
StatCounter tracking code:
<script type="text/javascript">
var sc_project=12345678;
var sc_invisible=1;
var sc_security="abcd1234";
</script>
<script type="text/javascript"
src="https://www.statcounter.com/counter/counter.js" async></script>
This code:
- Runs in the browser (client-side)
- Collects information from the DOM and browser APIs
- Sends data directly to StatCounter servers
What Gets Tracked Client-Side
Automatically Collected:
- Page URL and title
- Referrer (previous page or external source)
- Browser type and version
- Operating system
- Screen resolution
- Geographic location (via IP)
- Timestamp of visit
- User agent string
Browser APIs Used:
// Examples of what StatCounter accesses
window.location.href // Current URL
document.title // Page title
document.referrer // Referring page
navigator.userAgent // Browser info
screen.width // Screen dimensions
navigator.language // Browser language
Advantages of Client-Side Tracking
For StatCounter's Use Case
Detailed Browser Information
- Exact browser version
- Screen resolution
- Plugin information
- Real-time user interactions
Accurate Timestamps
- Tracks when user actually viewed the page
- Not when server generated the page
Easy Implementation
- Simple JavaScript snippet
- Works with any web platform
- No server-side code required
JavaScript Event Tracking
- Can capture clicks, scrolls, interactions
- Real-time user behavior
- Dynamic page changes
No Server Load
- Tracking happens on user's device
- No impact on server performance
- Scalable without server upgrades
Code Example
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
</head>
<body>
<h1>Welcome</h1>
<!-- Client-side tracking at end of body -->
<script type="text/javascript">
var sc_project=12345678;
var sc_invisible=1;
var sc_security="abcd1234";
</script>
<script type="text/javascript"
src="https://www.statcounter.com/counter/counter.js" async></script>
</body>
</html>
Limitations of Client-Side Only
What You Cannot Track
Server-Side Events
- API calls
- Background processes
- Cron jobs
- Server-to-server communications
Pre-Render Data
- Server-side rendering metrics
- Build-time information
- Backend processing times
Blocked JavaScript
- Users with JavaScript disabled (rare)
- Aggressive ad blockers
- Privacy-focused browsers
- Bot traffic (some bots don't execute JS)
Backend Operations
- Database queries
- Payment processing
- Email sends
- File uploads
Impact of Client-Side Limitations
Users Not Tracked:
- JavaScript disabled (~2% of users)
- Ad blocker users (~25-40% depending on audience)
- Privacy browsers with strict settings
- Some bot traffic
Events Not Trackable:
- Server-side form submissions
- API endpoint usage
- Backend errors
- Server-side conversions
Workarounds for Server-Side Needs
1. JavaScript-Based Solutions
For events that happen server-side, trigger client-side tracking afterward:
// After form submission (server-side)
// Redirect to a thank you page with tracking
// thank-you.html
<script>
if (typeof _statcounter !== 'undefined') {
_statcounter.record_pageview();
}
</script>
2. Hybrid Approach
Use StatCounter for client-side + another tool for server-side:
// Client-side: StatCounter
<script>/* StatCounter code */</script>
// Server-side: Custom logging
// In your server code (Node.js example)
app.post('/api/action', (req, res) => {
// Custom server-side logging
logger.log('Action performed', { userId: req.userId });
// Send response
res.json({ success: true });
});
3. Beacon API for Last-Minute Tracking
For events that might occur as the page unloads:
// Use navigator.sendBeacon for reliable last-minute tracking
window.addEventListener('beforeunload', function() {
// This sends even if page is closing
navigator.sendBeacon('/log-event', JSON.stringify({
action: 'page_exit',
timestamp: Date.now()
}));
});
Note: This is custom logging, not StatCounter, but can supplement your analytics.
Browser Compatibility
JavaScript Requirements
StatCounter requires JavaScript to be:
- Enabled: User hasn't disabled it
- Supported: Modern browser (all current browsers)
- Executable: No errors blocking execution
Fallback for No JavaScript
StatCounter includes a <noscript> tag for basic tracking:
<noscript>
<div class="statcounter">
<a title="Web Analytics" href="https://statcounter.com/" target="_blank">
<img class="statcounter"
src="https://c.statcounter.com/12345678/0/abcd1234/1/"
alt="Web Analytics"
referrerPolicy="no-referrer-when-downgrade">
</a>
</div>
</noscript>
This tracks via a 1x1 pixel image when JavaScript is disabled, but provides limited data.
Performance Considerations
Client-Side Performance Impact
Positive Aspects:
- Async loading doesn't block page rendering
- Minimal JavaScript payload
- Cached after first load
- No server processing required
Implementation for Best Performance:
<!-- Async loading (non-blocking) -->
<script type="text/javascript"
src="https://www.statcounter.com/counter/counter.js" async></script>
<!-- Or defer for execution after page load -->
<script type="text/javascript"
src="https://www.statcounter.com/counter/counter.js" defer></script>
Measuring Impact
Test performance impact:
// Measure timing
var startTime = performance.now();
// Load StatCounter
var script = document.createElement('script');
script.src = 'https://www.statcounter.com/counter/counter.js';
script.async = true;
script.onload = function() {
var loadTime = performance.now() - startTime;
console.log('StatCounter loaded in:', loadTime, 'ms');
};
document.body.appendChild(script);
Privacy and Ad Blockers
Impact of Ad Blockers
Many ad blockers block analytics scripts:
- uBlock Origin: Blocks StatCounter by default
- Adblock Plus: Often blocks StatCounter
- Privacy Badger: May block after detecting tracking
- Brave Browser: Blocks trackers by default
Result: 25-40% of users may not be tracked depending on your audience.
Privacy-Focused Browsers
Browsers with enhanced privacy block tracking:
- Brave: Aggressive tracker blocking
- Firefox: Enhanced Tracking Protection
- Safari: Intelligent Tracking Prevention
- DuckDuckGo Browser: Blocks trackers
Compliance Considerations
Client-side tracking requires:
Cookie Consent (GDPR/ePrivacy)
- StatCounter uses cookies
- Requires user consent in EU/UK
- Implement consent management
Privacy Policy
- Disclose use of StatCounter
- Explain data collection
- Provide opt-out mechanism
Do Not Track
- Consider honoring DNT headers
- Implement opt-out functionality
Comparison Table
| Feature | Client-Side (StatCounter) | Server-Side (Not Available) |
|---|---|---|
| Browser info | Detailed | Limited |
| User interactions | Full tracking | Not applicable |
| Ad blocker bypass | Blocked | Works |
| JavaScript required | Yes | No |
| Server load | None | Additional load |
| Page performance | Minimal impact | None |
| Bot filtering | Limited | Better control |
| Accuracy | 60-75% of users | ~100% of requests |
| Implementation | Very easy | More complex |
Use Cases and Recommendations
Best Use Cases for StatCounter
StatCounter's client-side approach is ideal for:
Content Websites
- Blogs and news sites
- Portfolio sites
- Informational pages
Small Business Sites
- Simple tracking needs
- Budget-conscious
- Easy implementation required
Visitor Behavior Analysis
- Understanding user demographics
- Page popularity
- Traffic sources
When You Need Server-Side
Consider alternatives if you need:
Ad Blocker Bypass
- Maximum data collection accuracy
- Professional analytics requirements
- Critical business metrics
Server-Side Events
- API usage tracking
- Backend process monitoring
- Server-to-server tracking
Bot Traffic Analysis
- Comprehensive bot detection
- Server log analysis
- API endpoint monitoring
Recommended Alternatives for Server-Side
If you need server-side tracking:
- Matomo: Supports both client and server-side
- Google Analytics 4: Measurement Protocol for server-side
- Plausible: Server-side proxy option
- Custom Solution: Direct server logging
Validation
Verify Client-Side Tracking
1. Check Browser Console:
// Open DevTools console (F12)
// Verify StatCounter loaded
console.log(typeof _statcounter !== 'undefined' ? 'Loaded' : 'Not loaded');
2. Network Tab:
- Open DevTools > Network
- Reload page
- Look for requests to
statcounter.com - Verify 200 status code
3. Test with JavaScript Disabled:
- Disable JavaScript in browser
- Visit your site
- Check if noscript tracking fires (limited data)
4. Test with Ad Blocker:
- Enable ad blocker
- Visit your site
- Verify tracking is blocked (expected)
- Check console for blocked requests
Common Issues
| Issue | Cause | Solution |
|---|---|---|
| No tracking | JavaScript disabled | Enable JS, use noscript fallback |
| Ad blocker blocking | Privacy extensions | Expected, cannot bypass |
| Script not loading | Network issue or typo | Verify URL, check network tab |
| Delayed tracking | Async loading | Normal behavior, data appears within minutes |
| Missing on some pages | Code not on all pages | Add tracking to all templates |
Best Practices
Code Placement
<!-- Recommended: Before </body> -->
<body>
<!-- Your content -->
<!-- StatCounter at end -->
<script type="text/javascript">
var sc_project=12345678;
var sc_invisible=1;
var sc_security="abcd1234";
</script>
<script type="text/javascript"
src="https://www.statcounter.com/counter/counter.js" async></script>
</body>
Async Loading
Always use async attribute:
<script src="https://www.statcounter.com/counter/counter.js" async></script>
Error Handling
Wrap tracking in try-catch for resilience:
try {
if (typeof _statcounter !== 'undefined') {
_statcounter.record_pageview();
}
} catch (e) {
console.error('StatCounter error:', e);
}
Don't Block Page Load
Never make tracking synchronous:
<!-- BAD: Synchronous loading -->
<script src="https://www.statcounter.com/counter/counter.js"></script>
<!-- GOOD: Async loading -->
<script src="https://www.statcounter.com/counter/counter.js" async></script>