Navigace

Hlavnφ menu

 

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.

<script language="JavaScript" type="text/javascript">
<!--
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:

CREATE TABLE referer (
  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 (1, 'P°φmΘ volßnφ');
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 - odkud prisel navstevnik
$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.

  } else { // navstevnik prisel z cizich stranek
    $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 X PRISTUPY Z CIZICH STRANEK

// 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.

// REFERER
// 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.

Kebrt, Michal (28. 2. 2004)

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!