“Who Is Online” Widget With PHP, MySQL & jQuery

"Who Is Online" Widget With PHP, MySQL & jQuery

For this week’s tutorial, we are taking a look at our ever-so-interesting inbox. It all started with a letter from one of our readers a couple of weeks ago:

My boss is always coming into my office asking me to install things on our client’s sites. One of the items that’s been coming up more and more is “How can we tell who’s currently online?” So, the next time you need a tutorial idea, there you go – a php/mysql/jquery ‘online users’ widget. Oh, and a geomap of each visitor would be super rad too.

Thanks for everything you guys do,
Taylor

Taylor, we are always happy when we receive good tutorial ideas, so today we are doing just that – a “Who is online” widget with PHP, MySQL & jQuery. It will display the number of visitors, currently viewing your site, and thanks to Hostip’s free IP to location API, it will even be able to detect the country your visitors are from and display it in a slide out panel.

Step 1 – XHTML

As usual, we start off with the XHTML part. The code presented here might not look like much, but it is all that we need to show off all the work that has been done by the backend. The widget features a slick slide-out panel with all the geolocation data, shown on mouse over.

demo.html

<div class="onlineWidget">

<div class="panel">

	<!-- Fetched with AJAX: -->

	<div class="geoRow">
	<div class="flag"><img src="who-is-online/img/famfamfam-countryflags/us.gif" width="16" height="11"></div>
	<div class="country" title="UNITED STATES">UNITED STATES</div>
	<div class="people">2</div>
	</div>

	<div class="geoRow">
	<div class="flag"><img src="who-is-online/img/famfamfam-countryflags/uk.gif" width="16" height="11"></div>
	<div class="country" title="UNITED KINGDOM">UNITED KINGDOM</div>
	<div class="people">1</div>
	</div>

</div>

<div class="count">8</div>
<div class="label">online</div>
<div class="arrow"></div>
</div>

As you may see from the markup above, the main container div – “onlineWidget” contains the slide-out panel (the div with class name “panel“), the total number of people online (the “count” div), the “online” label and the green arrow to the right.

Geolocation-enabled Who Is Online Widget

Geolocation-enabled Who Is Online Widget

The panel div is dynamically filled by AJAX with the countries with the most visitors currently online. The default content of this div is a rotating gif preloader, which is replaced with the geo data once the AJAX request is complete (usually in less than a second). We will come back to this in a moment.

Step 2 – The Database

Unlike the usual routine, here we are going to take a look at how the database is structured, as it is fundamental to the rest of the script.

All of the widget data is stored into the tz_who_is_online table. It consists of six fields (or columns). The first one – ID, is a standard primary key / auto increment field. After this is the IP field which stores the visitor’s IP address (converted to a integer beforehand with the ip2long PHP function).

After this are three fields fetched by Hostip’s API – Country, CountryCode and City. The widget is not using the city field at this point, but it is good to have in case somebody wants to implement it. Last is the DT timestamp field, which is updated on every page load and enables us to track who is online (users without a page load in the last 10 minutes have probably left the site).

Table Structure Of tz_who_is_online

Table Structure Of tz_who_is_online

Step 3 – CSS

The widget is (almost) image free, and is only styled with CSS. Lets take a look at the styling, as defined in styles.css. The code is divided in two parts, so it is easier to follow.

who-is-online/styles.css – Part 1

.onlineWidget,.panel{

	/* Styling the widget and the sliding panel at once */

	background-color:#F9F9F9;
	border:2px solid #FFFFFF;
	height:25px;
	padding:4px 8px;
	position:relative;
	width:130px;

	cursor:pointer;

	/* CSS3 rules for rounded corners, box and text shadows: */

	-moz-border-radius:6px;
	-webkit-border-radius:6px;
	border-radius:6px;

	-moz-box-shadow:0 0 3px #CCCCCC;
	-webkit-box-shadow:0 0 3px #CCCCCC;
	box-shadow:0 0 3px #CCCCCC;

	text-shadow:0 2px 0 white;
}

