Dubrowsky
Хроники одного дупла
Блогово  →  WebDev  → 

Обработка кликов и цели в Яндекс.Метрике, улучшенный вариант

15 Февраля 2013 года

А я тут, пока писал про открытие внешних ссылок в новом окне при помощи JS, вспомнил еще, что у меня был пост про цели в Яндекс.Метрике. Хороший и годный пост, но я уже довольно давно использую немного другой подход. Общую идею смотрите по ссылке выше, она не изменилась, а вот в код обработки я внес пару улучшений, они под катом.

Напомню, код из прошлого поста выглядел вот так:

$(document).ready( function() {
	$('.metrika').click( function() {
		var goal_name = this.className.match(/metrika_([^\s]+)/)[1];
		yaCounter123123123.reachGoal(goal_name);
		return true;
	});
})

Проставляем для блоков, клики по которым мы засчитываем как достижение цели, классы вида class="metrika metrika_cart_click", и в статистике начинаем наблюдать конверсии.

У этого кода есть два недостатка. Во-первых, в него зашит идентификатор счетчика, и надо его каждый раз править для нового сайта. Если сайтов выпускается много, между ними будет кочевать неисправленный, а значит неработающий код.

Придуманный мной workaround исключительно туп, однако работает. Вряд ли Яндекс обновит код так, что переменная, содержащая объект-счетчик, перестанет попадать под шаблон "yaCounter11111", так что можно использовать вот такую функцию:

function metrikaReach(goal_name) {
	for (var i in window) {
		if (/^yaCounter\d+/.test(i)) {
			window[i].reachGoal(goal_name);
		}
	}
}

Еще один бонус - возможность обрабатывать события сразу несколькими счетчиками (что редко бывает, но теоретически возможно). Если мы обрабатываем редкие события типа кликов, обход всех "глобальных" переменных и сопоставление с регуляркой не должны занимать много времени. Если в вашем случае события могут возникать чаще, допишите кэш :)

Во-вторых, обработчики в старом коде вешались на найденные при загрузке документа блоки, соответственно не работали для контента, подгруженного аяксом. За примером далеко ходить не надо - тут на блогове после отправки коммента список комментов обновляется аяксом. Чтобы отлавливать клики по внешним ссылкам внутри комментов я, собственно, и переделал скрипт. Нам на помощь приходит jQuery с конструкцией "$('body').on(event)". 

$('body').on('click', '.metrika', function() {
	var goal_name = this.className.match(/metrika_([^\s]+)/);
	if (goal_name[1]) {
		metrikaReach(goal_name[1]);
	}
	return true; 
});

 Например, поставили мы со своего бложека ссылку на сериалы онлайн бесплатно без регистрации, и хотим выяснить, кто и сколько по ней кликает. Наша последовательность действий:

  1. Добавить ссылке класс с кодом цели: <a class="metrika metrika_serial_click">сериалы...</a>
  2. Завести цель в интерфейсе Яндекс.Метрики (кстати, раньше приходилось использовать не совсем логичный вариант "URL содержит...", теперь есть специальный тип цели "Событие"). Вот картинка:
  3. Через какое-то время начинаем видеть интересующие нас сессии под вкладкой "Конверсии" в интерфейсе счетчика.

На всякий случай еще раз поясню: простановка классов и дальнейшая ловля кликов - это быстрый и удобный способ организации отслеживания целей в Яндекс.Метрике, но не единственный. Используя чуть-чуть головы, JavaScript и приведенный выше код, можно фиксировать и более сложные события.

Для затравки: вот кусок кода, который создает событие счетчика, когда юзер набрал в поле отправки комментария текст больше 10 символов:

$('body').on('keyup.comment_writer', '#inp_text_comment_form', function() {
	// если напечатали больше 10 символов
	if ($(this).val().length > 10) {
		// отправляем событие
		metrikaReach('comment_writer');
		// и снимаем обработчик
		$('body').off('keyup.comment_writer');
	}
});

Ясное дело, потом это нужно отсматривать вебвизором :) Могу в комментах придумать код, который будет отлавливать ваши идеи для целей, спрашивайте :)

Камменты

