Вообще, нормальный способ, если есть веб сокеты, поднять вот это
https://github.com/centrifugal/centrifugo/А из своей практики, наиболее простое решение - периодически пинговать с клиента сервер и записывать для клиента время последнего пинга. И просто это время отдавать обратно на клиентов. Если отличие от текущего времени больше 5 минут - считаем за офлайн.
Минусы тоже есть - статус узнаётся не оперативно и на клиентах должно быть правильное время. Ну и ещё один не такой очевидный - криво оборвавшиеся коннекты будут впустую занимать ресурсы на сервере