') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - returnly/event_tracker: Gem for sharing event-tracking functionality between Rails apps · GitHub
Skip to content

Repository files navigation

EventTracker

For consistent behavioral and event tracking across Rails applications. Supports Mixpanel out of the box, and allows for implementing custom tracker plugins for additional providers.

Installation

Add this line to your application's Gemfile:

gem'event_tracker',git: 'https://www.github.com/returnly/event_tracker'

And then execute:

$ bundle

Usage

Setup

Instantiate a tracker:

tracker=EventTracker::Tracker.new(doer_id,properties)

where properties is a hash with common event properties, e.g. session information. Then, call tracker.track(event_name, event_label, properties):

tracker.track('return.refunded.merchant','Merchant Refunded Return',event_context)

where event_context is a hash with extra information to be merged with the original properties, e.g. a tag that identifies which button triggered the action.

By default, it will use the Development tracker, which simply prints events to the console.

Mixpanel Configuration

Add event_tracker.rb to your config/initialiers directory:

EventTracker.configuredo |config|
config.mixpanel_project_token='yourTokenHere'end

Register your tracker

defmixpanel_tracker@mixpanel_tracker ||= begintracker=EventTracker::Trackers::Mixpanel.new(EventTracker.configuration.mixpanel_project_token)tracker.register_tracker(EventTracker::Trackers::Mixpanel)trackerendend

Adding a custom tracker

Create a Tracker and corresponding Job in your project like so:

my_tracker.rb

moduleEventTrackermoduleTrackersclassMyTracker < EventTracker::Trackers::Basedeftrack(event_name,event_label,properties)EventTracker::Jobs::MyJob.perform_later(@doer_id,event_name,event_label,properties)endendendend

my_job.rb

moduleEventTrackermoduleJobsclassMyJob < EventTracker::Jobs::TrackerJobdefperform(doer_id,event_name,event_label,properties)track(doer_id,event_name,event_label,properties)endprivatedeftrack(*args)# Connect to your custom event-tracking provider here :)endendendend

And to register your new tracker in your project:

defevent_tracker@event_tracker ||= begintracker=EventTracker::Tracker.new(current_user_id,session.to_hash)tracker.register_tracker(EventTracker::Trackers::MyTracker)trackerendend

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/returnly/event_tracker :)

About

Gem for sharing event-tracking functionality between Rails apps

Resources

Stars

2 stars

Watchers

22 watching

Forks

Releases

Packages

Used by

Contributors

Languages