Statistika přístupů v PHP – počet unikátních návštěvníků

13. prosince 2003

Tímto článkem začíná další série, v jejímž průběhu se postupně dozvíte, jak vytvořit rozsáhlou statistiku přístupů, která bude zjišťovat a vyhodnocovat mnoho důležitých údajů. Kromě klasických informací, jako je počet unikátních návštěvníků a IP adres, budeme zjišťovat i typy prohlížečů a operačních systémů, vyhledávací fráze, regionální polohu a podobně. Tentokrát si kromě nutného úvodu povíme, jak zjistit počet unikátních návštěvníků za den.

Hotovou aplikaci si jako obvykle můžete prohlédnout a vyzkoušet. V této ukázkové verzi se provádí statistika přístupů stránek http://www.czechia.cz/help/.

Popis a struktura

Hned na úvod se nabízí otázka: „Potřebují naše stránky vůbec nějakou statistiku přístupů?“ Odpověď je jasná – ano. Technické informace zahrnující statistiku prohlížečů, rozlišení a podobně, se mohou hodit tvůrcům stránek, kteří tak mají alespoň základní přehled o tom, jaké počítače a software používají jejich návštěvníci. Ostatní informace, jako je regionální lokalizace, nejvíce a nejméně prohlížené stránky, vyhledávací fráze a další, se dají využít například v oblasti marketingu, kde mohou pomoci při prodeji reklamy, nebo při dalším vývoji stránek, případně při jejich analýze z hlediska přístupnosti.

Nyní se trošku podrobněji zmíním o tom, co vše bude tato statistika přístupů zjišťovat a vyhodnocovat. Kromě zmíněného počtu unikátních návštěvníků a unikátních IP adres to bude samozřejmě i celkový počet shlédnutých stránek. Dále se bude určovat návštěvnost v hodinách (0 – 23) a dnech (Pondělí – Neděle) a podíl jednotlivých typů prohlížečů, operačních systémů, rozlišení obrazovky a barevné hloubky. Budeme zjišťovat, z jakých stránek návštěvníci přicházejí a jaké fráze používají ve vyhledávačích (Seznam, Google, Jyxo a další). Na základě doménové adresy budeme moci zjistit, jaké jsou nejčastější domény nejvyšší úrovně a v jakém kraji a městě se návštěvník nachází. Struktura celé aplikace však umožňuje přidat i další funkce, záleží tedy jen na vás.

Celá aplikace se skládá pouze z několika souborů – counter.php (počítá přístupy, zjišťuje údaje, zapisuje do databáze), stat.php (vyhodnocuje údaje uložené v databázi), db.php (zajišťuje připojení k databázi), config.php (jednoduchá konfigurace) a calendar.php (kalendář). Aplikace využívá databázi MySQL, kterou tvoří celkem třináct tabulek, což znázorňuje následující schéma:

Schéma použité databáze (náhled)
Schéma použité databáze (plná velikost, cca 40 kB)

Tabulka access

Ze schématu vyplývá, že nejdůležitější je tabulka access, kam se ukládá každý přístup na naše stránky. Tabulku access, která má celkem třináct položek, vytvoříme pomocí tohoto SQL příkazu:

CREATE TABLE access (
id int NOT NULL auto_increment,
access_date datetime NOT NULL,
visit int NOT NULL,
browser int NOT NULL,
os int NOT NULL,
resolution int NOT NULL,
colordepth int NOT NULL,
referer int NOT NULL,
path int NOT NULL,
area int NOT NULL,
ip varchar(25) NOT NULL,
ip_name varchar(60) NOT NULL,
domain int NOT NULL,
PRIMARY KEY (id)
)

  • id – unikátní označení každého přístupu (primární klíč)
  • access_date – datum a čas přístupu ve formátu RRRR-MM-DD HH:MM:SS
  • visit – jedná se o visit (unikátní návštěvník/den) nebo ne
  • browser – prohlížeč
  • os – operační systém
  • resolution – rozlišení obrazovky
  • colordepth – barevná hloubka
  • referer – stránka, ze které návštěvník přišel
  • path – stránka, kterou si návštěvník prohlédl
  • area – oblast (město, kraj, VŠ), ze které je návštěvník
  • ip – IP adresa počítače
  • ip_name – doménová adresa počítače
  • domain – doména nejvyšší úrovně

