One way to troubleshoot is to add a couple of echos in each section in the if/else (for testing purposes). This will help you to see where the code is going.
if($sql_hits_rows == 1){
extract($sql_hits_fetch);
$stats_hits++;
echo "This is the PRE UPDATE section";
mysql_query("UPDATE stats SET stats_hits='$stats_hits' WHERE stats_date='$today'") or die(mysql_error());
echo "This is the POST UPDATE section";
} else {
echo "This is the PRE INSERT section";
mysql_query("INSERT INTO stats (stats_date, stats_hits) VALUES ('$today', '1')") or die(mysql_error());
echo "This is the POST INSERT section";
}
This will allow you to see a couple of things:
1) Which part of the if is it going to when the date is not found.
2) If it is breaking anywhere before the insert occurs.
You may also want at looking into [man]mysql_affected_rows[/man]. This will allow you to debug the code even more, and add a bit of error checking...
The code, as you have it, looks fine, so I have to wonder what kind of field is your stats_date field? (Of course, I am tired, so I may be missing something)
Lastly, the if/else has to go to one area or another, so if no insert is occurring, I wonder if the UPDATE portion is what's actually running instead... concatenate your query variables like so, and let's see how that works for you:
$sql_hits = mysql_query("SELECT * FROM stats WHERE stats_date='".$today."'") or die(mysql_error());