.onlineWidget:hover{
	background-color:#fcfcfc;
}

.onlineWidget:hover .arrow{
	/* Changing the background image for the green arrow on hover: */
	background-position:bottom center;
}

.count{
	/* The total number of people online div */

	color:#777777;
	float:left;
	font-size:26px;
	font-weight:bold;
	margin-top:-3px;
	text-align:center;
	width:30px;
}

.label{
	/* The online label */

	float:left;
	font-size:10px;
	padding:7px 0 0 7px;
	text-transform:uppercase;
}

In the first step above, you can see that we style the widget and the slide-out panel at once. This is to ensure that they have consistent styling which is easy to change later on. Some rules are unique to the panel, however, so we include a individually targeted set of rules in the second part of the code.

We also define the hover state and style the label and count divs.

who-is-online/styles.css – Part 2

.arrow{
	/* The green arrow on the right */

	background:url(img/arrow.png) no-repeat top center;
	position:absolute;
	right:6px;

	width:25px;
	height:25px;
}

.panel{
	/* The slideout panel */

	position:absolute;
	cursor:default;

	bottom:50px;
	left:0;
	height:auto;
	display:none;
	margin:-2px;
	z-index:1000;
}

.preloader{
	/* The rotating gif preloader image */
	display:block;
	margin:10px auto;
}

.geoRow{
	/* The div that contains each country */

	height:16px;
	overflow:hidden;
	padding:2px 0;
}

.flag{
	float:left;
	margin:0 4px;
}

.country, .people{
	float:left;
	font-size:10px;
	padding:2px;
}

.country{
	width:85px;
	overflow:hidden;
}

.people{
	font-weight:bold;
}

In the second part of the file, we style the how the geolocation data that is presented in the slide-out panel, after jQuery fetches it from the back-end. With this we can continue with the next step.

CSS3 & jQuery Front End

CSS3 & jQuery Front End

Step 4 – PHP

This is where the magic happens. PHP has to keep the database of online users up to date and fetch IP-to-location data from Hostip’s API. This is later cached for future use in a cookie on the visitors PC.

who-is-online/online.php

require "connect.php";
require "functions.php";

// We don't want web bots altering our stats:
if(is_bot()) die();

$stringIp = $_SERVER['REMOTE_ADDR'];
$intIp = ip2long($stringIp);

// Checking wheter the visitor is already marked as being online:
$inDB = mysql_query("SELECT 1 FROM tz_who_is_online WHERE ip=".$intIp);

