Initial commit: AutonetSellCar platform with deployment system
- Frontend: Next.js 14 with TypeScript - Backend: FastAPI with SQLAlchemy - Agent: Carmodoo sync agent - Deployment: Docker Compose based staging/production setup - Scripts: Automated deployment with rollback support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
111
backend/app/models/visitor.py
Normal file
111
backend/app/models/visitor.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""
|
||||
Visitor tracking models for analytics
|
||||
"""
|
||||
from sqlalchemy import Column, Integer, String, DateTime, Text, Index
|
||||
from sqlalchemy.sql import func
|
||||
from ..database import Base
|
||||
|
||||
|
||||
class VisitorLog(Base):
|
||||
"""
|
||||
Raw visitor log - tracks every page visit
|
||||
IP addresses are hashed for privacy
|
||||
"""
|
||||
__tablename__ = "visitor_logs"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
|
||||
# Visitor identification (hashed for privacy)
|
||||
visitor_hash = Column(String(64), nullable=False, index=True) # SHA256 hash of IP + User-Agent
|
||||
ip_hash = Column(String(64), nullable=False) # SHA256 hash of IP only
|
||||
|
||||
# Session tracking
|
||||
session_id = Column(String(64), nullable=True, index=True) # Cookie-based session ID
|
||||
user_id = Column(Integer, nullable=True, index=True) # If logged in
|
||||
|
||||
# Page information
|
||||
page_path = Column(String(500), nullable=False, index=True)
|
||||
page_title = Column(String(200), nullable=True)
|
||||
referrer = Column(String(1000), nullable=True)
|
||||
referrer_domain = Column(String(200), nullable=True, index=True)
|
||||
|
||||
# Device information
|
||||
device_type = Column(String(20), nullable=True, index=True) # mobile, desktop, tablet
|
||||
browser = Column(String(50), nullable=True, index=True)
|
||||
browser_version = Column(String(20), nullable=True)
|
||||
os = Column(String(50), nullable=True)
|
||||
os_version = Column(String(20), nullable=True)
|
||||
|
||||
# Geographic information (from IP geolocation)
|
||||
country = Column(String(50), nullable=True, index=True)
|
||||
country_code = Column(String(5), nullable=True)
|
||||
city = Column(String(100), nullable=True)
|
||||
region = Column(String(100), nullable=True)
|
||||
|
||||
# UTM parameters
|
||||
utm_source = Column(String(100), nullable=True)
|
||||
utm_medium = Column(String(100), nullable=True)
|
||||
utm_campaign = Column(String(100), nullable=True)
|
||||
|
||||
# Timestamp
|
||||
visited_at = Column(DateTime(timezone=True), server_default=func.now(), index=True)
|
||||
|
||||
|
||||
class VisitorDailyStats(Base):
|
||||
"""
|
||||
Aggregated daily statistics for faster queries
|
||||
Pre-computed by a scheduled task
|
||||
"""
|
||||
__tablename__ = "visitor_daily_stats"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
stat_date = Column(String(10), nullable=False, unique=True, index=True) # YYYY-MM-DD
|
||||
|
||||
# Visitor counts
|
||||
total_visits = Column(Integer, default=0)
|
||||
unique_visitors = Column(Integer, default=0)
|
||||
|
||||
# Device breakdown (JSON string)
|
||||
device_breakdown = Column(Text) # {"mobile": 100, "desktop": 200, "tablet": 20}
|
||||
|
||||
# Browser breakdown (JSON string)
|
||||
browser_breakdown = Column(Text) # {"Chrome": 150, "Safari": 100, ...}
|
||||
|
||||
# Country breakdown (JSON string)
|
||||
country_breakdown = Column(Text) # {"MN": 200, "RU": 50, "KR": 30}
|
||||
|
||||
# Top pages (JSON string)
|
||||
top_pages = Column(Text) # [{"path": "/", "views": 500}, ...]
|
||||
|
||||
# Top referrers (JSON string)
|
||||
top_referrers = Column(Text) # [{"domain": "google.com", "visits": 100}, ...]
|
||||
|
||||
# Timestamps
|
||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now())
|
||||
|
||||
|
||||
class VisitorSession(Base):
|
||||
"""
|
||||
Track visitor sessions for better analytics
|
||||
"""
|
||||
__tablename__ = "visitor_sessions"
|
||||
|
||||
id = Column(Integer, primary_key=True, index=True)
|
||||
session_id = Column(String(64), unique=True, nullable=False, index=True)
|
||||
visitor_hash = Column(String(64), nullable=False, index=True)
|
||||
user_id = Column(Integer, nullable=True)
|
||||
|
||||
# Session info
|
||||
first_page = Column(String(500))
|
||||
last_page = Column(String(500))
|
||||
page_count = Column(Integer, default=1)
|
||||
|
||||
# Device/geo info (copied from first visit)
|
||||
device_type = Column(String(20))
|
||||
browser = Column(String(50))
|
||||
country = Column(String(50))
|
||||
|
||||
# Timestamps
|
||||
started_at = Column(DateTime(timezone=True), server_default=func.now(), index=True)
|
||||
last_activity_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||
Reference in New Issue
Block a user