I'm attempting to make use of Mixpanel event tracking in a single page site based on Backbone.js and require.js.
Looking at the snippet that Mixpanel provide for cut-and-pasting into a regular webpage, I can tell they've rolled their own async loading mechanism that pulls in the actual Mixpanel API from a standalone resource, do some extra work to setup 'people' and other attributes, and finally expose the 'mixpanel' object through the global namespace.
I've tried to add shim config entries for either the snippet or the standalone API but neither work well.
Through my research, I found a project on github that does exactly what I want, however it's a few years old and is based on the 'old' mixpanel API. In the new version, Mixpanel have made some non-trivial changes to the snippet and API that I just can't get my head around.
I'm hoping somebody understands the Mixpanel snippet and/or AMD and require.js and can step me through this.
There are two funny things that makes this an odd problem to solve:
Out of the box, the mixpanel snippet doesn't support get_distinct_id (and any call that is, by definition, synchronous) until the lib is loaded but does stub out other methods (such as track) BEFORE loading the mixpanel lib for the sake of queueing. Therefore we have two options:
Option 1. Drop async support and wait until the lib is loaded - Gist
This method works by creating a pre-init module to setup the window.mixpanel deps needed by the mixpanel lib and then specifying that as a dependency to the lib itself. Then requiring "mixpanel" will block until the lib is fully loaded.
Option 2. Provide a "loaded" callback to update the module's properties. - Gist
If you REALLY want async support, you'll need to update your stub's methods once the mixpanel lib is loaded. I don't recommend this because (among other reasons) it results in window.mixpanel !== mixpanel after the copy. This also means you must protect against race conditions on synchronous calls like get_distinct_id(). If the lib hasn't loaded yet, it'll be undefined. NOTE: I recommend that if you must have async support, you should just call through window.mixpanel instead of all of this craziness.
Following solution works for mixpanel api 2.2
add mixpanel with following shim -
and use following requirejs module instead of the the snippet given by mixpanel -
I simply took the snippet from mixpanel, removed the async mixpanel load and wrapped it in a requirejs module definition.
Change "YOUR TOKEN" at the bottom of the module.
Example use with a require call --
EDIT: The second one is the right answer after a little modification. the way mixpanel script works is it needs the init call in the snippet to happen before the actual mixpanel load. the trick is to require mixpanel after the init call.i have edited the 2nd answer and removed the first one and here's the gist
EDIT: Answer to comment from @johanandren Requirejs follows AMD principle and the order in which scripts will load is not fixed. In case you need to load mixpanel before using mixpanel-snippet, following hack can be used.
** it violates the Async load features of AMD, forces the script to block plus even in vanila mixpanel snippet the load is async and availability for initial api calls is not guaranteed
This worked for me. Place your mixpanel snippet in your js/lib directory named mixpanel-snippet.js.
In your app.js add the following shim to require.config:
In your require function add 'mixpanel-snippet' to the required array and initialize mixpanel:
I can provide a full app.js example if it would help but this should get your started. Let me know if this works.
As of mixpanel's 2.7.x release, they now support multiple AMD/UMD versions compatible with requirejs, you can grab it on their github page: https://github.com/mixpanel/mixpanel-js