if(!mysql_num_rows($inDB))
{
	// This user is not in the database, so we must fetch
	// the geoip data and insert it into the online table:

	if($_COOKIE['geoData'])
	{
		// A "geoData" cookie has been previously set by the script, so we will use it

		// Always escape any user input, including cookies:
		list($city,$countryName,$countryAbbrev) = explode('|',mysql_real_escape_string(strip_tags($_COOKIE['geoData'])));
	}
	else
	{
		// Making an API call to Hostip:

		$xml = file_get_contents('http://api.hostip.info/?ip='.$stringIp);

		$city = get_tag('gml:name',$xml);
		$city = $city[1];

		$countryName = get_tag('countryName',$xml);
		$countryName = $countryName[0];

		$countryAbbrev = get_tag('countryAbbrev',$xml);
		$countryAbbrev = $countryAbbrev[0];

		// Setting a cookie with the data, which is set to expire in a month:
		setcookie('geoData',$city.'|'.$countryName.'|'.$countryAbbrev, time()+60*60*24*30,'/');
	}

	$countryName = str_replace('(Unknown Country?)','UNKNOWN',$countryName);

	mysql_query("	INSERT INTO tz_who_is_online (ip,city,country,countrycode)
					VALUES(".$intIp.",'".$city."','".$countryName."', '".$countryAbbrev."')");
}
else
{
	// If the visitor is already online, just update the dt value of the row:
	mysql_query("UPDATE tz_who_is_online SET dt=NOW() WHERE ip=".$intIp);
}

// Removing entries not updated in the last 10 minutes:
mysql_query("DELETE FROM tz_who_is_online WHERE dt<SUBTIME(NOW(),'0 0:10:0')");

// Counting all the online visitors:
list($totalOnline) = mysql_fetch_array(mysql_query("SELECT COUNT(*) FROM tz_who_is_online"));

// Outputting the number as plain text:
echo $totalOnline;

This PHP script is initially called by jQuery in order to populate the count div with the current number of people online. Behind the scenes, however, this script writes the visitor’s IP to the database and resolves their IP-to-location data.

This is the best strategy in organizing the back-end, as we keep the calls to the API (which are quite time expensive) distributed to each user as they visit the site for the first time.

The other alternative would be to store only the IPs of the visitors and queue the geolocation data once the panel is shown. This would mean to resolve a huge number of IPs simultaneously, which would make the script unresponsive and get us black-listed from the API. Totally not cool.

You can queue the Hostip’s API by opening a connection to a URL similar to this: http://api.hostip.info/?ip=128.128.128.128. It returns a valid XML response, which contains all sorts of data, including a country and city name associated with the IP, country abbreviation and even absolute coordinates. We are fetching this data with the PHP file_get_contents() function and extracting the bits of information we need.

who-is-online/geodata.php

require "connect.php";
require "functions.php";

// We don't want web bots accessing this page:
if(is_bot()) die();

// Selecting the top 15 countries with the most visitors:
$result = mysql_query("	SELECT countryCode,country, COUNT(*) AS total
						FROM tz_who_is_online
						GROUP BY countryCode
						ORDER BY total DESC
						LIMIT 15");

while($row=mysql_fetch_assoc($result))
{
	echo '
	<div class="geoRow">
		<div class="flag"><img src="who-is-online/img/famfamfam-countryflags/'.strtolower($row['countryCode']).'.gif" width="16" height="11" /></div>
		<div class="country" title="'.htmlspecialchars($row['country']).'">'.$row['country'].'</div>
		<div class="people">'.$row['total'].'</div>
	</div>
	';
}

Geodata.php is fetched by jQuery to populate the slide-out panel with location data. This file basically queues the database with a GROUP BY query, which groups the individual users by country and orders the resulting rows in a descending order, with the most popular countries at the top.

For the flag icons, we are using the famfamfam flag icon set, which is released as public domain. A great thing about the Hostip API, is that it returns the country code in a standard two letter format, which is also shared by the famfamfam icon set. This means that in the while loop, it is really easy to find the appropriate flag to show, by just lowering the case of the country abbreviation stored in the database and adding a gif extension.

Step 5 – jQuery

JavaScript manages the AJAX requests and slides the panel. This would be a daunting task with pure JS alone, which is why we are using the newest version of the jQuery library.

Now lets take a look at what the code looks like.

who-is-online/widget.js

$(document).ready(function(){
	// This function is executed once the document is loaded

	// Caching the jQuery selectors:
	var count = $('.onlineWidget .count');
	var panel = $('.onlineWidget .panel');
	var timeout;

	// Loading the number of users online into the count div with the load AJAX method:
	count.load('who-is-online/online.php');

	$('.onlineWidget').hover(
		function(){
			// Setting a custom 'open' event on the sliding panel:

			clearTimeout(timeout);
			timeout = setTimeout(function(){panel.trigger('open');},500);
		},
		function(){
			// Custom 'close' event:

			clearTimeout(timeout);
			timeout = setTimeout(function(){panel.trigger('close');},500);
		}
	);

	var loaded=false;	// A flag which prevents multiple AJAX calls to geodata.php;

	// Binding functions to custom events:

	panel.bind('open',function(){
		panel.slideDown(function(){
			if(!loaded)
			{
				// Loading the countries and the flags
				// once the sliding panel is shown:

				panel.load('who-is-online/geodata.php');
				loaded=true;
			}
		});
	}).bind('close',function(){
		panel.slideUp();
	});

});

You might be a bit perplexed with the use of setTimeout in the menu. This is done, so we have a bit of delay between the hovering of the mouse and the actual opening of the slide-out panel. This way, unintentional movements of the mouse cursor over the widget won’t fire the open event, and once opened, will not close it immediately once the mouse leaves it.

With this our widget is ready!

Setting up the demo

At this point you probably want to grab the widget and put it on your site. To make it work, you need to execute the SQL code found in table.sql in the download archive. It will create the tz_who_is_online table in your database, which is used by the widget. Later you need to upload the files to your server and include widget.js to the head section of your page (along with the jQuery library). After this you have to fill your MySQL login details in connect.php and finally add the markup from demo.html to your web page.

Conclusion

Having access to real time data on your site userbase is a dream to any webmaster. Tools like Google Analytics give a great perspective on your site’s reach, but lack the real time feel a simple widget like this can provide.

What do you think? How would you modify this code?

Presenting Bootstrap Studio

a revolutionary tool that developers and designers use to create
beautiful interfaces using the Bootstrap Framework.

Learn more
Web Browser Frame DevKit Box Mouse Cursor
by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and it still is his favorite side project.

1Share this post
2Read one more article
3Get your free book
Book Cover
jQuery Trickshots

Tutorialzine's advanced jQuery techniques book.

Download

80 Comments

  1. Dennis says:

    Holy moly!

    Haven't studied the code completely, but I would suggest an auto-refresh with jQuery (only the div).

    Cheers,

    Dennis

  2. Aztekk says:

    WoW !

    I think this is the best site for learning php, you should make a php series tutorials for beginners =)

    Peace from Holland

  3. Eric Grint says:

    Really Great Tutorial.. :)

  4. Taylor Hunt says:

    Well written. The .js has more bindings than Shaun White's snowboard garage. Grabbing the code and going to work as we speak. Rock solid. Martin, you have a free beer (or 12) here in Wichita, Ks anytime.

  5. arnold says:

    very usable... your tutorial is cool..
    idk you make jquery more amazing...thanks

  6. Al says:

    Very nice and useful! Thanks for the Tut! :D

  7. Al says:

    Is there any way to change the direction it slides? Like for example I want it come slide out to the left if I am keeping it in my sidebar.

  8. Hoxxy says:

    Great little script as usual :)

  9. Rilwis says:

    This is an awesome article. I like this so much. Thank you.

  10. Chris Horton says:

    Hi, first time I've been on your site. Really well written tutorial and could come in handy for some clients sites. I'll be subscribing to your RSS.

    Chris

  11. apex says:

    Hey it's not working!!! I didn't change anything in the code, but the data is not written to database. IP is inserted but nothing else?

  12. Martin Angelov says:

    Thank you for the great comments!

    @ apex
    Seems your server cannot communicate with the Hostip API. In the demonstration I've used the file_get_contents() PHP function for fetching the Hostip URL.
    It is possible that your host disabled file_get_contents from fetching remote URL's. To test if this is the case, create a new php file and put this code inside it:

    <?php

    echo file_get_contents('http://www.google.com');

    ?>

    You should get the contents of the Google homepage printed out. Write here how this goes.

    @ Al
    Yes, you could make it slide out to the left. However you'll have to replace most of the CSS and add jQuery UI to the page, as jQuery does not provide a function for sliding out content this way .

  13. apex says:

    I have found the problem. It's not in your script it's working perfectly now. I have replaced "file_get_contents" with "curl", it seems that "file_get_contents" is somehow disabled on my server, I don't know why?

    Thanks again for this nice script and for interest in helping me!

  14. Florin M says:

    Can you please share the psd for the "who is online" logo from the preview ? Thank you!

  15. Zero says:

    Not working!!

    Warning: mysql_num_rows() expects parameter 1 to be resource

  16. Martin Angelov says:

    @ apex
    Glad that the problem is solved!

    @ Florin M
    I usually don't share these, but you can download it from here.

    @ Zero
    You have probably filled wrong MySQL login details and the script is failing to connect to the server.

  17. Zero says:

    @ Martin Angelov

    No, my conecction is good and the table is ok, but this line in the code generates the error:

    if(!mysql_num_rows($inDB))

    but the query
    $inDB = mysql_query("SELECT 1 FROM tz_who_is_online WHERE ip=".$intIp);
    returns 0 rows, because is the first time i run the page.

    maybe some configuration is wrong

  18. apex says:

    @zero
    try with SELECT *
    ----------------------------------------------

    you should add
    if ($countryName == "") { $countryName='UNKNOWN';$countryAbbrev='XX';$city='(Unknown City?)'; }

    before inserting data to database, check your database, sometimes it get's filled with empty rows

  19. Florin M says:

    Thank you , your posts are the best i ever seen! And thank you for the psd!

  20. Áki says:

    thanks for this great tutorial

  21. Jutix says:

    Nice!!!

    I like this widget!! Thank you :)

  22. Borce M. says:

    Useful, but something I won't use on my blog.

  23. SMH says:

    One flaw in this processing is that people who go "offline"(not active after 10 minutes) are not updated in the database until someone else comes online. This would result in potentially inflated online numbers.

  24. Kurt Milam says:

    @Angelo, re:
    Yes, you could make it slide out to the left. However you’ll have to replace most of the CSS and add jQuery UI to the page, as jQuery does not provide a function for sliding out content this way.

    You can do this with straight jQuery no jQuery UI required. Just use the standard animate() function in jQuery to make the div slide to the right or left.

    Nice tutorial!

  25. Michael Pehl says:

    Very cool stuff! Nice tut, thanks for sharing this beauty.

  26. says:

    Hey Martin !

    F*cking great article as usual !
    So complete & well explained, THE top of the cream out there...

    Love your tuts man. Keep up the good work !

  27. Keerthi Teja says:

    Hello Martin.... :)
    As usual Great Tut...
    I have a doubt....
    I want to use this script in multiple sites....
    Means i want to install this script in one site and i want to run this in my other websites...
    How to do that...?

    I think u understood my question...
    Thanx in Advance... :)

    1. yosef says:

      u can use iframe code put in it the link to the master page that u put the online code in it.

      <iframe src="#"></iframe>

  28. really nice and small widget to use in project, best combination of PHP,Mysql and jquery in love i am.

  29. Martin Angelov says:

    Thank you for the great comments!

    @Keerthi Teja - the script is organized in a way that it is only suitable for use in a single site. You could modify it to work with more than one site (by adding one more field to the database and reorganizing the code), but I would suggest to use it as is and implement it for each site individually.

  30. Denis says:

    Hello !
    thanks for putting together this nice tutorial.

    I was wondering if it's possible to have the results displaying on one page only while recording data from other pages. Let me put it in my website's context :

    I have 4 index pages with pull-down menus (one per language) that loads the page contents into an iframe underneath. So will it work if I place code that records visitor into each of the 4 index pages, and the code that display the result in the "stats" page (see left handside box : icon with vertical bars). In addition, I also have a store section based on zencart where I want to record but not display the number of visitors.

    To record the visitors online, only the two line pointing to the js files are needed, right ? or the section div class="onlineWidget" as well ?

    I hope I explained clearly. Thanks in advance for your answer.
    Best regards

    Denis

  31. Thank you so much, this is awesome!

  32. Martin Angelov says:

    @ Denis

    Currently the widget in the demo shows all of Tutorialzine's online visitors, despite the demo running on a different subdomain than the main site. To make this work, you need to include an image on the page you want to be tracked, which points to online.php.

    You can do it either with a regular image tag somewhere in the markup of the page:

    <img src="http://domain.com/somepath/who-is-online/online.php" width="1" height="1" />

    Or with JavaScript:

    <script type="text/javascript">
    (new Image()).src="http://domain.com/somepath/who-is-online/online.php";
    </script>

    You can show the online widget in an entirely different page (or even an admin area) not accessible by regular visitors.

  33. Denis says:

    Hey Martin,

    thanks for the explanation : I have done as you said and it works like a charm. Widget is up and running on my stats page. Brilliant, thanks a million !!

    Denis

  34. Michael Pehl says:

    I always see "Unknown". When checking with hostip.info it recognizes my ip correctly, but on my site http://1click.at it always shows "Unknown".

    Any tipps on that?

  35. Michael Pehl says:

    Sorted it out, thanks.

  36. ikreknin says:

    1st problem:

    Hostip API returnes, for example, for 217.169.39.0:
    UK

    So, after strtolower($row['countryCode']).'.gif
    we get 'uk.gif'

    But famfamfam doesn't have this UK flag, it has 'gb.gif'.

    So, I see these 2 systems -- Hostip API & famfamfam -- are not compatible.

    2nd issue:

    `ip` int(10) NOT NULL default '0',

    I think int(10) is too small for ip2long, so MySQL saves an incorrect value for the same 217.169.39.0.

    I made it larger as varchar, after that it works correctly with this IP.

    3rd (system) issue: Hostip API is very... narrow. For example, it doesn't know my IP (EU country, capital):

    > Location: ... actually we haven't a clue.

    A very interesting architecture of the solution, but the Hostip API service is very weak. As a result, the countries are mainly 'UNKNOWN'.

  37. Martin Angelov says:

    @ikreknin

    1) Both the hostip API and the famfamfam iconset follow the same standard. The difference comes from the fact that there has been a change with the standard for the GB/UK code you mention. By simply renaming the flag (or using the icon pack that is supplied with the demo) you should be OK.

    2) As we are using a signed value for the IP address (positive and negative numbers), INT(10) is sufficient. However you are free to change it to a varchar if you like, and drop the ip2long conversion entirely.

    3) Yes, hostip is community supported and it does have its pitfalls. However I hope that if it becomes more popular, the accuracy would increase. There are commercial alternatives, which provide a much higher level of accuracy, but again, they are not free. This widget is more for the average webmaster, who is curious about his community, and I think for the most part it gets the job done.

  38. ikreknin says:

    1) If I use this code:

    // $stringIp = $_SERVER['REMOTE_ADDR'];
    $stringIp = '94.30.152.100';
    $intIp = ip2long($stringIp);
    echo $intIp;

    & INT(10) in MySQL

    I see:
    1) 1579063396 in ECHO and
    2) 1579063396 in MySQL

    Ok.

    2) Now I replace

    $stringIp = '94.30.152.100';

    with

    $stringIp = '217.169.39.0';

    (one line only!)

    and I get:
    1) 3651741440 in ECHO and
    2) 2147483647 in MySQL

    3651741440 vs. 2147483647. No idea why.

    3) If change IP back:

    $stringIp = '94.30.152.100';

    I get 1579063396 and 1579063396.

    Ok again.

    So, I don't understand why MySQL saves 2147483647, not 3651741440.

    That is why I replaced INT(10) with VARCHAR.

    P.S. I'm not a programmer (a hobby).

  39. ikreknin says:

    I've just found.

    CREATE TABLE `tz_who_is_online` (
    ...
    `ip` int(10) NOT NULL default '0',

    in table.sql (demo files) should be

    CREATE TABLE `tz_who_is_online` (
    ...
    `wio_ip` int(10) unsigned NOT NULL default '0',

  40. ikreknin says:

    a correction: without the prefix 'wio_' -- I copied it from my table.

  41. Martin Angelov says:

    What operating system are you running PHP on? It seems that in your configuration ip2long returns an unsigned number (in PHP on Linux ip2long('217.169.39.0') echoes a signed negative number).

    This is probably the reason for the problems you are facing. Converting the ip field to INT(11) (or to a string) should indeed resolve your problems. I'm going to update table.sql with the new field, in case anybody else is having the same issues.

  42. ikreknin says:

    Linux, Apache 2, PHP 5.2.12

  43. ikreknin says:

    > [I]Converting the ip field to INT(11)[/I]

    I don't know why, but I see INT(11) or INT (12) doesn't solve the problem.
    IP is saved correctly only if INT(11) and INT (12) are unsigned.

  44. reddy says:

    Thanks a lot. I was trying to implement this but didn't know how to. SO, once again thnx a lot :)

  45. PackoRaban says:

    Hi Martin!
    Really a good script you are using.
    A simple question to you:
    How can I decorative items to the Info window comes down, instead it will be Up.

    Thank you for the answer

  46. PackoRaban says:

    Nevermind...i find it....
    in style.css change
    .panel{
    /* The slideout panel */

    position:absolute;
    cursor:default;

    top:50px;
    left:0;
    height:auto;
    display:none;
    margin:-2px;
    z-index:1000;
    }

  47. 1-TM says:

    Thanks Angelov

  48. dinle says:

    yeah.. really cool script.

    thanks

    Regards.

  49. weilik says:

    To Whom It May Concern,

    I am encountering the following problems when I run the demo.html. Can anyone tell me what is wrong with the script? I have posted here previously but it seems there isn't any response.

    Warning: mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource in /home/weilik/webapps/wp/who-is-online/geodata.php on line 16

    Warning: mysql_num_rows(): supplied argument is not a valid MySQL result resource in /home/weilik/webapps/wp/who-is-online/online.php on line 17

    Warning: Cannot modify header information - headers already sent by (output started at /home/weilik/webapps/wp/who-is-online/online.php:17) in /home/weilik/webapps/wp/who-is-online/online.php on line 45

    Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /home/weilik/webapps/wp/who-is-online/online.php on line 72

    Please help. Thank you.

    Regards,
    weilik

  50. Wow what a awesome script. Thanks so much. Got to try this one.

  51. cefer says:

    wooow...thanks so much!!!

  52. mp3 dinle says:

    really cool script.

    thanks

  53. Les says:

    Im lost here. Is there a way to grab this or just get html code to encorporate this into my blog?

  54. seks says:

    Hi Martin!
    Really a good script you are using.
    A simple question to you:
    How can I decorative items to the Info window comes down, instead it will be Up.

  55. Rafael Mussi says:

    I think you should add the timestamp on the first insert query:

    mysql_query("INSERT INTO tz_who_is_online (ip,city,country,countrycode,dt) VALUES (".$intIp.",'".$city."','".$countryName."', '".$countryAbbrev."', NOW())");

    Btw, nice script!

  56. Redsky says:

    Amazing tutorial, I'll use this widget on my sites.

    I found tutorialzine.com, just today and I love it!

  57. Mihai says:

    Cool script, but on a heavy traffic sit will kill your database server instantly!

  58. oyun oyna says:

    really cool script.

    thanks

  59. and this one is really good!
    I have 2 use it ;)

  60. Hasan says:

    No other words to explain about this tutorial... your company always rocks... am the great fan of your website.... keep it up....

  61. script indir says:

    really cool script.

    thanks

  62. Joseph says:

    That is really cool!

    thanks for the great tutorial :)

  63. Bolarinwa Olakunle says:

    This is a lovely Tut!. Thank You so much

  64. Jerome says:

    Thanks for sharing that widget, when I tried it on my xampp it worked perfectly but on my web server it didn't.

    So I came up with following fix, what is actually working on more configurations then with ip2long because of 32bit and 64bit system.

    You can let MySQL do the converting with INET_ATON():

    So what you have to change in online.php

    Find:
    $stringIp = $_SERVER['REMOTE_ADDR'];
    $intIp = ip2long($stringIp);

    Replace:
    $stringIp = $_SERVER['REMOTE_ADDR'];

    Find:
    1 FROM tz_who_is_online WHERE ip=".$intIp

    Replace
    1 FROM tz_who_is_online WHERE ip = INET_ATON(".$stringIp.")"

    Find:
    VALUES(".$intIp.",'".$city."',

    Replace:
    VALUES(INET_ATON(".$stringIp."),'".$city."',

    Find:
    dt=NOW() WHERE ip=".$intIp

    Replace:
    dt=NOW() WHERE ip = INET_ATON(".$stringIp.")"

    Again, thanks for sharing, I made a plugin for JAKCMS.

  65. This was an awesome tutorial! I really like how it works.

  66. Nic says:

    Getting 'UNKNOWN' for IP,etc., here I'm afraid. Searched for this script after seeing something similar elsewhere so would love to get it working. Tried the 'file_get_contents' test with Google and it worked, returning the Google page (text only, no images) so unsure what to test next.

    Many thanks in advance.

  67. alex says:

    I also make ip to unsigned Int that solve the problem.
    Thnks again

  68. Alpha says:

    Hey Martin,

    What is the function : get_tag() ?

    Nice demo buddy!

  69. amjad says:

    hi

    This is working fine but it is inserting uknown country into the databse and therefore not showing the when i put pointer over the widget. Any help please.

    Thanks

  70. Ruok2bu says:

    I'm having some problems with this script. It was working fine a few days ago, but after some recent database changes it doesnt work anymore. I have my database details entered correctly, but the slideout is blank and when i go directly to "who-is-online/online.php", the page is blank.

    Any idea what's happening?

  71. Ravindar Dev says:

    may be am asking too much but i really need a helping hand here.iam trying to put this plugin exactly at right center of the screen but i couldn't.

    a little help is appreciated...

  72. Coscho says:

    Very nice tutorial.

    Why is unique on IP??? What happen when there are more then one users on the same IP???

    you should insert command WHERE userid not WHERE IP...(in case you manage that after login script) ...

  73. ducsu says:

    Hi guys. I wish to use this script on a weebly site. I know weebly doesn't support php/db. I was thinking about setting this script up on a different host and somehow link it to weebly site. Is this possible, is so, can some one guide me on how I can write this up? Thanks.

  74. ducsu says:

    Is it possible to make the sliding panel to drop down instead of floating up? If so, can someone guide me on how to accomplish this? Thanks.

    1. ducsu says:

      I am also getting unknown for the ip address. I've seen a couple more posts like me but no answers. Anyone knows the reason why?

  75. Rezker says:

    Hey,
    Here is a solution to replace hover event by click event:

    function open (){panel.trigger('open');}
    function close(){panel.trigger('close');}
    	
    $('.onlineWidget').click(function(){
        var modal_id = $(this).attr('name');
    
        if(!$('.panel').is(":visible")){
            open();
        }
        else{
            close();
        }
    });
    
  76. Linces says:

    Yes, how i can "refresh" automatic the visitors div?

    Again, great tutor, you are the best. Thank you.

  77. Yes, I want to know how to make this script much faster (or the solution from Linces with refresh div or class)...I'm try use this script on my chat for the online users,but ts very slow and becomes a craziness :)
    I want users to be calculated every half minute,its possible ??

    Thanks Martin and keep up the good work.

    Tanas Alexandru Florin

  78. Sebastian says:

    Hello, first I wanted to congratulate the tutorial, the best on the subject I found :)

    I was already using it a few times but today we are in php7 and the standard mysql already no longer works in most applications, it would be nice to give you an updated using mysqli or else the PDO

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links