V položkách browser, os, resolution a dalších nebudeme uvádět konkrétní údaj, ale pouze označení daného údaje ze související tabulky, což dobře znázorňuje databázové schéma. O tom všem budou ale až další články.

Připojení k databázi

K databázi se připojíme pomocí souboru db.php:

$server_name = ‚localhost‘; // jmeno databazoveho serveru
$db_user = “; // uzivatel
$db_pass = “; // heslo
$db_name = ‚counter‘; // jmeno databaze
mysql_connect($server_name, $db_user, $db_pass) or die(‚Nepodařilo se připojit k MySQL databázi‘); // pripojeni k databazi
mysql_select_db($db_name) or die(‚Nepodařila se otevřít databáze.‘); // vyber databaze

Datum a unikátní návštěvník za den

V tomto článku vám ukáži využití prvních tří položek z tabulky access. Položka id obsahuje unikátní označení každého přístupu, což zajišťuje příkaz AUTO_INCREMENT, a je tedy primárním klíčem celé tabulky. Položka access_date obsahuje datum a čas přístupu ve formátu RRRR-MM-DD HH:MM:SS. Úvodní část souboru counter.php tedy vypadá takto:

// zabranime cashovani
header(‚Cache-Control: no-cache‘);
header(‚Pragma: no-cache‘);
header(‚Expires: ‚ . gmdate(‚D, d M Y H:i:s‘) . ‚ GMT‘);
// pocitadlo vkladame jako obrazek (mozno pouzit i jine formaty obrazku)
// dl(‚php_gd.dll‘);
header(‚Content-type: image/png‘);
// pripojeni k databazi, konfigurace
require ‚./config.php‘;
require ‚./db.php‘;
// DATUM
$date = date(‚Y-m-d H:i:s‘); // aktualni datum a cas

Třetí položka visit určuje, zda se jedná o visit nebo ne. Za visit přitom považujeme vstup návštěvníka na naše stránky, přičemž se nemusí nutně jednat o úvodní stránku. Každý návštěvník však může za den vytvořit pouze jeden visit. Vůbec tedy nezáleží na tom, jestli si prohlédne patnáct stránek nebo pouze tři. Sečteme-li všechny visits v určitý den, dostaneme počet unikátních návštěvníků za tento den.

Teoreticky to vypadá celkem jednoduše, ale v praxi se tato veličina měří velmi těžko. Nemůžeme totiž využít IP adres, protože jedna IP adresa může představovat i několik desítek či stovek uživatelů internetu a naopak jeden uživatel se může skrývat pod několika IP adresami. Jediným způsobem, jak od sebe odlišit jednotlivé uživatele, je proto použití cookies. I to má však své mouchy. Někteří uživatelé si totiž podporu cookies vypínají. Další problém může nastat, pokud počítadlo vkládáme jako obrázek z cizích stránek, stále častěji totiž bývá taková „cookie třetí strany“ odfiltrována. Navíc na jednom počítači může pracovat několik lidí. Z toho vidíte, že určit přesně počet unikátních návštěvníků za nějaké časové období (v našem případě den) je záležitost velmi komplikovaná a vlastně nemožná.

Náš skript bude měřit počet unikátních návštěvníků za den kombinací cookies a IP adres. Nejprve uložíme cookie s názvem visit, která bude platit pouze dnes. Toho docílíme použitím známé funkce mktime() vracející počet sekund od 1. 1. 1970 až do zadaného období. Jako čtvrtý parametr funkce setcookie() musíme uvést „/“ – cookie bude poté platná pro všechny dokumenty v rámci domény.

// VISIT – unikatní navstevnik / den (cookie plati pouze dnes)
setcookie(‚visit‘, ‚PAGEVIEW‘, mktime(23,59,59, date(‚m‘), date(‚d‘), date(‚Y‘)), ‚/‘);

