Login Attempt Monitor
A comprehensive WordPress plugin that monitors and logs all login attempts (successful and failed) with detailed information including username, IP address, status, browser info, and timestamp.
YT Login Attempt Monitor
A comprehensive WordPress plugin that monitors and logs all login attempts (successful and failed) with detailed information including username, IP address, status, browser info, and timestamp.
Description
The Login Attempt Monitor plugin provides complete visibility into all login activity on your WordPress site. Track successful logins, monitor failed attempts, identify potential security threats, and maintain detailed logs for compliance and security auditing.
Features
- Comprehensive Logging: Records both successful and failed login attempts
- Detailed Information: Username, User ID, IP address, browser info, timestamp
- Custom Database Table: Dedicated table for optimal performance
- Admin Dashboard: Clean interface under Users → Login Log
- Live Statistics: Total, successful, failed, and today's attempts
- Advanced Filtering: Filter by status, search by username/IP
- Pagination: Handle thousands of logs efficiently
- Export to CSV: Download complete log history
- Clear Logs: Bulk delete functionality
- Auto Cleanup: Automatic deletion of old logs based on retention policy
- IP Geolocation: Click IP addresses for lookup (external service)
- Browser Detection: Parse and display browser information
- Configurable Settings: Control what gets logged and for how long
- Maximum Log Limit: Prevent database bloat with configurable limits
- Time Formatting: Human-readable time differences ("2 hours ago")
- Responsive Design: Mobile-friendly admin interface
- Search Highlighting: Visual search term highlighting
- Keyboard Shortcuts: Ctrl+R (refresh), Ctrl+E (export)
- AJAX Operations: Delete logs without page reload
- Security Focused: Proper escaping, nonces, and capability checks
Installation
- Upload
yt-login-attempt-monitor.php
to/wp-content/plugins/
- Upload
yt-login-attempt-monitor.css
to the same directory - Upload
yt-login-attempt-monitor.js
to the same directory - Activate the plugin through the 'Plugins' menu
- View logs at Users → Login Log
- Configure settings at Settings → Login Monitor
Usage
Viewing Login Logs
- Go to Users → Login Log
- View statistics at the top:
- Total Attempts
- Successful Logins
- Failed Attempts
- Today's Activity
- Browse the log table with full details
- Use filters to narrow results
Filtering Logs
By Status:
- All Statuses
- Successful only
- Failed only
By Search:
- Search by username
- Search by IP address
- Real-time search highlighting
Managing Logs
Delete Single Entry:
- Click "Delete" button on any row
- Confirm the action
- Entry removed immediately
Clear All Logs:
- Click "Clear All Logs" button
- Confirm the action
- All logs permanently deleted
Export Logs:
- Click "Export CSV" button
- Download CSV file with all log data
- File named:
login-attempts-YYYY-MM-DD.csv
Configuration
Go to Settings → Login Monitor:
Log Types
- Log successful login attempts: Track successful logins
- Log failed login attempts: Track failed attempts
Log Retention
- Days: 1-365 (default: 30)
- Description: Logs older than this are auto-deleted daily
- Example: Set to 30 to keep only last month's data
Maximum Logs
- Count: Minimum 100 (default: 1000)
- Description: Maximum number of logs stored
- Behavior: Oldest logs deleted when limit reached
Browser Info
- Track Browser Info: Record user agent strings
- Shows: Browser name (Chrome, Firefox, Safari, etc.)
- Privacy: Optional if concerned about data collection
Settings Reference
Log Types
Log Successful Login Attempts
- Default: Enabled
- Purpose: Track all successful authentications
- Use Case: Audit trail, user activity monitoring
Log Failed Login Attempts
- Default: Enabled
- Purpose: Monitor potential security threats
- Use Case: Brute force detection, security alerts
Retention Days
Range: 1-365 days Default: 30 days Cleanup: Automatic daily via wp-cron
Recommendations:
- 7 days: Minimal storage, quick troubleshooting only
- 30 days: Good balance for most sites
- 90 days: Compliance requirements
- 365 days: Full year audit trail
Maximum Logs
Minimum: 100 Default: 1000 Purpose: Prevent database bloat
Calculation:
- Average log size: ~200 bytes
- 1000 logs ≈ 200 KB
- 10000 logs ≈ 2 MB
Recommendations:
- Small sites (< 10 users): 500-1000
- Medium sites (10-100 users): 1000-5000
- Large sites (100+ users): 5000-10000
Track Browser Info
Default: Enabled Data Collected: User agent string Privacy: Contains browser and OS info (no personal data)
Database Structure
Table Name
wp_login_attempts
(with prefix)
Schema
CREATE TABLE wp_login_attempts (
id bigint(20) NOT NULL AUTO_INCREMENT,
user_login varchar(60) NOT NULL,
user_id bigint(20) DEFAULT NULL,
ip_address varchar(100) NOT NULL,
user_agent text DEFAULT NULL,
status varchar(20) NOT NULL,
timestamp datetime NOT NULL,
PRIMARY KEY (id),
KEY user_login (user_login),
KEY ip_address (ip_address),
KEY status (status),
KEY timestamp (timestamp)
);
Indexes
Optimized for common queries:
- user_login: Search by username
- ip_address: Search by IP
- status: Filter by success/failed
- timestamp: Sort by date, cleanup old logs
WordPress Hooks
Actions
Login Monitoring:
wp_login
: Logs successful logins (priority 10)wp_login_failed
: Logs failed attempts
Admin:
plugins_loaded
: Load text domainadmin_menu
: Add admin pagesadmin_init
: Register settingsadmin_enqueue_scripts
: Load CSS/JS
Scheduled:
yt_lam_daily_cleanup
: Daily log cleanup (wp-cron)
Filters
plugin_action_links_{basename}
: Add "View Logs" and "Settings" links
AJAX Endpoints
yt_lam_delete_log
: Delete single log entryyt_lam_clear_logs
: Delete all logsyt_lam_export_logs
: Export CSV file
Log Data Captured
For All Attempts
- Username: Login attempted (sanitized)
- IP Address: User's IP (supports proxies)
- Timestamp: Date and time (MySQL format)
- Status: success or failed
- User Agent: Browser info (if enabled)
For Successful Logins
- User ID: WordPress user ID
- Link: Direct link to user profile
For Failed Logins
- User ID: NULL (user doesn't exist or wrong password)
- Username: Attempted username (may not exist)
IP Address Detection
The plugin detects IP addresses from multiple sources (in order):
HTTP_CF_CONNECTING_IP
(Cloudflare)HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR
(Proxy)HTTP_X_FORWARDED
HTTP_X_CLUSTER_CLIENT_IP
HTTP_FORWARDED_FOR
HTTP_FORWARDED
REMOTE_ADDR
(Direct)
Fallback: 0.0.0.0
if detection fails
Browser Detection
Simple browser parsing from user agent:
- Chrome: "Chrome" in user agent
- Firefox: "Firefox" in user agent
- Safari: "Safari" in user agent
- Edge: "Edge" in user agent
- Opera: "Opera" in user agent
- Unknown: Anything else
CSV Export Format
Filename: login-attempts-YYYY-MM-DD.csv
Columns:
- ID
- Username
- User ID
- IP Address
- Status
- Browser
- Timestamp
Encoding: UTF-8 Delimiter: Comma Headers: Yes (first row)
Admin Interface
Statistics Boxes
- Total Attempts: All-time count (blue)
- Successful: Success count (green)
- Failed: Failed count (red)
- Today: Today's count (yellow)
Filters & Actions Bar
Left Side:
- Status filter dropdown
- Search input (username/IP)
- Filter button
Right Side:
- Refresh button
- Export CSV button
- Clear All Logs button
Log Table Columns
- Time: Relative time + full timestamp
- Username: Username + link to user (if exists)
- IP Address: Clickable for lookup
- Status: Color-coded badge
- Browser: Parsed browser name
- Actions: Delete button
Pagination
- 20 logs per page
- Next/Previous navigation
- Page numbers
- Accessible URLs (bookmarkable)
Keyboard Shortcuts
- Ctrl/Cmd + R: Refresh page
- Ctrl/Cmd + E: Export CSV
- Tab: Navigate through interface
Performance
Database Impact
Per Login:
- 1 INSERT query (~1ms)
- Index maintained automatically
- No SELECT queries (unless viewing logs)
Viewing Logs:
- 1 COUNT query (for pagination)
- 1 SELECT query (for log entries)
- Both queries use indexes
Optimization Features
- Indexed Columns: Fast searches and filters
- Auto Cleanup: Prevents unlimited growth
- Max Logs Limit: Hard cap on table size
- AJAX Operations: No full page reloads
- Paginated Display: Only load 20 rows at a time
Benchmarks
- 1000 logs: <100 KB database space
- 10000 logs: <1 MB database space
- Log insertion: <1ms per entry
- Log retrieval: <50ms for 20 entries
- CSV export: ~1 second for 10000 logs
Security Features
Data Security
- Nonce Verification: All AJAX requests
- Capability Checks:
manage_options
required - Input Sanitization:
sanitize_user()
for usernamessanitize_text_field()
for general inputabsint()
for IDsfilter_var()
for IP validation
- Output Escaping:
esc_html()
for textesc_attr()
for attributesesc_url()
for URLs
- SQL Injection Prevention: Prepared statements only
- XSS Prevention: All output escaped
Privacy Considerations
Data Collected:
- Usernames (public information)
- IP addresses (potentially personal)
- User agents (device/browser info)
- Timestamps
GDPR Compliance:
- IP addresses are personal data
- User agents may contain identifying info
- Consider adding to privacy policy
- Respect retention limits
- Provide data export (CSV)
Best Practices:
- Set reasonable retention period (30-90 days)
- Document in privacy policy
- Don't share data with third parties
- Disable browser tracking if not needed
Use Cases
Security Monitoring
Scenario: Detect brute force attacks How: Monitor failed attempts from same IP Action: Review logs daily, block suspicious IPs
User Activity Audit
Scenario: Track employee logins How: Filter by specific usernames Action: Generate weekly reports via CSV export
Compliance Requirements
Scenario: Maintain 90-day audit trail How: Set retention to 90 days Action: Export logs monthly for archival
Troubleshooting Access Issues
Scenario: User can't login How: Search for username in logs Action: Check for failed attempts, identify issue
Site Migration Verification
Scenario: Verify all admins can access new site How: Review successful logins post-migration Action: Confirm all users logged in successfully
Frequently Asked Questions
How long are logs kept?
Logs are kept based on your retention setting (default: 30 days). You can change this in Settings → Login Monitor.
Can I prevent the database from growing too large?
Yes, set a maximum log limit (default: 1000). When the limit is reached, oldest logs are automatically deleted.
Does this slow down my site?
No. The plugin only runs during login attempts and when viewing the admin page. Normal page loads are not affected.
Can I see which country users are from?
The plugin records IP addresses. Click an IP to look it up on an external service that provides geolocation.
Is this GDPR compliant?
The plugin can be GDPR compliant if configured properly:
- Set reasonable retention period
- Document in privacy policy
- Provide data export option (CSV)
- Consider disabling user agent tracking
Can I track custom post type logins?
This plugin tracks WordPress user logins only. It doesn't track custom authentication systems.
What if someone changes their IP?
Each login attempt is logged separately with its IP at that time. Users with dynamic IPs will show different IPs for different logins.
Can I block IPs with failed attempts?
This plugin logs attempts but doesn't block IPs. Consider using a security plugin like Wordfence for IP blocking.
Does it work with two-factor authentication?
Yes, it logs attempts before 2FA. If 2FA fails, the attempt is logged as successful (password was correct).
Can I customize the CSV export?
Not currently, but you can modify the ajax_export_logs()
method to add/remove columns.
Troubleshooting
Logs not recording
- Check Settings → Login Monitor
- Ensure "Log successful" and "Log failed" are checked
- Test a login (correct and wrong password)
- Check Users → Login Log
Database table not created
- Deactivate and reactivate the plugin
- Check file permissions on plugin folder
- Verify database user has CREATE TABLE permission
- Check WordPress debug log for errors
CSV export not working
- Check browser popup blocker
- Verify you have
manage_options
capability - Check PHP memory limit (increase if needed)
- Try exporting smaller date range
Old logs not cleaning up
- Verify wp-cron is working:
wp cron event list
- Check retention days setting
- Manually trigger:
wp cron event run yt_lam_daily_cleanup
- Check WordPress debug log for errors
Statistics not accurate
- Statistics are real-time from database
- Clear all logs and test fresh
- Check for database corruption:
REPAIR TABLE wp_login_attempts
- Review retention and max log settings
Uninstallation
When you delete the plugin through WordPress:
- Database table dropped:
wp_login_attempts
removed - Options deleted: All plugin settings removed
- Scheduled events: wp-cron cleanup job removed
- Cache cleared: WordPress cache flushed
- No data remains: Complete cleanup
Note: Deactivation keeps data. Only deletion removes everything.
Changelog
1.0.0 (2025-01-XX)
- Initial release
- Login attempt logging (success and failed)
- Custom database table with indexes
- Admin interface with statistics
- Advanced filtering and search
- CSV export functionality
- Clear all logs feature
- Auto cleanup based on retention
- Maximum log limit enforcement
- IP address detection
- Browser detection
- Settings page
- AJAX operations
- Responsive design
- Keyboard shortcuts
- Translation ready
Developer Notes
Line Count
- PHP: 988 lines
- CSS: ~370 lines
- JS: ~430 lines
- Total: ~1,788 lines
Extending the Plugin
Custom Log Processing
add_action('yt_lam_after_log', function($log_data) {
// Send email alert for failed logins
if ($log_data['status'] === 'failed') {
wp_mail(
get_option('admin_email'),
'Failed Login Attempt',
'IP: ' . $log_data['ip_address']
);
}
}, 10, 1);
Custom Cleanup Logic
add_action('yt_lam_before_cleanup', function() {
// Custom pre-cleanup tasks
error_log('Cleaning up old login logs');
});
Modify Retention Period
add_filter('yt_lam_retention_days', function($days) {
return 60; // Override to 60 days
});
Database Queries
All queries use prepared statements:
// Safe query example
$wpdb->prepare(
"SELECT * FROM {$table_name} WHERE user_login = %s AND ip_address = %s",
$username,
$ip_address
);
Contributing
Follow WordPress Coding Standards:
phpcs --standard=WordPress yt-login-attempt-monitor.php
Support
For issues, questions, or feature requests:
License
GPL v2 or later
Author
Krasen Slavov
- Website: https://krasenslavov.com
- GitHub: @krasenslavov
Monitor your WordPress login activity with confidence!