940 lines
21 KiB
Markdown
940 lines
21 KiB
Markdown
# Analytics Platform - HOWTO Guide
|
|
|
|
## Table of Contents
|
|
1. [What is This Project?](#what-is-this-project)
|
|
2. [Features Overview](#features-overview)
|
|
3. [Architecture](#architecture)
|
|
4. [Installation](#installation)
|
|
5. [Configuration](#configuration)
|
|
6. [Required Background Tasks](#required-background-tasks)
|
|
7. [Tracking Setup](#tracking-setup)
|
|
8. [How It Works](#how-it-works)
|
|
9. [Database Structure](#database-structure)
|
|
10. [Artisan Commands](#artisan-commands)
|
|
11. [API Documentation](#api-documentation)
|
|
12. [Maintenance](#maintenance)
|
|
|
|
---
|
|
|
|
## What is This Project?
|
|
|
|
This is a **self-hosted web analytics platform** built with Laravel 11. It provides privacy-focused website analytics similar to Google Analytics or Plausible, allowing you to track visitor behavior, conversions, and engagement on your websites without relying on third-party services.
|
|
|
|
### Key Capabilities
|
|
- Real-time visitor tracking
|
|
- Goal and conversion tracking
|
|
- Custom event tracking
|
|
- Funnel analysis
|
|
- Automated alerts and notifications
|
|
- Custom dashboards
|
|
- Export analytics data
|
|
- API access for integrations
|
|
|
|
---
|
|
|
|
## Features Overview
|
|
|
|
### 1. **Visitor Tracking**
|
|
- Automatic page view tracking
|
|
- Session management (30-minute timeout)
|
|
- Device, browser, and OS detection
|
|
- Geolocation (country, region, city)
|
|
- Bot filtering
|
|
- UTM parameter tracking (campaign, source, medium, etc.)
|
|
- Time on page measurement
|
|
|
|
### 2. **Analytics Reports**
|
|
- **Audience**: Geographic distribution, technology breakdown, languages
|
|
- **Acquisition**: Traffic sources, referrers, campaigns
|
|
- **Behavior**: Popular pages, landing pages, exit pages
|
|
- **Events**: Custom event tracking with categories and labels
|
|
- **Conversions**: Goal completions with revenue tracking
|
|
|
|
### 3. **Goals (4 Types)**
|
|
- **URL Destination**: Track when users visit specific pages
|
|
- **Event Match**: Track custom events
|
|
- **Duration**: Sessions longer than X seconds
|
|
- **Pages Per Session**: Sessions with X or more pages
|
|
|
|
### 4. **Advanced Features**
|
|
- **Funnels**: Multi-step conversion tracking
|
|
- **Segments**: Custom visitor segments for filtered reporting
|
|
- **Alerts**: Automated notifications when metrics exceed thresholds
|
|
- **Annotations**: Add notes to specific dates for context
|
|
- **Custom Dashboards**: Drag-and-drop widget management
|
|
|
|
### 5. **Data Management**
|
|
- Automatic daily aggregation for performance
|
|
- Configurable data retention (default: 365 days)
|
|
- CSV export
|
|
- API access with token authentication
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### Technology Stack
|
|
- **Backend**: Laravel 11, PHP 8.2+
|
|
- **Frontend**: Blade templates, Alpine.js, Tailwind CSS
|
|
- **Database**: SQLite (default), MySQL/PostgreSQL compatible
|
|
- **Queue System**: Database-backed (Redis/SQS optional)
|
|
- **Build Tool**: Vite
|
|
|
|
### Data Flow
|
|
|
|
```
|
|
Client Website (tracking script)
|
|
↓ POST /api/collect
|
|
CollectController (validates & queues)
|
|
↓ Queue Job
|
|
ProcessTrackingPayload (processes data)
|
|
↓ Stores in DB
|
|
Raw Tables (visitors, sessions, page_views, events)
|
|
↓ Daily aggregation (02:00 AM)
|
|
Aggregated Tables (daily_aggregates, page_daily_aggregates)
|
|
↓ Used by
|
|
Dashboard & Reports (hybrid: aggregates + real-time)
|
|
```
|
|
|
|
---
|
|
|
|
## Installation
|
|
|
|
### Development Setup
|
|
|
|
```bash
|
|
# Clone the repository
|
|
cd /path/to/analytics
|
|
|
|
# Install dependencies and setup
|
|
composer setup
|
|
|
|
# This runs:
|
|
# - composer install
|
|
# - Creates .env from .env.example
|
|
# - php artisan key:generate
|
|
# - php artisan migrate --force
|
|
# - npm install
|
|
# - npm run build
|
|
|
|
# Start development environment (runs 4 processes)
|
|
composer run dev
|
|
```
|
|
|
|
This starts:
|
|
- Web server: `http://localhost:8000`
|
|
- Queue worker (processes tracking data)
|
|
- Log viewer (Pail)
|
|
- Vite dev server (hot module reload)
|
|
|
|
### Production Setup
|
|
|
|
```bash
|
|
# Install dependencies
|
|
composer install --no-dev --optimize-autoloader
|
|
|
|
# Generate application key
|
|
php artisan key:generate
|
|
|
|
# Run database migrations
|
|
php artisan migrate --force
|
|
|
|
# Build frontend assets
|
|
npm ci
|
|
npm run build
|
|
|
|
# Set proper permissions
|
|
chmod -R 755 storage bootstrap/cache
|
|
chown -R www-data:www-data storage bootstrap/cache
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
### Environment Variables
|
|
|
|
Copy `.env.example` to `.env` and configure:
|
|
|
|
```env
|
|
# Application
|
|
APP_NAME="Analytics Platform"
|
|
APP_ENV=production
|
|
APP_DEBUG=false
|
|
APP_URL=https://yourdomain.com
|
|
|
|
# Database
|
|
DB_CONNECTION=mysql
|
|
DB_HOST=127.0.0.1
|
|
DB_PORT=3306
|
|
DB_DATABASE=analytics
|
|
DB_USERNAME=your_user
|
|
DB_PASSWORD=your_password
|
|
|
|
# Queue (use 'redis' for better performance)
|
|
QUEUE_CONNECTION=database
|
|
|
|
# Mail (for alerts and notifications)
|
|
MAIL_MAILER=smtp
|
|
MAIL_HOST=smtp.mailtrap.io
|
|
MAIL_PORT=2525
|
|
MAIL_USERNAME=null
|
|
MAIL_PASSWORD=null
|
|
MAIL_FROM_ADDRESS=noreply@yourdomain.com
|
|
MAIL_FROM_NAME="${APP_NAME}"
|
|
|
|
# Cache (use 'redis' for better performance)
|
|
CACHE_STORE=database
|
|
|
|
# Session
|
|
SESSION_DRIVER=database
|
|
SESSION_LIFETIME=120
|
|
```
|
|
|
|
### Web Server Configuration
|
|
|
|
#### For Standard Setup (public/ folder)
|
|
Point your web server document root to the `public/` directory.
|
|
|
|
#### For Shared Hosting (engine/ + public_html/)
|
|
|
|
If your hosting has separate folders:
|
|
- `engine/` - Laravel application files
|
|
- `public_html/` - Public web root
|
|
|
|
**Modify `public_html/index.php`:**
|
|
|
|
```php
|
|
<?php
|
|
|
|
use Illuminate\Foundation\Application;
|
|
use Illuminate\Http\Request;
|
|
|
|
define('LARAVEL_START', microtime(true));
|
|
|
|
// Point to engine directory
|
|
if (file_exists($maintenance = __DIR__.'/../engine/storage/framework/maintenance.php')) {
|
|
require $maintenance;
|
|
}
|
|
|
|
require __DIR__.'/../engine/vendor/autoload.php';
|
|
|
|
$app = require_once __DIR__.'/../engine/bootstrap/app.php';
|
|
|
|
// Tell Laravel the public path is public_html
|
|
$app->usePublicPath(__DIR__);
|
|
|
|
$app->handleRequest(Request::capture());
|
|
```
|
|
|
|
---
|
|
|
|
## Required Background Tasks
|
|
|
|
### 1. Queue Worker (CRITICAL)
|
|
|
|
**Purpose**: Processes tracking data from websites
|
|
|
|
Without this, tracking events are queued but never persisted to the database.
|
|
|
|
```bash
|
|
# Start queue worker
|
|
php artisan queue:work database --tries=3 --timeout=60
|
|
```
|
|
|
|
**Production Setup**: Use a process supervisor
|
|
|
|
**Using Supervisor** (recommended):
|
|
|
|
```ini
|
|
# /etc/supervisor/conf.d/analytics-queue.conf
|
|
[program:analytics-queue]
|
|
process_name=%(program_name)s_%(process_num)02d
|
|
command=php /path/to/analytics/artisan queue:work database --tries=3 --timeout=60
|
|
autostart=true
|
|
autorestart=true
|
|
stopasgroup=true
|
|
killasgroup=true
|
|
user=www-data
|
|
numprocs=1
|
|
redirect_stderr=true
|
|
stdout_logfile=/path/to/analytics/storage/logs/queue-worker.log
|
|
stopwaitsecs=3600
|
|
```
|
|
|
|
Then run:
|
|
```bash
|
|
sudo supervisorctl reread
|
|
sudo supervisorctl update
|
|
sudo supervisorctl start analytics-queue:*
|
|
```
|
|
|
|
**Using systemd**:
|
|
|
|
```ini
|
|
# /etc/systemd/system/analytics-queue.service
|
|
[Unit]
|
|
Description=Analytics Queue Worker
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=www-data
|
|
WorkingDirectory=/path/to/analytics
|
|
ExecStart=/usr/bin/php /path/to/analytics/artisan queue:work database --tries=3 --timeout=60
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
```
|
|
|
|
Enable and start:
|
|
```bash
|
|
sudo systemctl enable analytics-queue
|
|
sudo systemctl start analytics-queue
|
|
```
|
|
|
|
### 2. Task Scheduler (CRITICAL)
|
|
|
|
**Purpose**: Runs scheduled tasks (aggregation, purging, alerts)
|
|
|
|
Add to crontab:
|
|
|
|
```bash
|
|
# Edit crontab
|
|
crontab -e
|
|
|
|
# Add this line
|
|
* * * * * cd /path/to/analytics && php artisan schedule:run >> /dev/null 2>&1
|
|
```
|
|
|
|
This executes:
|
|
- **Daily at 02:00 AM**: `analytics:aggregate` - Rolls up data into daily aggregates
|
|
- **Daily at 03:00 AM**: `analytics:purge --force` - Deletes old raw data
|
|
- **Every hour**: `analytics:check-alerts` - Evaluates alerts and sends notifications
|
|
|
|
Without the scheduler:
|
|
- Reports will be slower (no aggregated data)
|
|
- Old data will accumulate and bloat the database
|
|
- Alerts will never trigger
|
|
|
|
---
|
|
|
|
## Tracking Setup
|
|
|
|
### 1. Create a Website
|
|
|
|
1. Register/login to the analytics platform
|
|
2. Navigate to **Websites** → **Add Website**
|
|
3. Enter website name and domain
|
|
4. Copy the tracking ID (e.g., `abc123def456`)
|
|
|
|
### 2. Install Tracking Script
|
|
|
|
Add this script to your website's HTML (before `</head>`):
|
|
|
|
**Option 1: JavaScript Snippet**
|
|
|
|
```html
|
|
<script async src="https://analytics.yourdomain.com/api/t/YOUR_TRACKING_ID.js"></script>
|
|
```
|
|
|
|
**Option 2: Self-hosted Script**
|
|
|
|
```html
|
|
<script>
|
|
!function(t,e,a){/* tracking script */}(window,document,"https://analytics.yourdomain.com","YOUR_TRACKING_ID");
|
|
</script>
|
|
```
|
|
|
|
**Option 3: No-JavaScript Fallback**
|
|
|
|
```html
|
|
<noscript>
|
|
<img src="https://analytics.yourdomain.com/api/collect/pixel/YOUR_TRACKING_ID"
|
|
alt=""
|
|
style="position:absolute;left:-9999px;" />
|
|
</noscript>
|
|
```
|
|
|
|
### 3. Track Custom Events
|
|
|
|
```javascript
|
|
// Track a custom event
|
|
ta('event', 'button_click', {
|
|
category: 'engagement',
|
|
label: 'signup_button',
|
|
value: 1
|
|
});
|
|
|
|
// Track a purchase
|
|
ta('event', 'purchase', {
|
|
category: 'ecommerce',
|
|
value: 99.99
|
|
});
|
|
```
|
|
|
|
### 4. SPA Support
|
|
|
|
For single-page applications (React, Vue, etc.), the tracker automatically detects route changes via `pushState` and `popstate`. You can also manually track page views:
|
|
|
|
```javascript
|
|
// Manual page view tracking
|
|
ta('pageview');
|
|
```
|
|
|
|
---
|
|
|
|
## How It Works
|
|
|
|
### Tracking Process
|
|
|
|
1. **Client-side**: Tracking script loads on visitor's browser
|
|
2. **Collection**: Script sends tracking data to `/api/collect`
|
|
3. **Validation**: `CollectController` validates tracking ID and domain
|
|
4. **Queueing**: Tracking payload is queued as `ProcessTrackingPayload` job
|
|
5. **Processing**: Queue worker picks up job and:
|
|
- Creates/updates **Visitor** record (with geolocation)
|
|
- Creates/retrieves **AnalyticsSession** (30-min timeout)
|
|
- Records **PageView** or **Event**
|
|
- Evaluates active **Goals** and records conversions
|
|
- Updates session metrics (duration, bounce status)
|
|
6. **Aggregation**: Daily at 02:00 AM, raw data is rolled up into aggregates
|
|
7. **Reporting**: Dashboard queries combine aggregated + real-time data
|
|
|
|
### Session Logic
|
|
|
|
- **Session Start**: First page view from a visitor
|
|
- **Session Timeout**: 30 minutes of inactivity
|
|
- **Session Duration**: Time between first and last page view
|
|
- **Bounce**: Session with only 1 page view
|
|
- **Exit Page**: Last page viewed in session
|
|
|
|
### Goal Evaluation
|
|
|
|
Goals are evaluated in real-time during tracking:
|
|
|
|
1. **URL Destination**: Matches current page URL
|
|
- Exact: URL must match exactly
|
|
- Starts with: URL must start with pattern
|
|
- Contains: URL must contain pattern
|
|
- Regex: URL must match regex pattern
|
|
|
|
2. **Event Match**: Matches event name (and optionally category)
|
|
|
|
3. **Duration**: Session duration exceeds threshold
|
|
|
|
4. **Pages Per Session**: Page count exceeds threshold
|
|
|
|
### Data Aggregation
|
|
|
|
Raw tracking data is aggregated daily to improve query performance:
|
|
|
|
**Daily Aggregates** (per website, per day):
|
|
- Total visitors (unique)
|
|
- Total sessions
|
|
- Total page views
|
|
- Bounce count
|
|
- Total session duration
|
|
|
|
**Page Daily Aggregates** (per website, per page, per day):
|
|
- Page views
|
|
- Unique page views
|
|
- Total time on page
|
|
- Bounce count
|
|
|
|
**Query Strategy**:
|
|
- Historical dates: Query aggregated tables
|
|
- Today: Query raw tables
|
|
- Results are merged for complete picture
|
|
|
|
---
|
|
|
|
## Database Structure
|
|
|
|
### Core Tables
|
|
|
|
| Table | Description |
|
|
|-------|-------------|
|
|
| `users` | User accounts |
|
|
| `websites` | Tracked websites with settings |
|
|
| `visitors` | Unique visitors with device/location info |
|
|
| `analytics_sessions` | User sessions with UTM data |
|
|
| `page_views` | Individual page visits |
|
|
| `events` | Custom events with metadata |
|
|
| `goals` | Conversion goal definitions |
|
|
| `goal_conversions` | Goal completion records |
|
|
| `funnels` | Funnel definitions |
|
|
| `segments` | Custom visitor segments |
|
|
| `alerts` | Alert rule definitions |
|
|
| `alert_notifications` | Triggered alert records |
|
|
| `annotations` | Date annotations |
|
|
| `dashboard_widgets` | Custom dashboard layouts |
|
|
| `daily_aggregates` | Pre-computed daily metrics |
|
|
| `page_daily_aggregates` | Per-page daily metrics |
|
|
|
|
### Data Retention
|
|
|
|
- **Raw Data**: Retained for 365 days (configurable per website)
|
|
- **Aggregated Data**: Retained indefinitely
|
|
- **Purge Schedule**: Daily at 03:00 AM via `analytics:purge`
|
|
|
|
---
|
|
|
|
## Artisan Commands
|
|
|
|
### Analytics Commands
|
|
|
|
#### 1. Aggregate Data
|
|
```bash
|
|
php artisan analytics:aggregate [options]
|
|
|
|
Options:
|
|
--date=YYYY-MM-DD Aggregate specific date (default: yesterday)
|
|
--website=ID Aggregate specific website (default: all)
|
|
|
|
# Examples
|
|
php artisan analytics:aggregate
|
|
php artisan analytics:aggregate --date=2026-03-20
|
|
php artisan analytics:aggregate --website=1
|
|
```
|
|
|
|
**Important**: Cannot aggregate today's data (prevents incomplete aggregations)
|
|
|
|
#### 2. Purge Old Data
|
|
```bash
|
|
php artisan analytics:purge [options]
|
|
|
|
Options:
|
|
--website=ID Purge specific website (default: all)
|
|
--force Skip confirmation prompt
|
|
|
|
# Examples
|
|
php artisan analytics:purge --force
|
|
php artisan analytics:purge --website=1
|
|
```
|
|
|
|
Deletes raw data older than retention period (default: 365 days).
|
|
|
|
#### 3. Check Alerts
|
|
```bash
|
|
php artisan analytics:check-alerts
|
|
```
|
|
|
|
Evaluates all active alerts and triggers notifications.
|
|
|
|
### Queue Commands
|
|
|
|
```bash
|
|
# Process queue jobs
|
|
php artisan queue:work database --tries=3
|
|
|
|
# List failed jobs
|
|
php artisan queue:failed
|
|
|
|
# Retry failed job
|
|
php artisan queue:retry {job-id}
|
|
|
|
# Retry all failed jobs
|
|
php artisan queue:retry all
|
|
|
|
# Flush failed jobs
|
|
php artisan queue:flush
|
|
```
|
|
|
|
### Cache Commands
|
|
|
|
```bash
|
|
# Clear application cache
|
|
php artisan cache:clear
|
|
|
|
# Clear config cache
|
|
php artisan config:clear
|
|
|
|
# Clear route cache
|
|
php artisan route:clear
|
|
|
|
# Clear view cache
|
|
php artisan view:clear
|
|
|
|
# Cache config for production
|
|
php artisan config:cache
|
|
php artisan route:cache
|
|
php artisan view:cache
|
|
```
|
|
|
|
---
|
|
|
|
## API Documentation
|
|
|
|
### Authentication
|
|
|
|
Generate API token in dashboard: **Profile** → **API Tokens** → **Create Token**
|
|
|
|
Include in requests:
|
|
```bash
|
|
Authorization: Bearer YOUR_API_TOKEN
|
|
```
|
|
|
|
### Endpoints
|
|
|
|
#### GET /api/v1/websites
|
|
List all websites
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
|
https://analytics.yourdomain.com/api/v1/websites
|
|
```
|
|
|
|
#### GET /api/v1/websites/{id}/stats
|
|
Get website statistics
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
|
"https://analytics.yourdomain.com/api/v1/websites/1/stats?from=2026-03-01&to=2026-03-22"
|
|
```
|
|
|
|
Query Parameters:
|
|
- `from` (required): Start date (YYYY-MM-DD)
|
|
- `to` (required): End date (YYYY-MM-DD)
|
|
|
|
#### GET /api/v1/websites/{id}/pages
|
|
Get page analytics
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer YOUR_TOKEN" \
|
|
"https://analytics.yourdomain.com/api/v1/websites/1/pages?from=2026-03-01&to=2026-03-22&limit=20"
|
|
```
|
|
|
|
#### GET /api/v1/websites/{id}/referrers
|
|
Get referrer data
|
|
|
|
#### GET /api/v1/websites/{id}/events
|
|
Get event data
|
|
|
|
#### GET /api/v1/websites/{id}/visitors
|
|
Get visitor data
|
|
|
|
---
|
|
|
|
## Maintenance
|
|
|
|
### Daily Tasks (Automated)
|
|
|
|
These run automatically via cron (see [Task Scheduler](#2-task-scheduler-critical)):
|
|
|
|
- **02:00 AM**: Data aggregation
|
|
- **03:00 AM**: Old data purging
|
|
- **Every hour**: Alert evaluation
|
|
|
|
### Weekly Tasks (Manual)
|
|
|
|
#### Check Queue Status
|
|
```bash
|
|
# Check if queue worker is running
|
|
ps aux | grep "queue:work"
|
|
|
|
# Check failed jobs
|
|
php artisan queue:failed
|
|
|
|
# Retry failed jobs
|
|
php artisan queue:retry all
|
|
```
|
|
|
|
#### Monitor Disk Space
|
|
```bash
|
|
# Check database size
|
|
du -h database/database.sqlite
|
|
|
|
# Check storage usage
|
|
du -sh storage/
|
|
```
|
|
|
|
#### Review Logs
|
|
```bash
|
|
# Check application logs
|
|
tail -f storage/logs/laravel.log
|
|
|
|
# Check queue worker logs (if using supervisor)
|
|
tail -f storage/logs/queue-worker.log
|
|
```
|
|
|
|
### Monthly Tasks
|
|
|
|
#### Database Optimization
|
|
|
|
**SQLite**:
|
|
```bash
|
|
sqlite3 database/database.sqlite "VACUUM;"
|
|
```
|
|
|
|
**MySQL**:
|
|
```sql
|
|
OPTIMIZE TABLE visitors, analytics_sessions, page_views, events, daily_aggregates, page_daily_aggregates;
|
|
```
|
|
|
|
#### Review Data Retention
|
|
|
|
Check if retention settings are appropriate:
|
|
1. Navigate to **Website Settings**
|
|
2. Review **Data Retention** setting (default: 365 days)
|
|
3. Adjust based on compliance requirements
|
|
|
|
### Backup Strategy
|
|
|
|
#### Database Backup
|
|
|
|
**SQLite**:
|
|
```bash
|
|
# Copy database file
|
|
cp database/database.sqlite backups/database-$(date +%Y%m%d).sqlite
|
|
|
|
# Compress
|
|
gzip backups/database-$(date +%Y%m%d).sqlite
|
|
```
|
|
|
|
**MySQL**:
|
|
```bash
|
|
mysqldump -u user -p analytics > backups/analytics-$(date +%Y%m%d).sql
|
|
gzip backups/analytics-$(date +%Y%m%d).sql
|
|
```
|
|
|
|
#### Application Backup
|
|
```bash
|
|
# Backup entire application
|
|
tar -czf analytics-backup-$(date +%Y%m%d).tar.gz \
|
|
--exclude=node_modules \
|
|
--exclude=vendor \
|
|
--exclude=storage/logs \
|
|
/path/to/analytics
|
|
```
|
|
|
|
### Troubleshooting
|
|
|
|
#### Tracking Not Working
|
|
|
|
1. **Check queue worker is running**:
|
|
```bash
|
|
ps aux | grep "queue:work"
|
|
```
|
|
|
|
2. **Check failed jobs**:
|
|
```bash
|
|
php artisan queue:failed
|
|
```
|
|
|
|
3. **Check tracking domain matches**:
|
|
- Ensure website domain in dashboard matches actual domain
|
|
- Domain validation is case-insensitive but must match
|
|
|
|
4. **Check browser console**:
|
|
- Look for CORS errors
|
|
- Verify tracking script loads
|
|
|
|
5. **Check logs**:
|
|
```bash
|
|
tail -f storage/logs/laravel.log
|
|
```
|
|
|
|
#### Dashboard Shows No Data
|
|
|
|
1. **Check if aggregation ran**:
|
|
```bash
|
|
php artisan analytics:aggregate --date=yesterday
|
|
```
|
|
|
|
2. **Check date range** - today's data may not appear if only querying aggregates
|
|
|
|
3. **Verify tracking is working** - check raw tables:
|
|
```sql
|
|
SELECT COUNT(*) FROM page_views WHERE created_at > datetime('now', '-1 hour');
|
|
```
|
|
|
|
#### Alerts Not Triggering
|
|
|
|
1. **Check cron is running**:
|
|
```bash
|
|
grep CRON /var/log/syslog
|
|
```
|
|
|
|
2. **Manually run alert check**:
|
|
```bash
|
|
php artisan analytics:check-alerts
|
|
```
|
|
|
|
3. **Check mail configuration**:
|
|
```bash
|
|
php artisan tinker
|
|
>>> Mail::raw('Test', function($msg) { $msg->to('test@example.com')->subject('Test'); });
|
|
```
|
|
|
|
#### High Disk Usage
|
|
|
|
1. **Run aggregation** (if not running):
|
|
```bash
|
|
php artisan analytics:aggregate
|
|
```
|
|
|
|
2. **Purge old data**:
|
|
```bash
|
|
php artisan analytics:purge --force
|
|
```
|
|
|
|
3. **Adjust retention settings** in website configuration
|
|
|
|
---
|
|
|
|
## Performance Optimization
|
|
|
|
### 1. Use Redis for Queue & Cache
|
|
|
|
```env
|
|
QUEUE_CONNECTION=redis
|
|
CACHE_STORE=redis
|
|
SESSION_DRIVER=redis
|
|
|
|
REDIS_HOST=127.0.0.1
|
|
REDIS_PASSWORD=null
|
|
REDIS_PORT=6379
|
|
```
|
|
|
|
### 2. Database Indexing
|
|
|
|
Ensure migrations have run (indexes are included):
|
|
```bash
|
|
php artisan migrate
|
|
```
|
|
|
|
### 3. Cache Configuration
|
|
|
|
In production:
|
|
```bash
|
|
php artisan config:cache
|
|
php artisan route:cache
|
|
php artisan view:cache
|
|
```
|
|
|
|
### 4. Enable OPcache
|
|
|
|
Add to `php.ini`:
|
|
```ini
|
|
opcache.enable=1
|
|
opcache.memory_consumption=256
|
|
opcache.interned_strings_buffer=16
|
|
opcache.max_accelerated_files=10000
|
|
opcache.revalidate_freq=2
|
|
```
|
|
|
|
### 5. Queue Workers
|
|
|
|
Run multiple queue workers for high traffic:
|
|
```bash
|
|
# Run 3 workers
|
|
php artisan queue:work database --tries=3 &
|
|
php artisan queue:work database --tries=3 &
|
|
php artisan queue:work database --tries=3 &
|
|
```
|
|
|
|
Or use supervisor with `numprocs=3`.
|
|
|
|
---
|
|
|
|
## Security Considerations
|
|
|
|
### 1. Environment File
|
|
- Never commit `.env` to version control
|
|
- Use strong `APP_KEY` (generated automatically)
|
|
- Set `APP_DEBUG=false` in production
|
|
|
|
### 2. Database Credentials
|
|
- Use strong passwords
|
|
- Restrict database user permissions
|
|
- Use separate database user for application
|
|
|
|
### 3. HTTPS
|
|
- Always use HTTPS in production
|
|
- Update `APP_URL` to use `https://`
|
|
- Tracking script requires HTTPS for secure cookies
|
|
|
|
### 4. CORS
|
|
- CORS is enabled for `/api/collect` and `/api/t/{id}.js`
|
|
- Only these endpoints are publicly accessible
|
|
- Dashboard requires authentication
|
|
|
|
### 5. Rate Limiting
|
|
- Tracking endpoints have rate limiting
|
|
- API endpoints have Sanctum rate limiting
|
|
- Adjust in `app/Http/Middleware` if needed
|
|
|
|
---
|
|
|
|
## Support & Resources
|
|
|
|
### Documentation
|
|
- Laravel 11: https://laravel.com/docs/11.x
|
|
- Alpine.js: https://alpinejs.dev
|
|
- Tailwind CSS: https://tailwindcss.com
|
|
|
|
### Logs
|
|
- Application: `storage/logs/laravel.log`
|
|
- Queue Worker: Check supervisor/systemd logs
|
|
|
|
### Common Paths
|
|
- **Application**: `/path/to/analytics`
|
|
- **Public**: `/path/to/analytics/public`
|
|
- **Storage**: `/path/to/analytics/storage`
|
|
- **Database**: `/path/to/analytics/database/database.sqlite`
|
|
- **Logs**: `/path/to/analytics/storage/logs/`
|
|
|
|
---
|
|
|
|
## Quick Reference
|
|
|
|
### Essential Commands
|
|
|
|
```bash
|
|
# Development
|
|
composer run dev # Start dev environment
|
|
|
|
# Queue
|
|
php artisan queue:work database # Start queue worker
|
|
php artisan queue:failed # List failed jobs
|
|
php artisan queue:retry all # Retry failed jobs
|
|
|
|
# Analytics
|
|
php artisan analytics:aggregate # Aggregate yesterday's data
|
|
php artisan analytics:purge --force # Purge old data
|
|
php artisan analytics:check-alerts # Check alerts
|
|
|
|
# Cache
|
|
php artisan cache:clear # Clear cache
|
|
php artisan config:cache # Cache config (production)
|
|
|
|
# Maintenance
|
|
php artisan down # Enable maintenance mode
|
|
php artisan up # Disable maintenance mode
|
|
```
|
|
|
|
### Cron Entry
|
|
|
|
```cron
|
|
* * * * * cd /path/to/analytics && php artisan schedule:run >> /dev/null 2>&1
|
|
```
|
|
|
|
### Supervisor Config
|
|
|
|
```ini
|
|
[program:analytics-queue]
|
|
command=php /path/to/analytics/artisan queue:work database --tries=3
|
|
autostart=true
|
|
autorestart=true
|
|
user=www-data
|
|
```
|
|
|
|
---
|
|
|
|
**Last Updated**: 2026-03-22
|
|
**Laravel Version**: 11.50.0
|
|
**PHP Version**: 8.2+ (Compatible with 8.3)
|