Statistika p°φstup∙ v PHP - odkud p°ichßzejφ nßvÜt∞vnφci
V tomto Φlßnku opustφme pßtrßnφ po technick²ch informacφch o u₧ivateli a jeho prohlφ₧eΦi a povφme si, jak zjistit, ze kter²ch strßnek k nßm nßvÜt∞vnφci p°ichßzejφ.
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/.
Ke zjiÜt∞nφ odkud k nßm nßvÜt∞vnφci p°ichßzejφ, vyu₧ijeme HTTP hlaviΦku Referer - ta obsahuje URL strßnky, ze kterΘ u₧ivatel p°iÜel na aktußlnφ strßnku. V PHP je obsah tΘto hlaviΦky v prom∞nnΘ $_SERVER['HTTP_REFERER']. Musφme si vÜak uv∞domit, ₧e poΦφtadlo vklßdßme do strßnek jako obrßzek, a proto tato prom∞nnß neobsahuje URL strßnky, ze kterΘ u₧ivatel p°iÜel, n²br₧ URL aktußlnφ strßnky. Jak bylo naznaΦeno ji₧ v p°edchozφm Φlßnku, musφme pou₧φt JavaScript a obrßzek (counter.php) vklßdat s n∞kolika parametry. Parametr referer bude obsahovat URL strßnky, ze kterΘ u₧ivatel p°iÜel na aktußlnφ strßnku. Tuto hodnotu, kterß se nachßzφ v top.document.referrer, musφme pomocφ funkce escape() zak≤dovat tak, aby byla bezpeΦn∞ pou₧itelnß v URL. JavaScriptovß funkce escape() pracuje obdobn∞ jako PHP funkce urlencode(). O dalÜφch parametrech ji₧ byla °eΦ v minulΘm Φlßnku.
<!--
document.write("<img src=\"__vas_server__/counter.php?referer=" + escape(top.document.referrer) + "&screenres=" + screen.width + "x" + screen.height + "&colordepth=" + screen.colorDepth + "\" width=\"1\" height=\"1\" alt=\"\">");
// -->
</script>
Tabulka referer
Do tabulky referer budeme uklßdat strßnky (servery), ze kter²ch nßvÜt∞vnφci na naÜe strßnky p°ichßzejφ. Tabulku vytvo°φme pomocφ tohoto SQL dotazu:
id int(11) NOT NULL auto_increment,
server varchar(50) NOT NULL,
PRIMARY KEY (id)
);
- id - unikßtnφ oznaΦenφ ka₧dΘho serveru (primßrnφ klφΦ)
- server - adresa serveru, ze kterΘho p°ichßzejφ
Do tabulky vlo₧φme i dva zßkladnφ zßznamy, o kter²ch se za chvφli zmφnφm.
INSERT INTO referer VALUES (2, 'P°echod v rßmci serveru');
URL strßnky, ze kterΘ u₧ivatel p°iÜel ($_GET['referer']) musφme nejd°φv zp∞tn∞ pomocφ funkce urldecode() dek≤dovat a p°evΘst na malß pφsmena, aby se v databßzi neobjevovaly stejnΘ strßnky liÜφcφ se pouze velikostφ pφsmen v URL. Kombinace funkcφ escape() a urldecode() si ne v₧dy poradφ se vÜemi Φesk²mi znaky. Prozatφm nßs to vÜak nemusφ zajφmat, vφce se dozvφte v p°φÜtφm Φlßnku o vyhledßvacφch frßzφch.
Proto₧e ne v₧dy p°ichßzφ nßvÜt∞vnφk z cizφch strßnek, musφme rozliÜit celkem t°i mo₧nosti. Pokud je prom∞nnß $http_referer prßzdnß, jednß se o p°φmΘ volßnφ, co₧ znamenß, ₧e u₧ivatel zadal danΘ URL p°φmo do adresnφho °ßdku prohlφ₧eΦe -> $referer = 1. Dßle musφme rozliÜit, zda se nejednß pouze o p°echod mezi jednotliv²mi strßnkami v rßmci serveru. Do konstanty no_Referer v config.php nejprve vlo₧φme alespo≥ ΦßsteΦnou adresu naÜeho serveru. Pokud se no_Referer nachßzφ v $http_referer, jednß se o p°echod v rßmci serveru -> $referer = 2. Jestli₧e nebyla spln∞na ani jedna podmφnka, p°iÜel nßvÜt∞vnφk z cizφch strßnek.
$referer = 2; // predpokladame prechod v ramci serveru
if(isset($_GET['referer'])) {
// rozkoduje URL a prevede na mala pismena
$http_referer = addslashes(urldecode(strtolower($_GET['referer'])));
if ($http_referer == '') { // prime volani
$referer = 1;
} elseif (eregi(no_Referer, $http_referer)) { // prechod v ramci serveru
$referer = 2;
Nejprve struΦn∞ k tomu, jak²m zp∙sobem budeme provßd∞t statistiku p°φchod∙ z cizφch strßnek. Jasn∞jÜφ to bude na p°φkladu. Mßme tyto adresy, ze kter²ch nßvÜt∞vnφci p°iÜli: http://interval.cz/clanek.asp?article=754, http://interval.cz/clanek.asp?article=351, http://diskuse.interval.cz/default.asp?idcategory=1. Proto₧e celß adresa strßnky, ze kterΘ u₧ivatel p°iÜel, nßm p°φliÜ mnoho ne°ekne, budeme monitorovat jen domΘnovΘ adresy strßnek, z Φeho₧ vypl²vß, ₧e prvnφ nßvÜt∞vnφk (http://interval.cz/clanek.asp?article=754) p°iÜel z interval.cz. Proto₧e Φßst "www.", jako₧to domΘna t°etφ ·rovn∞, nemß prakticky ₧ßdn² vypovφdacφ v²znam (server.cz je totΘ₧, co www.server.cz), bude i 2. odkaz (http://interval.cz/clanek.asp?article=351) znamenat, ₧e nßvÜt∞vnφk p°iÜel z interval.cz. U t°etφho odkazu (http://diskuse.interval.cz/default.asp?idcategory=1) je domΘnou t°etφ ·rovn∞ Φßst "diskuse", co₧ nßm °φkß, ₧e se jednß nejspφÜ o n∞jakou diskusnφ Φßst serveru interval.cz, a proto se bude jednat o p°φstup z diskuse.interval.cz. Pokud byste cht∞li zjiÜ¥ovat, z jak²ch konkrΘtnφch strßnek danΘho serveru nßvÜt∞vnφci p°ichßzejφ, m∙₧ete tyto funkce samoz°ejm∞ odstranit nebo upravit.
Po troÜku delÜφ teorii p°ichßzφ na °adu praktickΘ °eÜenφ danΘ ·lohy. URL ($http_referer) si nejprve rozd∞lφme na jednotlivΘ Φßsti pomocφ funkce parse_url(). V poli s indexem host je potΘ domΘnovß adresa (nap°φklad www.interval.cz). Pole obsahuje celou °adu dalÜφch u₧iteΦn²ch informacφ - podrobnosti najdete v manußlu PHP. Nßsledn∞ odstranφme z adresy Φßst "www".
Pomocφ znßm²ch funkcφ a postup∙ zjistφme, zda dan² server v tabulce referer ji₧ existuje. Pokud ne, tak ho samoz°ejm∞ p°idßme. Do prom∞nnΘ $referer si ulo₧φme id danΘho serveru, tato prom∞nnß bude souΦßstφ SQL dotazu, kter² ulo₧φ do tabulky access vÜechny informace o danΘm p°φstupu.
$url = parse_url($http_referer); // rozdeli URL na casti
$host = eregi_replace("^www\.", "", $url['host']); // odstrani "www."
// je stranka v databazi ? (pokud ne, pridame ji)
$query = mysql_query("SELECT id FROM referer WHERE server = '$host'");
if ($result = mysql_fetch_array($query)) {
$referer = $result['id'];
} else {
$query = mysql_query("INSERT INTO referer VALUES ('', '$host')");
$referer = mysql_insert_id();
}
Vyhodnocenφ
Statistika se bude sklßdat ze dvou tabulek. V prvnφ bude vyjßd°en pom∞r p°φm²ch volßnφ a p°φstup∙ z cizφch server∙. V druhΘ potom p°φstupy z jednotliv²ch server∙. PoΦet p°φm²ch volßnφ za danΘ obdobφ ($sql_access_date) zjistφme tak, ₧e do SQL dotazu p°idßme podmφnku WHERE referer = 1. P°i urΦovßnφ poΦtu p°φstup∙ ze vÜech cizφch server∙ pou₧ijeme podmφnku WHERE referer > 2 (1 = p°φmΘ volßnφ, 2 = p°echod v rßmci naÜeho serveru). Nßsledn∞ pomocφ v∞tÜφ z obou hodnot ($max) a celkovΘho poΦtu ($sum) vypoΦφtßme Üφ°ku obrßzku znßzor≥ujφcφho podφl a samotn² podφl v procentech. Tento postup je blφ₧e popsßn v Φlßnku o detekci operaΦnφho systΘmu.
// prime volani
$query = mysql_query("SELECT count(id) FROM access WHERE referer = 1 AND $sql_access_date");
$result = mysql_fetch_array($query);
$count_direct = $result['count(id)'];
// pristupy z cizich stranek
$query = mysql_query("SELECT count(id) FROM access WHERE referer > 2 AND $sql_access_date");
$result = mysql_fetch_array($query);
$count_referer = $result['count(id)'];
$max = max($count_direct, $count_referer); // maximalni hodnota (kvuli meritku)
$sum = $count_referer+$count_direct;
if($max != 0) {
// sirky obrazku
$width_direct = round($count_direct/$max*200);
$width_referer = round($count_referer/$max*200);
// podil
$rate_direct = sprintf('%.2f', $count_direct/($sum/100));
$rate_referer = sprintf('%.2f', $count_referer/($sum/100));
echo '<h2>P°φmΘ volßnφ X p°φstupy z cizφch strßnek</h2>';
echo '<table width="550" cellspacing="0">';
echo '<tr><th>Typ</th><th>PoΦet</th><th>Podφl</th></tr>';
echo '<tr><td>P°φmΘ volßnφ</td><td>' . $count_direct . '</td><td><img src="1.gif" width="' . $width_direct . '" height="8" alt="" /> ' . $rate_direct .' %</td></tr>';
echo '<tr><td>Odjinud</td><td>' . $count_referer . '</td><td><img src="1.gif" width="' . $width_referer . '" height="8" alt="" /> ' . $rate_referer . ' %</td></tr>';
echo "</table>\n\n";
}
V²pis poΦtu p°φstup∙ z jednotliv²ch server∙ provedeme spojenφm tabulek referer a access, kde polo₧ka id v tabulce referer je primßrnφm klφΦem a polo₧ka referer v tabulce access cizφm klφΦem. Podrobn∞jÜφ vysv∞tlenφ, by¥ se jednß o statistiku prohlφ₧eΦ∙, najdete op∞t v ji₧ zmi≥ovanΘm Φlßnku o detekci operaΦnφho systΘmu.
// vybirame servery podle jejich zastoupeni
$query = mysql_query("SELECT server, count(referer) AS count_it FROM access JOIN referer ON (referer = referer.id) WHERE referer.id > 2 AND $sql_access_date GROUP BY referer ORDER BY count_it DESC");
if(mysql_numrows($query) != 0) {
echo '<h2>Z jak²ch strßnek priÜli</h2>';
echo '<table width="550" cellspacing="0">';
echo '<tr><th>Server</th><th>Pocet</th><th>Podφl</th></tr>';
$max = mysql_result($query, 0, "count_it"); // pocet pristupu z nejvice zastoupeneho serveru
$move = mysql_data_seek($query, 0); // presuneme se znovu na zacatek
while($result = mysql_fetch_array($query)) {
$width = round($result['count_it']/$max*200); // sirka obrazku znazornujiciho podil
$rate = sprintf('%.2f', $result['count_it']/($count_referer/100)); // podil v procentech
echo '<tr><td>' . $result['server'] . '</td><td>' . $result['count_it'] . '</td><td><img src="1.gif" width="' . $width . '" height="8" alt="" /> ' . $rate . ' %>/td>>/tr>';
}
echo "</table>\n\n";
}
V p°φÜtφm Φlßnku, kterΘ do znaΦnΘ mφry souvisφ s tφmto, se dozvφte, jak zjistit, kterΘ frßze pou₧φvajφ nßvÜt∞vnφci strßnek v r∙zn²ch vyhledßvaΦφch (Seznam, Atlas, Jyxo, Google a dalÜφ).
Pozn. red.: Tento Φlßnek vyÜel poprvΘ 20. 6. 2002. P∙vodnφ verze Φlßnku a k n∞mu vedenΘ diskuse jsou vßm k dispozici v ZIP archivech.
Statistika p°φstup∙ v PHP
Velmi podrobn² popis v²stavby analytickΘho systΘmu pro sledovßnφ pohybu nßvÜt∞vnφk∙ serverem. SouΦßstφ jsou funkΦnφ skripty k okam₧itΘmu pou₧itφ. DruhΘ vydßnφ. Tato sΘrie Φlßnk∙ dosud nebyla ukonΦena!
- Statistika p°φstup∙ v PHP - vyhledßvacφ frßze
- Statistika p°φstup∙ v PHP - odkud p°ichßzejφ nßvÜt∞vnφci (prßv∞ Φtete)
- Statistika p°φstup∙ v PHP - rozliÜenφ a barevnß hloubka
- Statistika p°φstup∙ v PHP - detekce operaΦnφho systΘmu
- Statistika p°φstup∙ v PHP - detekce prohlφ₧eΦe
- Statistika p°φstup∙ v PHP - poΦet unikßtnφch nßvÜt∞vnφk∙