var quickSearchEventTracking = (function () { // Configs var config = { clickTrackingContainer: '.quicksearch-ga-click-tracking', serveTrackingContainer: '.quicksearch-ga-serve-tracking', testingContainer: '#quicksearch-ga-debug', seeAllClass: 'see-all-results', categoryDataAttribute: 'quicksearch-ga-category', actionDataAttribute: 'quicksearch-ga-action', labelDataAttribute: 'quicksearch-ga-label', logQueryDataAttribute: 'quicksearch-ga-query' } // Public Methods function listenForClicks () { $(document).on('click', config.clickTrackingContainer + ' a', function(e) { var eventValuesDefined = eventValues($(this)); var link = $(this)[0]; // This ensures that ctrl and cmd click to open // link in a new window/tab continues to function. // No need to preventDefault in this case // because the original page remains. if (e.metaKey || e.ctrlKey) { sendEventData(eventValuesDefined, ''); return; } else { sendEventData(eventValuesDefined, link); e.preventDefault(); } // In case the hitCallback isn't triggered soon enough we ensure the link is followed // after this timeout in any case. setTimeout(function() { document.location.href = link.href; }, 200); }); } function listenForServesOnPageChange () { $(document).ready(function() { serveTrackingDivs = $(config.serveTrackingContainer).get(); $.map(serveTrackingDivs, function(val) { checkForServes(val); }); }); } function checkForServes(val) { var link = $(val).find('a'); var eventValuesDefined = eventValues(link); eventValuesDefined.category = eventValuesDefined.category + '-serve'; sendEventData(eventValuesDefined, ''); } // Private Methods function eventValues (link) { var link = link; var ga_event = {}; ga_event.category = eventCategory(link); ga_event.action = eventAction(link); ga_event.label = eventLabel(link); return ga_event; } function eventCategory (link) { // FIXME: There may be a better way to get the action from the parent. var category; if (link.data(config.categoryDataAttribute)) { category = link.data(config.categoryDataAttribute); } else if (link[0].id.length > 0) { category = link[0].id; } else { category = link.parents('[id]:first')[0].id; } return category; } function eventAction (link) { var action; if (link.data(config.actionDataAttribute)) { action = link.data(config.actionDataAttribute); } else if (link.hasClass(config.seeAllClass)) { action = 'see-all-results'; } else if (link.parent('h1,h2').length > 0) { action = 'heading'; } else { index = link.parents('li').index() result = index + 1 action = 'result-' + result; } return action } function eventLabel (link) { var label; if (link.data(config.labelDataAttribute)) { label = link.data(config.labelDataAttribute); } else if (link.parents('body').data(config.logQueryDataAttribute)){ label = link.parents('body').data(config.logQueryDataAttribute); } else { label = link[0].href; } return label; } function sendEventData (eventValues, link) { <% if Rails.env == 'development' %> console.log('click_tracking', [eventValues.category, eventValues.action, eventValues.label]); $.when(logEventToDatabase(eventValues)).then(function () { if (link !== '') { //document.location.href = link; } }); <% elsif Rails.env == 'production' or Rails.env == 'staging' %> $.when(logEventToDatabase(eventValues)).then(function () { sendDataToGoogleAnalytics(eventValues, link) }); <% else %> appendTestingData(eventValues); <% end %> } function appendTestingData (eventValues) { var debugBlock = $(config.testingContainer); var debugList = $(config.testingContainer + ' ol'); debugList.empty(); $.map (eventValues, function(val) { debugList.append('
  • ' + val + '
  • '); }); debugBlock.show(); } function sendDataToGoogleAnalytics (eventValues, link) { // Universal Analytics // ga('send', 'event', { // 'hitType': 'event', // 'eventCategory': eventValues.category, // 'eventAction': eventValues.action, // 'eventLabel': eventValues.label, // 'hitCallback': function () { // if (link !== '') { // document.location = link; // } // } // }); // Classic Analytics _gaq.push(['_set','hitCallback',function() { if (link !== '') { document.location = link; } }]); _gaq.push(['_trackEvent', eventValues.category, eventValues.action, eventValues.label]); } function logEventToDatabase(eventValues) { url = logging_url('log_event'); return $.ajax({ url: url, data: { category: eventValues.category, event_action: eventValues.action, label: eventValues.label } }); } function checkForSearch() { if ($('body').data(config.logQueryDataAttribute)) { var query = $('body').data(config.logQueryDataAttribute); if (query != '') { searchValuesDefined = searchValues(query); logSearchToDatabase(searchValuesDefined); } } } function searchValues (query) { var link = link; var ga_search = {}; ga_search.query = query; ga_search.page = searchPage(); return ga_search; } function searchPage() { var pathname = window.location.pathname; // Get the pathname relative to the application root return pathname.replace("<%= ActionController::Base.relative_url_root || '' %>", ""); } function logSearchToDatabase(searchValues) { console.log(searchValues); url = logging_url('log_search'); return $.ajax({ url: url, data: { query: searchValues.query, page: searchValues.page } }); } function logging_url(log_path) { var pathname = window.location.pathname; var url = pathname; if (url.substr(-1) != '/'){ url += '/'; } url += log_path; return url; } return { // Expose Public Methods listenForClicks: listenForClicks, listenForServesOnPageChange: listenForServesOnPageChange, checkForServes: checkForServes, checkForSearch: checkForSearch }; })(); $( document ).ready(function() { quickSearchEventTracking.checkForSearch(); if ($("body").hasClass("search-index")) { quickSearchEventTracking.listenForClicks(); quickSearchEventTracking.listenForServesOnPageChange(); } });