Как и многие программисты, я страдаю некоторой степенью подозрительности к чужим сервисам, и предпочитаю делать все сам.
К чужим сервисам, в частности относится liveinternet и другие счетчики посещений. Я им как то не доверяю, знаете ли.
Сейчас я вам расскажу (и покажу) как нетрудно сделать учет посетителей сайта с помощью modx.
Для начала нам нужно создать таблицу для хранения посещений. Делаем sql запрос как вам удобно. Например, в phpmyadmin.
Таблица готова, теперь нам нужен плагин, для фиксирования посещений.
Большинство пользователей знают про сниппеты и чанки в modx, а вот про плагины обычно не в курсе. Рассказываю: плагин в modx, если по простому — это сниппет, который работает без вызова из документа, сам по себе, реагируя на системные события, коих в движке предусмотрено довольно много. Нас интересует событие OnLogPageHit.
Идем в
Называем новый плагин dbLog и вставляем в него следующий код:
Переключаем вкладку Системные события и выставляем OnLogPageHit, затем жмакаем сохранить. Обратите внимание: при оформлении плагина в редакторе админки не должно быть <?php вначале и ?> в конце. У сниппетов должно, а у плагинов — нет. Не знаю почему так сделано, но при написании своего первого пагина я много матерился.
Все, плагин уже должен фиксировать всех ваших посетителей. Если вы, конечно, нигде не ошиблись!
Кстати, есть еще вариант повешать срабатывание плагина на событие OnWebPageComplete. Тогда нужно будет в настройках админки включить «Регистрировать посещения» и заработает аналогичный тырчик в свойствах документов. Тоже не плохой вариант, но я его еще не обкатывал. Подробнее о событиях можно глянуть тут.
Если вы хотите узнавать имена хостов, которые зарегистрированы на ip ваших посетителей, можно сделать еще один сниппет (Ip2Host) и запускать его по расписанию.
Почему так? Это сэкономит силы серверу, ибо, если узнавать хост юзера при каждом запросе страницы — нагрузка будет нешуточная. Лучше запускать раз в сутки, ночью.
Нужно оформить вызов на какой-нибудь скрытой от посторонних странице:
и дергать ее cron`ом:
В принципе, ваши посещения уже в базе, и выводить их оттуда можно как удобно. Лично мне приятно наблюдать это в виде симпатичного графика и отдельной табличке с циферками.
Так и сделаем.
Пишем сниппет для забора данных из БД и вывода их в понятную таблицу, график будем делать позже. Комментарии как обычно, внутри кода.
Создаем сниппет, называем его, например, generateStatGraph, копируем туда код и сохраняем.
Теперь нам нужно как то вывести на экран результат нашей бурной деятельности.
Нам понадобится два чанка-шаблона. первый, просто для таблицы, второй посложнее — для построения графика. Их можно будет использовать независимо друг от друга.
Первый шаблон, для вывода таблицы (tpl.StatTable).
Второй шаблон, для построения графика (tpl.StatGraph).
Как вы можете заметить, эти два шаблона отличаются наличием во втором подключения замечательного плагина jquery jQuery Visualize, который позволяет нам строить графики из таблиц. А также оформление этого графика.
Отрисовка графика запускается следующим кодом (подробнее про параметры jquery.visualize, а также примеры оформления — по ссылке выше):
Уффф… Уже почти все.
Создаем новый документ modx и запускаем в нем сниппет (отдельно таблицу и график).
Хотелось бы отметить, что здесь мы рассмотрели только показ анонимной статистики посещений, а в БД у нас хранится информация об ip, времени посещений, браузерах юзеров и тд. Эту информацию вы можете просматривать или напрямую из БД, или написать простенький сниппет + чанк оформления для вывода на сайт, в защищенный раздел.
Кому любопытно — можно посмотреть результат в работе, заодно воочию зацените хабраэффект.
Кстати, видно некислое различие статистики, которую собираю я, и которую показывает liveinternet на счетчике внизу каждой страницы.
Параметры сниппета generateStatGraph:
&db
&dateFormat
&days
&$daysText
&tpl
&act
&int
Плэйсхолдеры сниппета eventsCalendar:
[+stat.days+]
[+stat.days.text+]
[+stat.date+]
[+stat.host+]
[+stat.hit+]
Ссылки на нужные сайты.
Багрепорты засылать на bezumkin@yandex.ru, или оставлять в этой теме.
К чужим сервисам, в частности относится liveinternet и другие счетчики посещений. Я им как то не доверяю, знаете ли.
Сейчас я вам расскажу (и покажу) как нетрудно сделать учет посетителей сайта с помощью modx.
Этап 1. Пишем лог.
Для начала нам нужно создать таблицу для хранения посещений. Делаем sql запрос как вам удобно. Например, в phpmyadmin.
CREATE TABLE IF NOT EXISTS `modx_visitors_log` (
`index` int(10) NOT NULL AUTO_INCREMENT,
`ip` varchar(15) COLLATE utf8_unicode_ci NOT NULL,
`host` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`url` text COLLATE utf8_unicode_ci NOT NULL,
`datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`referer` text COLLATE utf8_unicode_ci NOT NULL,
`browser` varchar(255) NOT NULL,
PRIMARY KEY (`index`),
KEY `ip` (`ip`,`host`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
Таблица готова, теперь нам нужен плагин, для фиксирования посещений.
Большинство пользователей знают про сниппеты и чанки в modx, а вот про плагины обычно не в курсе. Рассказываю: плагин в modx, если по простому — это сниппет, который работает без вызова из документа, сам по себе, реагируя на системные события, коих в движке предусмотрено довольно много. Нас интересует событие OnLogPageHit.
Идем в
Элементы->Управление элементами->Плагины->Создать плагин
Называем новый плагин dbLog и вставляем в него следующий код:
/* Основные настройки*/
// Таблица для лога посетителей по умолчанию это modx_visitors_log
$db = '`modx_visitors_log`';
// Не логировать этих юзеров и IP. Если логировать всех - должны быть пустые массивы
$not_log_ip = array('192.168.100.1', '192.168.100.2');
$not_log_user = array('bezumkin');
/* Конец настроек */
// Выставляем переменные
$login = $_SESSION['webShortname']; // Если у вас юзеры авторизуются на сайте. Если нет - будет пустое поле.
$ip = $_SERVER['REMOTE_ADDR']; // IP запрашивающего адреса. Проверки на прокси нет.
$host = ''; // Здесь будет имя хоста, принадлежащего IP юзера. Пока не трогаем.
$url = $_SERVER['REQUEST_URI']; // Запрашиваемая страница.
$referer = urlencode($_SERVER['HTTP_REFERER']); // Откуда пришел юзер, по какой ссылке.
$browser = mysql_real_escape_string($_SERVER['HTTP_USER_AGENT']); // Браузер юзера. Я использую класс browscap, а вы как хотите. Для примера сойдет и так.
// Пишем в лог
if (!in_array($ip, $not_log_ip) and !in_array($login, $not_log_login)) {
$modx->db->query("INSERT INTO $db (`login`, `ip`, `host`, `url`, `referer`,`browser`)
VALUES ('$login','$ip','$host', '$url','$referer','$browser')");
}
Переключаем вкладку Системные события и выставляем OnLogPageHit, затем жмакаем сохранить. Обратите внимание: при оформлении плагина в редакторе админки не должно быть <?php вначале и ?> в конце. У сниппетов должно, а у плагинов — нет. Не знаю почему так сделано, но при написании своего первого пагина я много матерился.
Все, плагин уже должен фиксировать всех ваших посетителей. Если вы, конечно, нигде не ошиблись!
Кстати, есть еще вариант повешать срабатывание плагина на событие OnWebPageComplete. Тогда нужно будет в настройках админки включить «Регистрировать посещения» и заработает аналогичный тырчик в свойствах документов. Тоже не плохой вариант, но я его еще не обкатывал. Подробнее о событиях можно глянуть тут.
Если вы хотите узнавать имена хостов, которые зарегистрированы на ip ваших посетителей, можно сделать еще один сниппет (Ip2Host) и запускать его по расписанию.
Почему так? Это сэкономит силы серверу, ибо, если узнавать хост юзера при каждом запросе страницы — нагрузка будет нешуточная. Лучше запускать раз в сутки, ночью.
<?php
$db = '`modx_visitors_log`';
// Выбираем все записи, с пустым полем host
$sql = $modx->db->query("SELECT `ip` FROM $db WHERE `host` = '' GROUP BY `ip`");
$arr = $modx->db->makeArray($sql);
// Перебираем их все
foreach ($arr as $v) {
$ip = $v['ip'];
// Делаем обычный nslookup. Если сайт хостится на Windows, во-первых, мне вас жаль, а во-вторых - эту строчку придется поменять на что-то другое.
$host = `nslookup "$ip" | grep 'name =' | awk '{print $4}'`;
// Если имени мы не получили - пишем, что хост не известен, чтобы повторно его не выбирать в следующий раз.
if (empty($host)) {$host = 'unknown';}
//Сохраняем результат в базу.
$modx->db->query("UPDATE $db SET `host` = '$host' WHERE `ip` = '$ip' AND `host` = '';");
}
?>
Нужно оформить вызов на какой-нибудь скрытой от посторонних странице:
[!Ip2Host!]
и дергать ее cron`ом:
10 2 * * * * user wget localhost/secret_page.html
Этап второй. Вывод лога на экран.
В принципе, ваши посещения уже в базе, и выводить их оттуда можно как удобно. Лично мне приятно наблюдать это в виде симпатичного графика и отдельной табличке с циферками.
Так и сделаем.
Пишем сниппет для забора данных из БД и вывода их в понятную таблицу, график будем делать позже. Комментарии как обычно, внутри кода.
<?php
/* Основные настройки */
if (empty($db)) {$db = '`modx_visitors_log`';} // База данных с логом
if (empty($days)) {$days = 14;} // Кол-во дней для вывода таблицы
if (empty($daysText)) {$daysText = 'дней';} // Текст после кол-ва дней в чанке, не обязательно
if (empty($tpl)) {$tpl = 'visitStat.tpl';} // Шаблон для таблицы
if (empty($act)) {$act = 'graph';} // Режим вывода таблицы, всего их два, graph & table
if (empty($dateFormat)) {$dateFormat = '%d.%m';} // вывод даты, формат strftime()
if (empty($int)) {$int = 2;} // Интервал вывода даты в режиме graph. по умолчанию - каждая вторая.
/* Конец настроек */
// Выясняем, за какое время выбирать данные
$cur = time();
$end = date("Y-m-d");
$start = strftime("%Y-%m-%d", ($cur - ($days * 86400)));
// Выбираем
$sql = $modx->db->query("SELECT DATE(`datetime`) as `date`,
COUNT(distinct `ip`) as `host`,
COUNT(`ip`) as `hit`
FROM $db WHERE DATE(`datetime`) BETWEEN '$start' AND '$end'
GROUP BY DATE(`datetime`) ORDER BY `datetime` ASC");
$result = $modx->db->makeArray($sql);
// Разбираем результат на 3 разных массива, дату, хосты и хиты
foreach($result as $v) {
$date[] = $v['date'];
$host[] = $v['host'];
$hit[] = $v['hit'];
}
// В режиме graph выводится каждая $int дата, в режиме таблицы - все даты
$i = 1;
foreach ($date as $v) {
if ($act == 'graph') {
if ($i == $int) {
$i = 0;
$date2 .= '<th></th>';
}
else {
$date2 .= '<th>'.strftime($dateFormat, strtotime($v)).'</th>';
}
$i++;
}
else if ($act == 'table') {
$date2 .= '<th>'.strftime($dateFormat, strtotime($v)).'</th>';
}
}
foreach ($host as $v) {
$host2 .= '<td>'.$v.'</td>';
}
foreach ($hit as $v) {
$hit2 .= '<td>'.$v.'</td>';
}
$placeholders = array('[+stat.days+]','[+stat.days.text+]','[+stat.date+]','[+stat.host+]','[+stat.hit+]');
$values = array($days, $daysText, $date2, $host2, $hit2);
$html = $modx->getChunk($tpl);
echo str_replace($placeholders, $values, $html);
?>
Создаем сниппет, называем его, например, generateStatGraph, копируем туда код и сохраняем.
Теперь нам нужно как то вывести на экран результат нашей бурной деятельности.
Нам понадобится два чанка-шаблона. первый, просто для таблицы, второй посложнее — для построения графика. Их можно будет использовать независимо друг от друга.
Первый шаблон, для вывода таблицы (tpl.StatTable).
<div style='margin: auto;text-align: center;'>
<table id='chart_table'>
<caption>Статистика посещений сайта за последние [+stat.days+] [+stat.days.text+]</caption>
<thead>
<tr><td></td>[+stat.date+]</tr>
</thead>
<tbody>
<tr><th>Посетители</th>[+stat.host+]</tr>
<tr><th>Просмотры</th>[+stat.hit+]</tr>
</tbody>
</table>
</div>
Второй шаблон, для построения графика (tpl.StatGraph).
<link type='text/css' rel='stylesheet' href='[(site_url)]inc/css/visualize.css' />
<script type='text/javascript' src='[(site_url)]inc/js/visualize.jquery.js'></script>
<script type='text/javascript'>
$(document).ready(function(){
$('#chart').visualize({
type: 'area',
width: '570',
height: '300'
});
});
</script>
<div style='margin: auto;'>
<table id='chart' style='display: none;'>
<caption>Статистика посещений сайта за последние [+stat.days+] [+stat.days.text+]</caption>
<thead>
<tr><td></td>[+stat.date+]</tr>
</thead>
<tbody>
<tr><th>Посетители</th>[+stat.host+]</tr>
<tr><th>Просмотры</th>[+stat.hit+]</tr>
</tbody>
</table>
</div>
Как вы можете заметить, эти два шаблона отличаются наличием во втором подключения замечательного плагина jquery jQuery Visualize, который позволяет нам строить графики из таблиц. А также оформление этого графика.
Отрисовка графика запускается следующим кодом (подробнее про параметры jquery.visualize, а также примеры оформления — по ссылке выше):
$(document).ready(function(){
$('#chart').visualize({
type: 'area',
width: '570',
height: '300'
});
});
Уффф… Уже почти все.
Этап 3. Запуск!
Создаем новый документ modx и запускаем в нем сниппет (отдельно таблицу и график).
[!generateStatGraph?
&days=`20`
&tpl=`tpl.StatTable`
&act=`table`
&dateFormat=`%d <i>%b</i>`
!]
[!generateStatGraph?
&days=`20`
&daysText=`дней`
&tpl=`tpl.StatGraph`
&act=`graph`
&dateFormat=`%d`
!]
Хотелось бы отметить, что здесь мы рассмотрели только показ анонимной статистики посещений, а в БД у нас хранится информация об ip, времени посещений, браузерах юзеров и тд. Эту информацию вы можете просматривать или напрямую из БД, или написать простенький сниппет + чанк оформления для вывода на сайт, в защищенный раздел.
Приложение.
Кому любопытно — можно посмотреть результат в работе, заодно воочию зацените хабраэффект.
Кстати, видно некислое различие статистики, которую собираю я, и которую показывает liveinternet на счетчике внизу каждой страницы.
Параметры сниппета generateStatGraph:
&db
по умолчанию: `modx_visitors_log`
значение: [string]
описание: Имя существующей таблицы, можно вместе с БД (`modx`.`modx_log`).
&dateFormat
по умолчанию: '%d %b %Y %H:%M'
значение: переменные strftime()
описание: Формат даты.
&days
по умолчанию: 14
значение: [int]
описание: Количество дней выборки посещений от сейчас.
&$daysText
по умолчанию: 'дней'
значение: [string]
описание: Текст подписи для кол-ва дней выборки, не обязательно, используется только в шаблонах.
&tpl
по умолчанию: 'tpl.StatGraph'
значение: Имя существующего шаблона modx
описание: Шаблон для вывода таблицы.
&act
по умолчанию: 'graph'
значение: graph, table
описание: Режим обработки таблицы при выводе. graph пропускает даты.
&int
по умолчанию: 2
значение: [int]
описание: Если &act=`graph`, &int указывает, каждую какую дату показывать. по умолчанию - каждую вторую.
Плэйсхолдеры сниппета eventsCalendar:
[+stat.days+]
Количество дней выборки
[+stat.days.text+]
Подпись к дням.
[+stat.date+]
Дата в заданном формате.
[+stat.host+]
Количество уникальных посещений за день (хосты).
[+stat.hit+]
Количество не уникальных посещений за день (хиты).
Ссылки на нужные сайты.
Багрепорты засылать на bezumkin@yandex.ru, или оставлять в этой теме.