DrJeans15.02.2013, 14:42#
Дубр, годный код!
Иван07.03.2013, 06:10#
Как насчёт цели - когда пользователь копирует в буфер обмена текст более 500 знаков? ;)
Владимир15.09.2013, 13:46#
Подскажите пожалуйста, а можно ли подобным способом собирать данные по клику на кнопки, т.е. чтобы цель срабатывала на
input type="submit" id="payStep" .....
Алексей19.04.2014, 23:29#
А этот код можно до кода метрики ставить? А то что-то у меня не работает :(
Алексей19.04.2014, 23:38#
И не нужно ли ни на что заменять goal_name[1]?
Если целей несколько, то код можно написать как:

$('body').on('click', '.metrika', function() {
var goal_name = this.className.match(/metrika_([^s]+)/);
if (goal_name[1]) {
metrikaReach(goal_name[1]);
}
if (goal_name[2]) {
metrikaReach(goal_name[2]);
}
if (goal_name[3]) {
metrikaReach(goal_name[3]);
}
return true;
});

??? Подскажите, пожалуйста.
Дуброн самый24.04.2014, 04:33#
Алексей, привет!

1. Код нужно вставлять после подключения jQuery. Обращение к Метрике происходит только в момент клика, так что пофигу, подключена метрика до или после - когда юзер кликнет, в любом случае все уже будет загружено.

2. В goal_name[1] попадает идентификатор цели, который вытаскивается из имени класса. Если юзер кликнул по блоку с class="metrika_ololo", будет отправлена команда на достижение цели "ololo". Чтобы на самом деле что-то произошло, цель с таким кодом должна быть предварительно заведена в интерфейсе Метрики (см. скрин).
koreash10.11.2015, 14:06#
Ваш способ не работает. Все перепробовал, данные не передаются.
koreash10.11.2015, 14:13#
Все сработало. Дело было в библиотеке jquery.js. jquery.min.js - не подходит! jquery.js - подходит!
Kolotun Bobo28.11.2015, 18:32#
Спасибо тебе, добрый человек! Отличное решение!
Владимир11.02.2016, 06:57#
"div class="form_ok">

Спасибо за заявку! Наш менеджер свяжется с вами в ближайшее время!

Олег09.06.2016, 15:29#
Добрый день. Спасибо за решение.
Подскажите, в чем у меня косяк?
Обработчик ошибок (FireFox) пишет:
TypeError: goal_name is null
В Chrome
Uncaught TypeError: Cannot read property '1' of null

Использовал этот код:
Олег09.06.2016, 15:30#
Обрезался код в предыдущем сообщении:
function metrikaReach(goal_name) {
for (var i in window) {
if (/^yaCounterd+/.test(i)) {
window[i].reachGoal(goal_name);
}
}
}
$(document).ready( function() {

$('body').on('click', '.metrika', function() {
var goal_name = this.className.match(/metrika_([^s]+)/);
if (goal_name[1]) {
metrikaReach(goal_name[1]);
}
return true;
});

});
Андрей15.07.2016, 12:21#
проверь класс у элемента на которое вешаешь событие.
в классах должен быть класс metrika_...
Вячеслав17.04.2017, 16:31#
Пытаюсь создать событие - прокрутка страницы до появления начала таблицы.
Само событие прокрутки до появления таблицы я добился. А вот запустить событие Метрики нет. Идентификатор на это событие в Метрике тоже price-service
Вот мой код с попыткой сделать его с вашим кодом.

Вячеслав17.04.2017, 16:32#
function metrikaReach(goal_name) {
for (var i in window) {
if (/^yaCounterd+/.test(i)) {
window[i].reachGoal(goal_name);
}
}
}

function checkViewport() {
var $myElement = document.getElementById("price-service"),
landmark = $myElement.getBoundingClientRect(),
visibility = landmark.top + $myElement.scrollHeight > 0 && landmark.left + $myElement.scrollWidth > 0 && landmark.bottom - $myElement.scrollHeight < document.documentElement.clientHeight && landmark.right - $myElement.scrollWidth < document.documentElement.clientWidth
return visibility

}

var AlreadyDone = false;

window.onscroll = function() {
$('body').on('scroll', '#price-service', function() {
if ( !AlreadyDone && checkViewport() ) {
metrikaReach('price-service')
return true
})
alert('Событие выполнено')
AlreadyDone = true
$('body').off('scroll')
}
}
Вячеслав17.04.2017, 16:33#
ну и таблица в теге table имеет id="price-service"
Вячеслав17.04.2017, 16:37#
Во, вот так хотя бы alert выводится при появлении таблицы.
Но событие в Метрике не фиксируется.

window.onscroll = function() {
if ( !AlreadyDone && checkViewport() ) {
$('body').on('scroll', '#price-service', function() {
metrikaReach('price-service')
return true
})
alert('Событие выполнено')
AlreadyDone = true
$('body').off('scroll')
}
}
Дубр17.04.2017, 18:11#
Привет!
1) код лучше запостить куда-нибудь на https://gist.github.com
2) а зачем вызов метрики оборачивать вот в это:

$('body').on('scroll', '#price-service', function() {

Так вы добавляете еще один обработчик на событие scroll, если его target вложен в таблицу (сработает например если внутри таблицы есть див со скроллбарами).

https://gist.github.com/dubrowsky/0b07fa5e60029a13565f6497effa8ab0 - попробуйте так - я не тестил, но снабдил комментами )))
Вячеслав17.04.2017, 21:43#
То что вы там запостили это вместо последнего куска? Остальное также?
Вячеслав17.04.2017, 21:53#
Вашу версию вставил.
Даже alert проверочный выводится.
Т.е. строчка, которая должна отправлять событие в Метрику не работает.
Вячеслав17.04.2017, 21:53#
вот http://www.totalat.ru/service/remont-akpp-bmw/
Дуброн самый18.04.2017, 13:43#
Вячеслав, блин, я там скобку потерял =)
Обновил, попробуйте еще раз: https://gist.github.com/dubrowsky/0b07fa5e60029a13565f6497effa8ab0
Vadim Guk21.05.2017, 14:06#
Большое спасибо за решение задачи.

Написать коммент: памятка постеру

 

Крутые посты wtf??? →

27.06.2012 · 37 камментов · рейтинг 12.02
14.07.2017 · 1 каммент · рейтинг 11.85
23.01.2013 · 20 камментов · рейтинг 9.39
06.03.2008 · 29 камментов · рейтинг 7.83
28.03.2008 · 23 каммента · рейтинг 6.99

Поисковый спам

Последне камменты

20.07.2017  СергейСвязь: Здравствуйте. Хочу предложить Вам тройной обмен п...
17.07.2017  Илья АрхипкинСколько журналистов в России?: Мне рассказывали как журналисты освещали акцию в К...
21.05.2017  Vadim GukОбработка кликов и цели в Яндекс.Метрике, улучшенный вариант: Большое спасибо за решение задачи.
20.05.2017  ДмитрийТестовое задание для PHP-программиста (Junior): А джуны ещё нужны у вас в компании?
18.04.2017  ДубрОбработка кликов и цели в Яндекс.Метрике, улучшенный вариант: Вячеслав, блин, я там скобку потерял =) Обновил, ...

Статсы