March 4, 2014

Multiple Domain Tracking with Segment.IO and Mixpanel

This post was written in 2014 and it's advice is absolutely less relevant today, nevertheless it's one of the top search results for this problem.

At One Month, we've chosen to operate our app across several domains depending on what course you're taking. (OneMonthRails.com, OneMonthHTML.com, or the primary domain OneMonth.com)

As a result we broke a lot of our tracking that we do to figure out how people are using our site. We use a services called Segment.io that abstracts away a plethora of providers including Mixpanel, Google Analytics, and Customer.io. Segment.IO provides Analytics.js a nice well documented open source library. That we make a lot of use of.

Problem

The crux of the problem is that analytics.js and (and every service it supports) leverage a cookie to uniquely identify users. Cookies are local to the domain that served them. As a result you'll be identified as someone new on each domain of ours that you visit. If for example we wanted to see how many users were getting stuck trying to log in from the OneMonthHTML.com homepage. We wouldn't be able to tell who visited the homepage and then tried logged in, as the login happens on onemonth.com. We'd see them as new people during each step.

To work around this we'll need to move the responsibility of identifying users to a single domain. In this case onemonth.com. And we'll need to modify analytics.js to ask onemonth.com for the user's unique ID and use that on our other domains.

Cross-Origin XMLHttpRequest

There are a number of thought out security attacks around allowing javascript from other domains to run on your site. Because we own all the domains in question we don't need to worry about most of the issues. I opted to go for an asynchronous approach using Ajax and CORS. This required a little server side support. I'll save the details for another blog post, but you'll need a route on your primary domain that does the following;

  • Returns a unique id for the user (saved in a cookie)
  • Has the the proper CORS headers for your secondary domains
  • This id should also be available for calls to identify() on pages served from your primary domain.

All this will enable analytics.js to ask for the ID of the user before sending tracking events. Now on our secondary domains we have the following JS.

var idXhr = $.ajax({
  url: 'https://primarydomain.tld/tracking/id',
  xhrFields: {
    withCredentials: true // needed for cookies to work in CORS requests
 }
});
idXhr.done(function(data){
  analytics.identify(data.trackingID);

  // Ensure identify is caleld before anything else
  analytics.unshift(analytics.pop());
}).always(function(){
  analytics.load(OM.segment_io_key);
});

It defers loading the analytics.js until we have an ID and forces the identify call to be processed before calls to track() or other functions. In a future version we'll probably write our own track() that doesn't processes until after after the user has been identified. Both approaches allow other parts of our app to track events without knowledge of our identify scheme.

Broken but solvable things

  • Mixpanel Super properties are stored in cookies and don't follow across domains
  • Initial referring domain on events often reflect one of our own domains

It would be cool if we could work this scheme and the fixes for super properties and referring domains into an extension of analytics.js. But that's something for next time.

-Francis

Roborooter.com © 2024
Powered by ⚡️ and 🤖.