Анализ Rage Clicks (многократные клики по неработающим элементам)
Rage Click — 3 и более клика в одну точку за короткое время (обычно < 1 секунды). Сигнализирует о разочаровании пользователя: он ожидает реакции от элемента, а её нет.
Типичные причины rage clicks
- Кнопка или ссылка визуально выглядит кликабельной, но не реагирует
- JavaScript ошибка сломала обработчик клика
- Анимация кнопки не даёт обратной связи (нет cursor: pointer, нет hover-состояния)
- Долгая загрузка — пользователь кликает повторно думая что клик не прошёл
- Декоративный элемент похож на функциональный
Настройка обнаружения в Microsoft Clarity
Clarity автоматически выявляет rage clicks и показывает:
- Страницы с наибольшим числом rage click сессий
- Конкретные координаты на странице
- Записи сессий с rage clicks для просмотра
Кастомный детектор rage clicks
class RageClickDetector {
constructor(threshold = 3, timeWindow = 500) {
this.threshold = threshold
this.timeWindow = timeWindow
this.clicks = []
this.maxDistance = 30 // пикселей
document.addEventListener('click', this.handleClick.bind(this))
}
handleClick(event) {
const now = Date.now()
const { clientX, clientY, target } = event
// Очистить старые клики
this.clicks = this.clicks.filter(c => now - c.time < this.timeWindow)
// Проверить близость к предыдущим кликам
const nearbyClicks = this.clicks.filter(c =>
Math.abs(c.x - clientX) < this.maxDistance &&
Math.abs(c.y - clientY) < this.maxDistance
)
nearbyClicks.push({ x: clientX, y: clientY, time: now })
this.clicks.push({ x: clientX, y: clientY, time: now })
if (nearbyClicks.length >= this.threshold) {
this.onRageClick(event, nearbyClicks.length)
}
}
onRageClick(event, clickCount) {
const element = event.target
const selector = this.getSelector(element)
console.warn(`Rage click detected: ${selector} (${clickCount} clicks)`)
// Отправить в аналитику
gtag('event', 'rage_click', {
element_selector: selector,
click_count: clickCount,
page_path: window.location.pathname,
element_text: element.textContent?.trim().slice(0, 50)
})
// Если нет cursor: pointer — возможная проблема
const cursor = window.getComputedStyle(element).cursor
if (cursor !== 'pointer' && element.tagName !== 'A' && element.tagName !== 'BUTTON') {
gtag('event', 'non_pointer_rage_click', {
element_selector: selector,
computed_cursor: cursor
})
}
}
getSelector(el) {
if (el.id) return `#${el.id}`
if (el.className) return `.${el.className.split(' ')[0]}`
return el.tagName.toLowerCase()
}
}
new RageClickDetector()
Анализ rage click данных
def analyze_rage_clicks(analytics_db, days=30):
results = analytics_db.query(f"""
SELECT
element_selector,
COUNT(*) as rage_click_events,
COUNT(DISTINCT session_id) as affected_sessions,
AVG(click_count) as avg_clicks,
MIN(page_path) as example_page
FROM events
WHERE event_name = 'rage_click'
AND date >= CURRENT_DATE - INTERVAL '{days} days'
GROUP BY element_selector
ORDER BY affected_sessions DESC
LIMIT 20
""")
print("Top rage click targets:")
for row in results:
print(f" {row['element_selector']}: "
f"{row['affected_sessions']} sessions, "
f"avg {row['avg_clicks']:.1f} clicks")
return results
Исправление проблем
-
Кнопка без feedback: добавить
cursor: pointer, hover-состояние, активное состояние:
.btn { cursor: pointer; transition: opacity 0.1s; }
.btn:hover { opacity: 0.9; }
.btn:active { transform: scale(0.98); }
.btn:disabled { cursor: not-allowed; opacity: 0.5; }
- Долгая обработка: показать loader после клика:
button.addEventListener('click', async function() {
this.disabled = true
this.textContent = 'Загрузка...'
await processOrder()
this.textContent = 'Готово!'
})
Срок выполнения
Настройка детектора rage clicks, анализ данных и исправление топ-5 проблем — 1–2 рабочих дня.







