Prevent account sharing on WordPress by capping how many places a user can be logged in at once.
Loggedin enforces a per-account session limit across every device a user signs in from. When the limit is hit, you choose what happens next — block the new login, or kick the oldest session out so the new device can take its place.
- Concurrent-session cap — set a global maximum number of simultaneous logins per account.
- Two enforcement modes — block the new login, or auto-logout the oldest active session.
- Force-logout tool — terminate every active session for any user from the admin UI.
- Modern settings UI — built with
@wordpress/componentsand Gutenberg patterns, not a hand-rolled options page. - REST-backed — all settings flow through the WordPress REST API.
- Extensible — addons hook into the settings UI via the
loggedin.settings.panelsJS filter and into the bootstrap via theloggedin_initaction. - Privacy-respecting — no third-party calls beyond Freemius for licensed addons.
| Addon | Description |
|---|---|
| Active Sessions | Browse every user with a live session, drill into each device, and sign out one session — or all of them — in one click. |
| Limit Per User | Override the global cap for individual users. |
| Limit Per Role | Set custom caps per WordPress role; highest applicable wins. |
| Real-time Logout | Detect background-terminated sessions and log the user out immediately. |
- PHP 7.4+
- WordPress 6.0+
From WordPress.org
- Plugins → Add New → search "Loggedin".
- Install and activate.
- Configure under Settings → Loggedin.
From source
git clone https://github.com/joel-james/loggedin.git
cd loggedin
composer install --no-dev
npm install && npm run buildThen symlink or copy the directory into wp-content/plugins/ and activate.
composer install # PHP dependencies (incl. dev tools)
npm install # JS dependencies
npm run start # JS watch build
npm run build # production JS build
composer test # PHPUnit
composer run phpcs # WPCS lintPHP code follows WordPress Coding Standards (see phpcs.xml.dist). JS uses @wordpress/scripts defaults.
Addons register themselves via two hooks wired at file load:
// Register with the parent's Freemius-addons map.
add_filter( 'loggedin_register_addon', [ Plugin::class, 'register_addon' ] );
// Boot once the parent's modules are ready.
add_action( 'loggedin_init', [ Plugin::class, 'boot' ] );Addons can contribute a panel to the Settings tab from JS:
import { addFilter } from '@wordpress/hooks';
addFilter(
'loggedin.settings.panels',
'my-addon/panel',
( panels ) => [ ...panels, { id: 'my-addon', Component: MyPanel } ]
);Pull requests welcome. Please read contributing.md and run composer test + composer run phpcs before opening a PR.
If you discover a security issue, please follow the disclosure process in security.md rather than opening a public issue.