V další části zjistíme, zda cookie existuje. Pokud ano, o visit se nejedná ($visit = 0). V opačném případě musíme zjistit, zda uživatel s danou IP adresou ($ip) přistoupil na stránky v posledních 20 minutách. K tomu použijeme dvě databázové funkce DATE_ADD(datum, období) a NOW(). DATE_ADD umožňuje přičíst k datu určité období. My k datu přístupu (access_date) přičteme oněch dvacet minut a porovnáme s aktuálním datem a časem, jejichž hodnotu vrací funkce NOW(). Pokud v databázi existuje alespoň jeden takový záznam, znamená to, že uživatel s danou IP adresou přistoupil před časovým úsekem kratším než 20 minut a tudíž se nejedná o visit. V opačném případě se jedná o visit ($visit = 1).

Ani tato metoda však bohužel neurčí přesně počet unikátních návštěvníků za den. Může se stát, že na stránkách se současně pohybuje několik uživatelů se stejnou IP adresou, kteří mají vypnuté cookies – bude započítán pouze jeden visit. Naopak uživatel s vypnutými cookies může v průběhu dne navštívit stránky vícekrát a vytvořit tak více visits.

// IP ADRESA
if(isset($_SERVER[‚HTTP_X_FORWARDED_FOR‘])) {
  $explode_ip = explode(‚,‘, $_SERVER[‚HTTP_X_FORWARDED_FOR‘]);
  $ip = $explode_ip[0];
} else {
  $ip = $_SERVER[‚REMOTE_ADDR‘];
}
// pokud cookie existuje, nejedna se o visit
// v opacnem pripade zjistime, zda dana IP adresa pristoupila v poslednich 20 minutach (pokud ne, jedna se o visit)
if(isset($_COOKIE[‚visit‘])) {
  $visit = 0;
} else {
  $query = mysql_query(„SELECT access_date FROM access WHERE ip = ‚$ip‘ AND DATE_ADD(access_date, INTERVAL 20 MINUTE) > NOW() LIMIT 0,1“);
  if($result = mysql_fetch_array($query))
    $visit = 0;
  else
    $visit = 1;
}

Pozn. aut.: Postup, kterým zjišťujeme IP adresu, bude popsán v některém z dalších článků, týkajícím se domén.

Souhrnná statistika

Nyní si projdeme úvodní část souboru stat.php, který provádí vyhodnocení získaných údajů.

<?php
// zabranime cashovani
header(‚Cache-Control: no-cache‘);
header(‚Pragma: no-cache‘);
header(‚Expires: ‚ . gmdate(‚D, d M Y H:i:s‘) . ‚ GMT‘);
?>
<!DOCTYPE html PUBLIC ‚-//W3C//DTD XHTML 1.0 Strict//EN‘ ‚http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd‘>
<html xmlns=“http://www.w3.org/1999/xhtml“ xml:lang=“cs“ lang=“cs“>
<head>
<meta http-equiv=“Content-Type“ content=“text/html; charset=windows-1250″ />
<meta http-equiv=“Content-language“ content=“cs“ />
<meta http-equiv=“Cache-control“ content=“no-cache“ />
<meta http-equiv=“Pragma“ content=“no-cache“ />
<meta http-equiv=“Expires“ content=“0″ />
<title>Statistika přístupů</title>
<style media=“all“ type=“text/css“>
@import „style.css“;
</style>
</head>
<body>

Součástí statistiky je i možnost zvolit si v kalendáři období, pro které se vypracuje statistika. (O vytvoření kalendáře bude některý z dalších článků.) Pokud nebylo na kalendáři zvoleno datum, vložíme do proměnných $from_date (datum OD) a $to_date (datum DO) standardní hodnoty, tj. dnešní datum. Do proměnných $sql_access_date a $sql_search_date poté vložíme podmínku omezující výběr záznamů z databáze pouze na dané období.

require ‚./db.php‘; // pripojeni k databazi
require ‚./calendar.php‘; // kalendar
// standardni hodnoty promennych
$from_date = date(‚Y-m-d‘);
$to_date = date(‚Y-m-d‘);
if(isset($_GET[‚from_date‘])) $from_date = addslashes($_GET[‚from_date‘]);
if(isset($_GET[‚to_date‘])) $to_date = addslashes($_GET[‚to_date‘]);
// omezeni statistiky na urcite obdobi
$sql_access_date = „access_date >= ‚$from_date‘ AND access_date <= ‚$to_date 23:59:59′“;
$sql_search_date = „search_date >= ‚$from_date‘ AND search_date <= ‚$to_date 23:59:59′“;

