High level utilities for tracking events with Mixpanel in your Rails project.
- Tracking URL params
- External domains exceptions
- Tracking properties priority!!
- Custom sessions using mixpanel superproperty
- Running Jasmine test suite
- License
Add this line to your application's Gemfile:
gem "mixingpanel", github: 'gguerrero/mixingpanel'
And then execute:
$ bundle
## Config
Run this generator to copy the config on your project initializers as mixingpanel.rb
.
$ rails generate mixingpanel:config
This config is based on the official mixpanel configuration, you can have a look at the allowed options.
Once you have your initializer installed you may want to change options:
Mixingpanel.configure do |config|
config.track_pageview = false
config.cross_subdomain_cookie = false
config.cookie_name = "third-party-mp"
config.cookie_expiration = 30
config.track_links_timeout = 100
end
Remember to have a coherence between project options, otherwise the cookie may not be read between projects and it will be a mess to discover why!
For insert the inline JS Mixpanel source code, add the following line on application.html.erb:
<%= include_mixpanel %>
Or if you're using HAML:
= include_mixpanel
For JS, in your application.js add the following line:
//= require mixingpanel
Set up the following environment variables on your project to deal with:
- Mixpanel Secret token:
MIXPANEL_SECRET_TOKEN="xxxxxxxxxxxxxxxxxx"
On a CoffeeScript from your choose, you should initialize and bind the mixingpanel trackings:
$ ->
mixingpanel_tracker = new MixingpanelTracker()
mixingpanel_tracker.register
appname: "MyCoolApp"
device_type: categorizr()
user_logged_in: user_logged_in()
mixingpanel_tracker.bind()
Remember to setup this after the document is ready.
By using these view helpers you'll add all the data attributes required for the Mixingpanel JS to track event on your Mixpanel account.
- Event tracker, launched at JQuery document ready callback. Track as much events as you want to:
<%= event_tracker "Visit homepage", username: current_user.name %>
That will generate the following HTML code:
<div class='mpevent trackme' style='display:none;' data-event='Visit homepage' data-extra-props='{"username":"William"}'></div>
- Link tracker, tracks the event when the link is clicked:
<%= tracked_link_to 'Read Me!', '/readme', 'Click on ReadMe', {username: current_user.name}, {class: "button"} %>
That will generate the following HTML code:
<a href='/readme' class='button trackme' id='tracked_item_1382331238331' data-event='Click on ReadMe' data-extra-props='{"username":"William"}'>
Read Me!
</a>
- Form tracker, tracks the event when the form is submited:
<%= tracked_form_for @user, 'Submit user', {admin: current_user.admin?}, {class: "cool_form"} do |f| %>
<% f.text_field ... %>
<% f.text_field ... %>
<% f.text_field ... %>
<% end %>
That will generate the following HTML code:
<form accept-charset="UTF-8" action="/users/2/edit" class="cool-form" id="tracked_item_138576212213312" method="post" data-event='Submit user' data-extra-props='{"admin":"True"}'>
<...>
<...>
<...>
</form>
The source feature tracks 2 cool superproperties within all your mixpanel events. The default behaviour for tracking sources is:
- If utm_campaign appears in the URL params and the utm_medium param is different than 'email' the source will turn into SEM.
- If utm_medium is 'email', source will turn into Email.
- If the document referer is a search engine and there is no UTM params, the source turns into SEO.
- If the document referer is a social network, source come Social.
- If the document referer is another reference (but never from same domain), the source will be Referral.
- If there is no referer at all and none of the other conditions is true, the source turns into Direct.
As well as any company would like to have it's own way to track sources, you can provide new source mapping and a custom callback within the source is retrieved when the tracker is initialized. For example:
$ ->
mpp = new MixingpanelTracker
source:
values:
SEM_PERMANENT: "SEM Permanent"
SEM_EXPERIMENT: "SEM Experiment"
SEO_GOOGLE: "SEO Google"
SEO_OTHERS: "SEO Others"
callback: ->
if @utm.campaign is "sem_permanent"
@sources.SEM_PERMANENT
else if @utm.campaign is "sem_experiment"
@sources.SEM_EXPERIMENT
else if @utm.medium is "email"
@sources.EMAIL
else if @properties.engine?
if @properties.engine is "google"
@sources.SEO_GOOGLE
else
@souces.SEO_OTHERS
else if @properties.referer != ""
if @properties.isSocial()
@sources.SOCIAL
else
@sources.REFERRAL
else if @properties.referer is ""
@sources.DIRECT
else
undefined
mpp.bind()
If you don't want to automatically append sources on MixingpanelTracker initializer, you could do so with:
$ ->
mpp = new MixingpanelTracker
source:
append: false
# ...
# DO SOME STUFF
# ...
mpp.source.append()
mpp.bind()
Remember to implement all the sources values you want to return as you've override the default behaviour!!
The mixpanel superproperties tracked are:
- first_touch_source set the first user source on your site within an expiration of 30 days. You can change this expiration days value by
mpp = new MixingpanelTracker
source:
firstTouchExpirationDays: 15
- last_touch_source set the current user source on your site.
As extra properties for debug aim:
- first/last_touch_timestamp set the timestamp in the moment of the tracking.
- last_touch_start_session set to true on the first session navigation point, otherwise is false.
- last_touch_utm_* set the
utm
parameters extracted from the URL.
By default Mixingpanel will append the body data attributes under 'mp' on every track, i.e:
$('body').data('mp');
You may set different mixpanel properties from your controller or views by using the helpers provided on the gem add_mixpanel_attributes
, or by manually set the variables @mp_section
, @mp_owner
, @mp_product
, @mp_subproduct
, @mp_item
and @mp_extras
.
So, in your application.html add this:
<body data="<%= { mp: global_mixpanel_attributes } %>">
...
</body>
And on your views and on your controllers:
class ApplicationController
include MixingpanelHelper
end
class UserController < ApplicationController
def index
add_mixpanel_attributes section: "home",
owner: "seo",
product: "insurances",
subproduct: "car insurance",
foo: "bar"
end
end
or
def index
@mp_section = "home"
@mp_owner = "seo"
@mp_product = "insurances"
@mp_subproduct = "car insurance"
@mp_extras = {foo: "bar"}
end
You can even retrieve any of the already set properties with:
mixpanel_attributes
mixpanel_attributes[:product]
mixpanel_attributes[:item]
If you don't want to auto append all this properties on your events add the following config on your Mixingpanel
initializer:
$ ->
mpp = new MixingpanelTracker
appendGlobals: false
# ...
# DO SOME STUFF
# ...
mpp.bind()
This functionality allows you to track URL params as properties on any event. You may create a whitelist of the URL parameters you allow to be tracked. Something you may know about tracking params:
- They will be only be tracked if these params come from an external source, i.e, any source not from your own domain.
- They will stop tracking after you visit your site from another external source that do not contains those params (the cookie that contains the params will be deleted).
- These params will override any other property named equal. So keep in mind that any other tracking that contains a property with the same name that a tracking param, that value, will be written by the value on the tracking params cookie.
To setup your params whitelist you should add them on the tracker initializer like this:
mpp = new MixingpanelTracker
tracking_params: ['foo', 'bar', 'baz']
If you need to track/set a source or URL param in specials cases, even the fact that the referring domain is internal, you can add a list of whitelisted referring domains:
mpp = new MixingpanelTracker
external_domains:
[ 'foo.bar.org', 'baz.bar.org', 'meh.bar.org' ]
Remember, that list checks domains when:
- Adding a source
- Adding URL params for tracking
DO NOT SET IN ANY CASE YOUR OWN DOMAIN ('bar.org' on the example case) OR THE SOURCE WILL BE RECALCULATED ON EVERY PAGE VISIT
Be careful at this point, there are many ways of tracking properties, but they will be merged in order, so maybe you'll find some of then are been override and you won't know why. Properties tracking order is:
For example, you're tracking a property that is already on $('body').data().mp
attributes:
$('body').data.mp
=> Object {foo: 'bar'}
@mixingpanel_tracker.track('Visit page', foo: 'foo')
In the case above, you'll get foo property with bar value on Mixpanel, because the Global body attributes have a more important priority on tracking. Same way will happen with tracking URL params.
You can create a custom session which use mp_session_id superproperty using the query param mp_session_start=YOURSESSIONID
in the url.
This is useful when you are doing tests and want to regroup all your tracking in multiple devices. You can close the custom session with the query param mp_session_end=ANY
.
As these code is writed on CoffeScript, the Jasmine test suite requieres to compile all the specs, source files, helper files and fixtures to JS first, so that's why jasmine/compiler.rb exists. See also Pivotal CI solution
To run the Jasmine test suite server:
$ rake jasmine:coffee
To run the Jasmine test suit as CI:
$ rake jasmine:ci:coffee
This project uses MIT-LICENSE.