AJAX, WordPress и счётчики: пишем свой плагин AJAX Яндекс.Метрика, отражаем AJAX-переходы в счётчике
В этой заметке опишу свой опыт по регистрации AJAX действий в счётчике Яндекс.Метрика, а также приведу пример использования замыканий в PHP при разработке плагинов WordPress.
Итак, задача максимально проста. Если мы какой-либо контент подгружаем через AJAX (пример — “Докатился до AJAX, или WordPress + AJAX + jQuery: загружаем продолжение статьи (после <!—more—>)”), было бы правильным отразить этот факт и в счётчике / счётчиках. Поэтому и решил для начала написать простенький jQuery плагин, являющийся точкой интерфейса между счётчиками и генераторами AJAX событий. Итак:
jQuery плагин jQuery.AJAX.counters
А вот и его код:
jQuery.fn.AJAXCounters = function(method, arg) { var methods = { bind: function(id, counter) { $('body') .delegate( '', 'hit.counter.' + id, { url: $(location).attr('href'), title: $(document).attr('title'), referrer: $(document).attr('referrer'), params: {} }, function (e, params) { params = $.extend(e.data, params); if ($.isFunction(counter.hit)) counter.hit(params.url, params.title, params.referrer, params.params); return true; } ) .delegate( '', 'reachGoal.counter.' + id, { target: '', params: {} }, function (e, params) { params = $.extend(e.data, params); if ($.isFunction(counter.reachGoal)) counter.reachGoal(params.target, params.params); return true; } ) ; return this; }, unbind: function(id) { $('body').undelegate(id); return this; }, hit: function(params) { $('body').trigger('hit.counter', params); return this; }, reachGoal: function(params) { $('body').trigger('reachGoal.counter', params); return this; } }; if ( methods[method] ) { return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 )); } else if ( typeof arg === 'object' ) { return methods.bind( method, arg ); } else { $.error( 'Метод "' + method + '" не найден в плагине jQuery.AJAXcounters' ); }; }; jQuery( function() { jQuery().AJAXCounters('hit'); });
Как видно, наш простенький плагин сам после загрузки документа заставит “сработать” (hit) все установленные через него счётчики (последние 3 строки кода). Наш плагин предоставляет ряд методов. В том числе bind
и unbind
, ну и hit
(ради него всё и начиналось). При регистрации обработчиков событий мы используем namespace события в терминологии jQuery, что существенно облегчает нам “отвязывание” счётчика (именно благодаря namespace код метода unbind
настолько краток).
Использование механизма событий jQuery дало возможность другим плагинам взаимодействовать с нашим, не вызывая напрямую наши методы и не проверяя вообще доступности нашего API. Достаточно для изменённого элемента просто сгенерировать событие:
$(this).trigger('hit.counter');
Именно так и действуют мои AJAX плагины.
Регистрируем Yandex.Metrika через собственный jQuery плагин
А вот и пример использования выше приведённого плагина:
jQuery().AJAXCounters( 'YaMetrika', new Ya.Metrika({ id: YaMetrikaConfig.ua, defer: true, accurateTrackBounce: true }) );
По сути – один вызов, и счётчик Яндекс.Метрики инициализирован и привязан не только к “статическим”, но и к AJAX событиям. Первым параметром мы передаём наш личный id на ресурсе Яндекс.Метрики (скажем – id счётчика). Как мы его передаём из php в JS – увидим далее.
Также кратко будет выглядеть и “привязывание” Google Analytics. А что делать, если счётчик имеет иное API, либо мы хотим свой счётчик использовать? Ничего сложного. Ниже пример регистрации собственного счётчика, который на самом деле просто выбрасывает alert на экран:
jQuery().AJAXCounters( 'test', { hit: function () { alert('test'); } });
Выше приведённый код удобно использовать при отладке, в частности.
По сути – всё. Теперь приведу PHP код самого плагина ради двух задач: передача id счётчика клиенту, а также – демонстрация использования PHP замыканий при разработке интерфейса в консоли управления WordPress.
PHP, замыкания, и плагин AJAX.Counters
Начну сразу с кода:
<?php $ajax_yandex_metrika_cfg = array( 'name' => '', 'ver' => '2.0.0', 'namespace' => 'ajax_yandex_metrika', 'folder' => dirname(plugin_basename(__FILE__)), 'domain' => dirname(plugin_basename(__FILE__)), 'path' => WP_PLUGIN_DIR . '/' . dirname(plugin_basename(__FILE__)) . '/', 'url' => WP_PLUGIN_URL . '/' . dirname(plugin_basename(__FILE__)) . '/', 'options' => array(), 'options_id' => 'YandexMetrikaPP', 'options_page_id' => 'ajax_yandex_metrika_options_page' ); function ajax_yandex_metrika_validate_options($options) { if (!is_array($options)) { $options = array(); }; if ($options['position'] != 'footer') $options['position'] = 'head'; return $options; } if (is_admin()) { include_once('admin\admin.php'); }; add_action('init', function () { global $ajax_yandex_metrika_cfg; $pluginDIR = $ajax_yandex_metrika_cfg['path']; $pluginURL = $ajax_yandex_metrika_cfg['url']; if(!is_admin()) { $ajax_yandex_metrika_cfg['options'] = ajax_yandex_metrika_validate_options( get_option($ajax_yandex_metrika_cfg['options_id']) ); $ua = $ajax_yandex_metrika_cfg['options']["uastring"]; $script_pos = ( 'footer' == ($ajax_yandex_metrika_cfg['options']['position']) ); if (($ua != "") && (!current_user_can('edit_users') || $options["admintracking"]) && !is_preview()) { // if (true) { //for debug wp_register_script( 'jquery.ajax.counters', $pluginURL . "jquery/ajax/counters/jquery.ajax.counters.js", array('jquery'), $ajax_yandex_metrika_cfg['ver'], $script_pos ); wp_register_script( 'yandex.metrika', 'http://mc.yandex.ru/resource/watch.js', array(), $ajax_yandex_metrika_cfg['ver'], $script_pos ); wp_register_script( 'ajax-yandex-metrika', $pluginURL . "ajax-yandex-metrika.js", array('jquery', 'yandex.metrika', 'jquery.ajax.counters'), $ajax_yandex_metrika_cfg['ver'], $script_pos ); wp_enqueue_script('jquery.ajax.counters'); wp_enqueue_script('yandex.metrika'); wp_enqueue_script('ajax-yandex-metrika'); wp_localize_script( 'ajax-yandex-metrika', 'YaMetrikaConfig', array( 'ua' => $ua )); }; }; }); ?>
Ну, во-первых, мы выделили весь код, касающийся консоли управления, в файл admin.php. И грузим его только при необходимости (что правильно с точки зрения производительности). Во-вторых, обратите внимание на вызов wp_localize_script
. Именно данный код и формирует фрагмент javascript кода на нашей странице, через который мы передаём параметры нашему подгружаемому javascript коду. Выглядит сформированный код следующим образом:
<script type='text/javascript'>/* */ var YaMetrikaConfig = { ua: "5009335" }; /* */</script>
Да, можно идти другим путём, и генерировать javascript файл через php, включая необходимые параметры прямо в файл сценария. Но в ряде случаев предложенное выше решение вполне устраивает.
Также можно не “подключать” watch.js непосредственно в html, а реализовать подключиние через наш javascript файл (чтобы сэкономить несколько десятков байт в html коде). Пример читаем в справке Яндек.Метрики. (Подробное описание API счётчика Вы можете почитать здесь).
А теперь — к admin.php и лямбда-функциям:
<?php register_deactivation_hook ( $AJAX_Yandex_metrika, function () { global $ajax_yandex_metrika_cfg; unregister_setting( $ajax_yandex_metrika_cfg['namespace'], $ajax_yandex_metrika_cfg['options_id'] ); }); register_uninstall_hook ( $AJAX_Yandex_metrika, 'ajax_yandex_metrika_uninstall'); function ajax_yandex_metrika_uninstall() { global $ajax_yandex_metrika_cfg; delete_option( $ajax_yandex_metrika_cfg['options_id'] ); }; add_action ('init', function () { global $ajax_yandex_metrika_cfg; $ajax_yandex_metrika_cfg['options'] = ajax_yandex_metrika_validate_options( get_option($ajax_yandex_metrika_cfg['options_id']) ); load_plugin_textdomain( $ajax_yandex_metrika_cfg['domain'], false, $ajax_yandex_metrika_cfg['folder'] . '/languages/' ); $ajax_yandex_metrika_cfg['name'] = __('AJAX Yandex Metrika', $ajax_yandex_metrika_cfg['domain']); add_action('admin_init', function () { global $ajax_yandex_metrika_cfg; register_setting( $ajax_yandex_metrika_cfg['namespace'], $ajax_yandex_metrika_cfg['options_id'], 'ajax_yandex_metrika_validate_options' ); add_settings_section( $ajax_yandex_metrika_cfg['namespace'] . '_main_options', __('Main Settings', $ajax_yandex_metrika_cfg['domain']), function () { global $ajax_yandex_metrika_cfg; ?> <p> <?php _e('You must obtain UID from <a href="http://metrika.yandex.ru/">yandex.metrika</a> and set it in the UID field.', $ajax_yandex_metrika_cfg['domain']); ?> </p> <?php }, $ajax_yandex_metrika_cfg['options_page_id'] ); add_settings_field( $ajax_yandex_metrika_cfg['options_id'] . '[uastring]', __('Yandex.Metrika UID', $ajax_yandex_metrika_cfg['domain']), function () { global $ajax_yandex_metrika_cfg; ?> <label> <input name="<?php echo $ajax_yandex_metrika_cfg['options_id'] . '[uastring]' ?>" type="text" maxlength="40" style="width: 100%" value="<?php echo $ajax_yandex_metrika_cfg['options']['uastring']; ?>" /> <br/><?php _e('Your Yandex.Metrika UID.', $ajax_yandex_metrika_cfg['domain']); ?> </label> <?php }, $ajax_yandex_metrika_cfg['options_page_id'], $ajax_yandex_metrika_cfg['namespace'] . '_main_options' ); add_settings_field( $ajax_yandex_metrika_cfg['options_id'] . '[position]', __('Code in the head', $ajax_yandex_metrika_cfg['domain']), function () { global $ajax_yandex_metrika_cfg; ?> <div> <label> <input type="radio" name="<?php echo $ajax_yandex_metrika_cfg['options_id'] . '[position]' ?>" value="head" <?php checked( $ajax_yandex_metrika_cfg['options']['position'], 'head' ); ?> /> <?php _e('At the begin of pages (wp_head), when wp_footer isn`t used in the theme.', $ajax_yandex_metrika_cfg['domain']) ?> </label> </div> <div> <label> <input type="radio" name="<?php echo $ajax_yandex_metrika_cfg['options_id'] . '[position]' ?>" value="footer" <?php checked( $ajax_yandex_metrika_cfg['options']['position'], 'footer' ); ?> /> <?php _e('At the end of pages (wp_footer), by default.', $ajax_yandex_metrika_cfg['domain']) ?> </label> </div> <?php }, $ajax_yandex_metrika_cfg['options_page_id'], $ajax_yandex_metrika_cfg['namespace'] . '_main_options' ); }); add_action('admin_menu', function () { global $ajax_yandex_metrika_cfg; add_options_page( __('AJAX Yandex.Metrika', $ajax_yandex_metrika_cfg['domain']) , __('AJAX Yandex.Metrika', $ajax_yandex_metrika_cfg['domain']) , 'manage_options' , $ajax_yandex_metrika_cfg['options_page_id'] , function () { global $ajax_yandex_metrika_cfg; ?> <div class="wrap"> <?php screen_icon('options-general'); ?> <h2><?php _e('AJAX Yandex.Metrika options', $ajax_yandex_metrika_cfg['domain']) ?></h2> <form method="post" action="options.php"> <?php settings_fields($ajax_yandex_metrika_cfg['namespace']); do_settings_sections($ajax_yandex_metrika_cfg['options_page_id']); ?> <p class="submit"> <input name="Submit" type="submit" class="button-primary" value="<?php _e('Save Changes') ?>" /> </p> </form> </div> <?php } ); }); }); ?>
Как видно, в таком варианте проблема с пространством имён для функций плагина решается просто отсутствием имён как таковых. Да и код становится более читаемым, не приходится бегать по файлу вверх-вниз в тщетных попытках понять идею автора.
P.S. Замыкания я не использовал сознательно, ограничился лямбда функциями. Дело в том, что мне требуется взаимодействие функционалов с одним разделяемым объектом параметров плагина, а не создание фиксированной копии параметров для каждого функционала в момент создания функционала. Посему замыкания здесь были бы вредны.
Качайте плагин AJAX Yandex.Metrika из репозитория WordPress и используйте его в своё удовольствие!
P.S. Текущая версия плагина (2.0.0) требует от Вас самостоятельной регистрации на Яндексе, получении id счётчика а также самостоятельного подтверждения прав на сайт. Однако, Яндекс.Метрика предоставляет API с авторизацией по OAuth 2.0, с помощью которого можно автоматизировать процесс регистрации счётчика и подтверждения прав на сайт. Уж очень хочется попробовать реализовать полноценное взаимодействие по oAuth 2.0 и сделать плагин совсем для ленивых. Жаль, что пока что Яндекс.Метрика не поддерживает авторизации по OpenId, а то можно было бы и войти с правами текущего пользователя WordPress сайта…
Ну и кроме выше описанного также имеет смысл добавить в dashboard свой виджет с данными с Яндекс.Метрики.
Отзывы » (11)
RSS комментарии
Обратная ссылка
Добрый день, Сергей.В репозитарии WordPress на странице с вашим плагином AJAX Yandex.Metrika указана неправильная ссылка на ваш блог: For more information, please visit the Sergey S. Betke blog: http://sergey-s-betke.blogs.novgaro.ru/category/it/web/wordpress/ajax-yandex-metrika
shserg.ru » Спасибо за замечание! readme.txt в репозитории уже заменил, ссылка должна измениться в ближайшее время.
P.S. менял структуру рубрик на сайте — вот и допустил ошибку. Ещё раз — спасибо.
Здравствуйте! Спасибо за чудесный плагин. Попробовал его установить, но не нашел, где в итоге вводить настройки после его активации. В параметрах раздела с настройками плагина не нашел… помогите, пожалуйста, разобраться.
Андрей, плагин прост на самом деле. А настройки — в Настройки | AJAX Yandex.Metrika. Если возникнут сложности — пишите, помогу
При попытке установить плагин, скачанный с репозитория на wprdpress.org версия плагина 2.1.0, версия движка 3.3.1 при активации вылазит следующая ошибка:
Parse error: syntax error, unexpected T_FUNCTION in /путь/wp-content/plugins/ajax-yandexmetrika/ajax-yandex-metrika.php on line 54 и активация не происходит
Мария, на текущий момент плагин требует php 5.3 и старше. Он пока ещё в процессе разработки.
Когда же будет обновлен плагин?
Евгений, он прекрасно работает на php 5.3. Вы просите версию для 5.2? указанная выше ошибка возникает на php 5.2.
Скриншоты бы, как он визуально в действии выглядит не помешали.
Согласен, Сергей, учту.
А для новой метрики подходит плагин? А то там изменился код. Спасибо.