Nyní tedy můžeme získat hodnoty základních statistických veličin za vybrané období. Jedná se o pageviews (počet shlédnutých stránek), visits (součet denních visits za dané období), počet unikátních IP adres (UIP) a poslední přístup. SQL dotazy jsou vcelku jednoduché. Za zmínku stojí snad jen použití agregačních funkcí count() a max() vracejících, počet záznamů a maximální hodnotu v určitém sloupci. Pro někoho je možná neznámý i modifikátor DISTINCT – při jeho použití se z databáze vyberou jen unikátní záznamy, v našem případě unikátní IP adresy.

// PAGEVIEWS – shlednute stranky
$query = mysql_query(„SELECT count(id) FROM access WHERE $sql_access_date“);
$result = mysql_fetch_array($query);
$pageviews = $result[‚count(id)‘];
// VISITS – soucet dennich visits za dane obdobi
$query = mysql_query(„SELECT count(id) FROM access WHERE visit = 1 AND $sql_access_date“);
$result = mysql_fetch_array($query);
$visits = $result[‚count(id)‘];
// UNIKATNI IP
$query = mysql_query(„SELECT count(DISTINCT ip) as count_ip FROM access WHERE $sql_access_date“);
$result = mysql_fetch_array($query);
$unique_ip = $result[‚count_ip‘];
// POSLEDNI PRISTUP
$query = mysql_query(„SELECT max(access_date) AS maxdate FROM access WHERE $sql_access_date“);
if($result = mysql_fetch_array($query))
  $maxdate = $result[‚maxdate‘];

V databázi je datum a čas uložen ve formátu RRRR-MM-DD HH:MM:SS. V češtině je zvykem psát datum ve formátu DD. MM. RRRR HH:MM:SS. Převod provedeme tak, že řetězec nejprve rozdělíme na dvě části – datum a čas, které jsou odděleny mezerou. Poté rozdělíme na jednotlivé části ještě datum a na závěr poskládáme vše dohromady. Některé řetězce ještě přetypujeme na čísla pomocí příkazu (int), zbavíme se tak počátečních nul.

// prevod na cesky zapis data
if($maxdate) {
  $explode1 = explode(‚ ‚, $maxdate);
  $explode2 = explode(‚-‚, $explode1[0]);
  $maxdatecz = (int)$explode2[2] . ‚. ‚ . (int)$explode2[1] . ‚. ‚ . $explode2[0] . ‚ ‚ . $explode1[1];
} else {
  $maxdatecz = ‚-‚;
}

Nad celou statistikou uvedeme období, pro které byla statistika vypracována a získané hodnoty zapíšeme do tabulky.

<?php
$from = explode(‚-‚, $from_date); // od
$to = explode(‚-‚, $to_date); // do
$period = (int)$from[2] . ‚. ‚ . (int)$from[1] . ‚. ‚ . $from[0] . ‚ – ‚ . (int)$to[2] . ‚. ‚ . (int)$to[1] . ‚. ‚ . $to[0];
echo ‚<h2>Období: ‚ . $period . ‚</h2>‘;
?>
<h2>Souhrnné statistiky</h2>
<table cellspacing=“0″>
 <tr><td>Pageviews</td><td><?php echo $pageviews;?></td></tr>
 <tr><td>Visits</td><td><?php echo $visits;?></td></tr>
 <tr><td>Unikátních IP</td><td><?php echo $unique_ip;?></td></tr>
 <tr><td>Poslední přístup</td><td><?php echo $maxdatecz;?></td></tr>
</table>

Tímto úvodní článek končí. Příště se dozvíte, jak provést detekci prohlížeče.

Pozn. red.: Tento článek vyšel poprvé 13. 5. 2002. Původní verze článku a k němu vedené diskuse jsou vám k dispozici v ZIP archivech.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

1 komentář

  1. Pave

    Čvc 27, 2010 v 15:52

    ukázka nefunguje, nemohli byste ji zpravit?

    Odpovědět

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *