本文目录导读:

我来帮你实现一个完整的浏览数据统计脚本,这里提供几种不同场景的实现方案:
基础页面访问统计(纯前端)
// page-view-stats.js
class PageViewTracker {
constructor(options = {}) {
this.options = {
storageKey: 'page_views', // localStorage键名
trackHistory: true, // 是否记录历史浏览
...options
};
this.init();
}
init() {
// 增加页面访问次数
this.incrementPageView();
// 记录浏览历史
if (this.options.trackHistory) {
this.recordHistory();
}
// 监听页面关闭/切换
this.listenVisibilityChange();
}
// 获取当前页面访问次数
getPageViews() {
const pageKey = this.getPageKey();
const data = JSON.parse(localStorage.getItem(this.options.storageKey) || '{}');
return data[pageKey] || 0;
}
// 增加页面访问次数
incrementPageView() {
const pageKey = this.getPageKey();
const data = JSON.parse(localStorage.getItem(this.options.storageKey) || '{}');
data[pageKey] = (data[pageKey] || 0) + 1;
localStorage.setItem(this.options.storageKey, JSON.stringify(data));
// 触发自定义事件
this.emitEvent('pageView', {
page: pageKey,
count: data[pageKey],
timestamp: Date.now()
});
}
// 获取页面标识
getPageKey() {
return window.location.pathname + window.location.search;
}
// 记录浏览历史
recordHistory() {
const historyKey = 'page_history';
const history = JSON.parse(localStorage.getItem(historyKey) || '[]');
history.push({
page: this.getPageKey(),
title: document.title,
time: new Date().toISOString(),
referrer: document.referrer
});
// 只保留最近1000条记录
if (history.length > 1000) {
history.shift();
}
localStorage.setItem(historyKey, JSON.stringify(history));
}
// 监听页面可见性变化
listenVisibilityChange() {
document.addEventListener('visibilitychange', () => {
if (document.hidden) {
this.emitEvent('pageHidden');
} else {
this.emitEvent('pageVisible');
}
});
}
// 触发自定义事件
emitEvent(name, data = {}) {
const event = new CustomEvent(name, { detail: data });
document.dispatchEvent(event);
}
// 获取统计数据
getStats() {
const data = JSON.parse(localStorage.getItem(this.options.storageKey) || '{}');
const history = JSON.parse(localStorage.getItem('page_history') || '[]');
return {
totalViews: Object.values(data).reduce((a, b) => a + b, 0),
pageViews: data,
recentHistory: history.slice(-10) // 最近10条记录
};
}
}
使用第三方服务(百度统计)
<!-- 在HTML中引入 -->
<script>
var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?你的跟踪ID";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
// 自定义事件跟踪
function trackEvent(category, action, label, value) {
_hmt.push(['_trackEvent', category, action, label, value]);
}
</script>
完整的Node.js + MongoDB后端方案
// server.js - 后端统计服务
const express = require('express');
const mongoose = require('mongoose');
const app = express();
// MongoDB模型
const PageViewSchema = new mongoose.Schema({
page: String,
ip: String,
userAgent: String,
referrer: String,
timestamp: { type: Date, default: Date.now },
sessionId: String
});
const PageView = mongoose.model('PageView', PageViewSchema);
// 统计中间件
app.use(async (req, res, next) => {
// 排除静态资源和某些路径
const excludePaths = ['/favicon.ico', '/robots.txt', '/api/'];
if (excludePaths.some(path => req.path.startsWith(path))) {
return next();
}
try {
await PageView.create({
page: req.path,
ip: req.ip,
userAgent: req.headers['user-agent'],
referrer: req.headers['referer'] || '',
sessionId: req.sessionID
});
} catch (error) {
console.error('统计记录失败:', error);
}
next();
});
// API接口
app.get('/api/stats', async (req, res) => {
try {
const stats = await PageView.aggregate([
{
$group: {
_id: '$page',
count: { $sum: 1 },
lastVisit: { $max: '$timestamp' }
}
},
{ $sort: { count: -1 } }
]);
res.json({
total: await PageView.countDocuments(),
pages: stats
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log('统计服务运行在 http://localhost:3000');
});
发送统计数据到服务器
// analytics.js - 前端发送统计
class Analytics {
constructor(endpoint) {
this.endpoint = endpoint;
this.sessionId = this.generateSessionId();
// 页面加载完成时发送数据
window.addEventListener('load', () => this.sendPageView());
// 页面退出前发送数据
window.addEventListener('beforeunload', () => this.sendBeacon());
}
// 生成会话ID
generateSessionId() {
let sessionId = sessionStorage.getItem('session_id');
if (!sessionId) {
sessionId = 'sess_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
sessionStorage.setItem('session_id', sessionId);
}
return sessionId;
}
// 发送页面浏览
sendPageView() {
const data = {
type: 'pageview',
sessionId: this.sessionId,
page: window.location.pathname,
title: document.title,
referrer: document.referrer,
screenWidth: screen.width,
screenHeight: screen.height,
language: navigator.language,
timestamp: Date.now()
};
this.sendData('/api/track', data);
}
// 使用Beacon API发送
sendBeacon() {
const data = {
type: 'pageleave',
sessionId: this.sessionId,
timeSpent: Date.now() - performance.timing.navigationStart
};
navigator.sendBeacon(this.endpoint + '/api/beacon', JSON.stringify(data));
}
// 发送数据
async sendData(path, data) {
try {
const response = await fetch(this.endpoint + path, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (!response.ok) {
console.error('统计发送失败:', response.status);
}
} catch (error) {
console.error('统计发送错误:', error);
}
}
// 自定义事件跟踪
trackEvent(eventName, properties = {}) {
this.sendData('/api/event', {
type: 'event',
sessionId: this.sessionId,
event: eventName,
properties,
timestamp: Date.now()
});
}
}
// 使用示例
const analytics = new Analytics('https://your-server.com');
// 点击按钮时跟踪
document.getElementById('buy-now').addEventListener('click', () => {
analytics.trackEvent('click_buy_now', { price: 99.9 });
});
使用建议
选择适合的方案:
- 简单页面统计:使用localStorage的前端方案
- 专业网站统计:百度统计、Google Analytics
- 自建统计系统:后端方案 + 前端发送
最佳实践:
- 数据隐私:遵守相关法规,告知用户
- 压缩数据:批量发送减少请求
- 降级方案:确保统计失败不影响页面功能
- 去重处理:避免重复统计(防刷)
需要我详细解释某个部分或提供特定场景的优化吗?