mixpanel-js icon indicating copy to clipboard operation
mixpanel-js copied to clipboard

Callback funcs on `alias` and `identify`

Open youcandanch opened this issue 10 years ago • 6 comments

Hey folks,

So unless I'm mistaken, both alias and identify don't allow for a callback function - this seems suboptimal especially for identify, since that's supposed to be called on login. In our application in particular, we're doing something like this:

params =
    username: 'a-username'
    password: 'a-well-encrypted-password'
Session.save params, ->
    User.get id:'me', (user) ->
        mixpanel.identify(user.id)
        redirect_to_next_url()

The problem here is that it's plausible our redirect will fire before the identify call completes - I realize it's a bit of a race condition, but it'd be much cleaner if I could do:

mixpanel.identify(user.id, ->
    redirect_to_next_url()
)

The same goes for alias and signing up a new user. Any reason these functions don't provide callbacks?

youcandanch avatar Oct 14 '15 13:10 youcandanch

Any updates here?

Volodymyr128 avatar Mar 16 '16 10:03 Volodymyr128

Bump. This is a serious problem for us. We have a race condition that can occur. Here is a basic sequence of events.

  1. User visits our website (gets MixPanel's distinct UUID).
  2. User signs up for our service.
  3. In parallel: 3.1) We call mixpanel.alias to alias our UserKey with MixPanel's distinct UUID. 3.2) Our server tells MixPanel details about the user.

If 3.2 occurs before 3.1 the result is we end up with two MixPanel profiles (one of which is orphaned). This happens because MixPanel does not retroactively alias a user. So in order for us to prevent this race condition, we need to know when mixpanel.alias has completed.

workmanw avatar Oct 18 '16 21:10 workmanw

Just for the record, providing a callback would not 100% solve @workmanw's problem. In that callback, you could be assured that api.mixpanel.com had responded with 200 OK to your alias request; but technically there is still a race in the Mixpanel backend between consuming the alias and consuming the new event data in step 3.2. (api.mixpanel.com is load-balanced, so your two requests might go to completely different physical machines, will get enqueued on completely different queues with potentially different rates of consumption, etc.) @workmanw, if you're seeing your race condition manifest a lot in practice, you probably should reach out to Mixpanel support and see if they can help you work around it.

Adding callback parameters does seem very JSish and therefore a good idea, but you'd have to add them all throughout the interface, right?

Quuxplusone avatar Oct 18 '16 21:10 Quuxplusone

@Quuxplusone Yes we have seen this happen in production. Our tracking has been in production for less than a week and we've already noticed it.

Yea I can understand that mixpanel itself could have it's own queuing. Though surely having this will significantly reduce the likelihood. It would seem this race condition is much more likely caused by latency over the wire, than items ending up a head of each other in different work queues.

Adding callback parameters does seem very JSish and therefore a good idea, but you'd have to add them all throughout the interface, right?

Many of the functions already have callback parameters as is evident in the public docs: https://mixpanel.com/help/reference/javascript-full-api-reference#mixpanel.track

workmanw avatar Oct 18 '16 23:10 workmanw

So crazy that this is somehow still unaddressed by MixPanel.

Javascript is their "main" recommended API, correct? They have 300 employees and a valuation of over $800M, but nobody has time to respond to GitHub issues.

leastbad avatar Sep 20 '18 07:09 leastbad

I'm not one to complain and then not offer a solution. Stick this early in your page JS:

var oldXHR = window.XMLHttpRequest;
function newXHR() {
  var realXHR = new oldXHR();
  realXHR.addEventListener("readystatechange", function(e) {
    var respXHR = realXHR.responseURL.split('/');
    if(realXHR.readyState==4 && realXHR.status==200 && respXHR[2]=='api.mixpanel.com'){
      // I still use jQuery because: suck it. Feel free to replace this with something that won't offend your virtual DOM library.
      $(document).trigger(`mixpanel.${respXHR[3]}.complete`);
    }
  }, false);
  return realXHR;
}
window.XMLHttpRequest = newXHR;

Then whenever you need a callback on your identify or alias calls:

$(document).on('mixpanel.engage.complete', function() {
  console.log('Enjoy that sweet callback action.');
});

One really important thing to note is that calling identify does not make an XHR request. What it does is set a cookie that is delivered with future requests to track, or if you're really on your game, people.set()

I'm pretty sure that calling register and register_once doesn't call home either. So you should/can call identify(), register_once() and then seal the deal with people.set({'$email': user_email})

If anyone at MixPanel wants to cut me a cheque, drop me a note. Hope you figured something out, @workmanw @youcandanch

leastbad avatar Sep 20 '18 09:09 leastbad