Идентификация кликов в PHP: практические решения
Основные методы передачи ID клика в PHP
Наиболее эффективным способом получения идентификатора клика на сервере PHP является асинхронная отправка данных через JavaScript с использованием Fetch API. Этот метод не прерывает взаимодействие пользователя и позволяет передавать произвольные данные в реальном времени. Предположим, на странице есть элементы с атрибутом data-click-id. При клике через JavaScript формируется POST-запрос к скрипту track.php, который принимает и сохраняет идентификатор. Пример кода на стороне клиента:
document.addEventListener('click', function(e) {
var target = e.target.closest('[data-click-id]');
if (target) {
var clickId = target.getAttribute('data-click-id');
fetch('track.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ id: clickId })
}).then(response => response.json()).then(data => {
console.log('ID отправлен:', data);
}).catch(err => console.error('Ошибка:', err));
}
});
На сервере PHP скрипт обрабатывает запрос:
<?php
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input['id'])) {
$clickId = htmlspecialchars($input['id'], ENT_QUOTES, 'UTF-8');
// Сохранение в базу данных, лог и т.д.
file_put_contents('clicks.log', date('Y-m-d H:i:s') . ' - ' . $clickId . PHP_EOL, FILE_APPEND);
echo json_encode(['status' => 'ok', 'id' => $clickId]);
} else {
echo json_encode(['status' => 'error', 'message' => 'ID не передан']);
}
?>
Типичные ошибки и их решения:
- Данные не доходят из-за CORS – настройка заголовков
Access-Control-Allow-Originна сервере. - При отправке большого количества кликов возможна перегрузка – используется дебаунсинг или буферизация на клиенте.
- Невалидный JSON – проверка корректности формирования тела запроса.
Как передать ID клика через GET-параметр в ссылке?
Самый простой метод – добавить идентификатор прямо в URL ссылки. При клике пользователь переходит на страницу, и PHP получает ID из параметра $_GET. Пример ссылки:
<a href="track.php?click_id=123" data-click="123">Нажми здесь</a>
На сервере значение извлекается так:
<?php
if (isset($_GET['click_id'])) {
$clickId = filter_input(INPUT_GET, 'click_id', FILTER_SANITIZE_STRING);
// Обработка
}
?>
Проблемы:
- ID виден в строке браузера и может быть подменён или скопирован.
- Переход по ссылке перезагружает страницу, что прерывает сценарий пользователя.
- Невозможно отследить клик без фактического перехода – подходит только для отслеживания переходов.
Как отправить ID клика при помощи скрытой формы и POST?
Метод основан на программном заполнении и отправке скрытой HTML-формы. Клик по элементу инициирует отправку формы с полем, содержащим ID:
<form id="clickForm" method="post" action="track.php" style="display:none;">
<input type="hidden" name="click_id" value="0">
</form>
<button onclick="document.getElementById('clickForm').click_id.value='456'; document.getElementById('clickForm').submit();">Клик</button>
PHP получает данные через $_POST:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['click_id'])) {
$clickId = $_POST['click_id'];
}
?>
Недостатки:
- Вызывает полную перезагрузку страницы, так как форма отправляется синхронно.
- Необходимо обновлять скрытое поле перед каждой отправкой.
- Может возникнуть конфликт с другими формами на странице.
Как отправить ID клика после ухода со страницы без блокировки?
Используется navigator.sendBeacon() – метод отправляет небольшой объём данных асинхронно, даже когда страница выгружается. Пример при клике на ссылку с уходом:
var link = document.querySelector('a[data-click-id]');
link.addEventListener('click', function(e) {
var id = this.getAttribute('data-click-id');
var data = new Blob([JSON.stringify({ id: id })], {type: 'application/json'});
navigator.sendBeacon('track.php', data);
// Уход со страницы не блокируется
});
PHP обработчик остаётся таким же, как в основном решении, но использует php://input.
Особенности:
- Метод работает только с протоколом HTTPS (для некоторых браузеров).
- Невозможно получить ответ от сервера – передача односторонняя.
- Не подходит для передачи больших объёмов данных.
Как передать ID клика через WebSocket в реальном времени?
При использовании WebSocket каждый клик отправляется на сервер немедленно, а сервер может обработать его и отправить подтверждение. Клиентский код:
var socket = new WebSocket('wss://example.com/ws');
socket.onopen = function() {
document.addEventListener('click', function(e) {
var target = e.target.closest('[data-click-id]');
if (target) {
socket.send(JSON.stringify({ type: 'click', id: target.getAttribute('data-click-id') }));
}
});
};
На сервере используется библиотека Ratchet или ReactPHP для обработки WebSocket.
Требования и ограничения:
- Необходим постоянно работающий WebSocket-сервер, что требует дополнительных ресурсов.
- При разрыве соединения данные теряются – требуется механизм повторной отправки.
- Подходит для интерактивных приложений, но избыточен для простого логирования кликов.
Расширенные примеры демонстрируют полную интеграцию методов с хранением данных в базе MySQL и обработкой нескольких кликов.
Пример 1: Сохранение кликов в MySQL с использованием основного метода (Fetch API)
// index.html (упрощённо)
<!DOCTYPE html>
<html>
<head><title>Клик трекер</title></head>
<body>
<button data-click-id="btn1">Кнопка 1</button>
<button data-click-id="btn2">Кнопка 2</button>
<div id="result"></div>
<script>
document.addEventListener('click', function(e) {
var target = e.target.closest('[data-click-id]');
if (target) {
var id = target.getAttribute('data-click-id');
fetch('save_click.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ click_id: id, timestamp: Date.now() })
}).then(r => r.json()).then(d => {
document.getElementById('result').innerText = 'Отправлено: ' + d.click_id;
});
}
});
</script>
</body>
</html>
// save_click.php
<?php
$conn = new mysqli('localhost', 'user', 'pass', 'clicks_db');
if ($conn->connect_error) {
http_response_code(500);
echo json_encode(['error' => 'DB connection failed']);
exit;
}
$data = json_decode(file_get_contents('php://input'), true);
$clickId = $conn->real_escape_string($data['click_id']);
$timestamp = (int)($data['timestamp'] / 1000);
$sql = "INSERT INTO clicks (click_id, created_at) VALUES ('$clickId', FROM_UNIXTIME($timestamp))";
if ($conn->query($sql) === TRUE) {
echo json_encode(['status' => 'ok', 'click_id' => $clickId]);
} else {
http_response_code(500);
echo json_encode(['error' => $conn->error]);
}
$conn->close();
?>
Результат выполнения (если данные успешно сохранены):
{"status": "ok", "click_id": "btn1"}
Пример 2: Использование сессии для объединения кликов одного пользователя
// Сессия создаётся при первом запросе, все клики пишутся в лог сессии
<?php
session_start();
if (!isset($_SESSION['click_ids'])) {
$_SESSION['click_ids'] = [];
}
$data = json_decode(file_get_contents('php://input'), true);
if (isset($data['click_id'])) {
$_SESSION['click_ids'][] = [
'id' => $data['click_id'],
'time' => date('Y-m-d H:i:s')
];
echo json_encode(['session_count' => count($_SESSION['click_ids'])]);
}
?>
При каждом клике возвращается количество кликов в текущей сессии:
{"session_count": 1}
{"session_count": 2}
Пример 3: Обработка кликов на динамически добавляемых элементах с делегированием
// Вешаем обработчик на document – работает для любых новых элементов
<script>
document.addEventListener('click', function(e) {
var item = e.target.closest('.clickable-item');
if (item) {
var id = item.dataset.clickId;
// отправка через fetch
}
});
// Добавление новой кнопки
var newBtn = document.createElement('button');
newBtn.className = 'clickable-item';
newBtn.dataset.clickId = 'dynamic_123';
newBtn.textContent = 'Динамическая кнопка';
document.body.appendChild(newBtn);
</script>
Клик по динамически добавленной кнопке отправляет ID ‘dynamic_123’ без дополнительной привязки обработчика.