10

I'm not able to connect to mixpanel.

I have tried with a correct api_key and api_secret, like this:

<html>
<head>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.min.js" />
    </script>
    <script type="text/javascript" src="faulty-labs-md5.js" />
    </script>
</head>
<body>
    <script type="text/javascript">
$(document).ready(function() {
    $("#btnTest").click(function() {

        var api_key = 'BigSecret';
        var api_secret = 'BigSecret2';
        var expire = new Date('2012', '12', '24').getTime() / 1000 + 3600;
        var from_date = $("#date1").val();
        var to_date = $("#date2").val();
        var sig = faultylabs.MD5("api_key=" + api_key + "expire=" + expire + "from_date=" + from_date + "to_date=" + to_date + api_secret);
        //var path = 'https://data.mixpanel.com/api/2.0/export?api_key=' + api_key + "&expire=" + expire + "&from_date=" + from_date + "&to_date=" + to_date;
        var path = 'https://data.mixpanel.com/api/2.0/export?api_key=' + api_key + "&expire=" + expire + "&from_date=" + from_date;
        path = path + "&sig=" + sig.toLowerCase();
        $.jsonp({
            type: 'GET',
            url: path,
            async: false,
            callback: to_date,  // sneaky bogus shenanigans
            callbackParameter: 'to_date', // more of same
            contentType: "application/json",
            dataType: 'jsonp',
            cache: true,
            success: function(json) {
                alert(json);
            },
            error: function(e) {
                console.log(e.message);
            }
        });
    });
});
    </script>
    <input type="text" id="date1" value="2012-10-29" />
    <input type="text" id="date2" value="2012-10-29" />
    <button onclick="return false" id="btnTest">Test</button>
</body>
</html>

As you can see, I try to use this API with JSONP, but I'm lost in the woods. Is there anybody who has knowledge about mixpanel and JSONP?

Thank you in advance.

EDIT: I've added the new version of the page.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
  • Can you tell us a little more like does the console ever return anything? Did you check your Console does the Ajax request ever get sent out? When are you calling sendRequestToPage() ? its not going to start by itself. – Haso Keric Oct 30 '12 at 13:57
  • 1
    I'm getting now an {"error": "Invalid API signature"} – Lajos Arpad Oct 30 '12 at 14:27
  • You are not specifying the api_secret in your url – Haso Keric Oct 30 '12 at 14:35
  • The api_secret is not part of the url according to the documentation. – Lajos Arpad Oct 31 '12 at 10:57
  • Why are you using JSONP? – Alan Nov 02 '12 at 19:36
  • As @Tyler mentioned in his answer, you need to MD5 hash the signature, and append that to your request. – Alan Nov 02 '12 at 19:47
  • 1
    I've created a Javascript library to make this really easy: https://github.com/michaelcarter/mixpanel-data-export-js – user2534862 Jun 29 '13 at 15:38
  • Can anyone give me any tips how to accomplish this while keeping my api secret a secret? I'd like to be able to query from front-end Javascript code but this page will be public-facing. – stealthysnacks Feb 09 '17 at 21:45
  • 1
    @stealthysnacks I think you could use a proxy. Your Javascript code could send a request to your server, triggering your server to send a request to MixPanel. The API secret this way would be known only by your server and would never be given to your client-side. – Lajos Arpad Feb 10 '17 at 08:41
  • $Lajos Arpad This is a good answer. I suppose there would be an extra call to our servers but this would keep the secret anonymous. – stealthysnacks Feb 10 '17 at 19:22
  • @stealthysnacks yes, I think this is the best way to keep your secret a secret in your conditions. – Lajos Arpad Feb 11 '17 at 10:39
  • This question has been recently downvoted. Is there a reason? – Lajos Arpad Jun 20 '18 at 10:17

6 Answers6

3

Here a few things I realized. I was able to get it working with all other end points I tried but "export". I'm tempted to believe it's something peculiar to just the raw data export endpoint. Reading through their docs, the raw data end point is the only end point that isn't part of the main API and therefore requires a different base URI "https://data.mixpanel.com/api/2.0". All other endpoints "events", "segmentation" etc. use "https://mixpanel.com/api/2.0". I've put down the steps I went through below. I'm using jquery.MD5 lib for the md5 implementation

$(function() {
  $("#test_request").click(function() {
    var api_secret, arg_keys, args, args_concat, end_point, key, 
    mixpanel_base_uri, sig, sorted_keys, _i, _len;
    args = {};
    end_point = "export";
    api_secret = "BIG_SECRET2";
    args.api_key = "BIG_SECRET";

    args.from_date = $("input[name=from_date]").val();
    args.to_date = $("input[name=to_date]").val();
    //using Math.floor to round to integer as api expects integer
    args.expire = Math.floor(new Date().getTime() / 1000 + 3600); 
    arg_keys = Object.keys(args);
    sorted_keys = arg_keys.sort();
    args_concat = "";

    //concatenating key value pairs
    for (_i = 0, _len = sorted_keys.length; _i < _len; _i++) {
      key = sorted_keys[_i];
      args_concat = "" + args_concat + key + "=" + args[key];
    }
    sig = $.md5(args_concat + api_secret);

    //merge signature property with args hash
    $.extend(args, {
      sig: sig
    });

    //export endpoint isn't part of the main api and data.mixpanel instead of just mixpanel.com
    DATA_URI = "https://data.mixpanel.com/api/2.0"
    DEFAULT_URI = "https://mixpanel.com/api/2.0"
    BASE_URI = end_point === "export" ? DATA_URI : DEFAULT_URI;
    $.getJSON("" + BASE_URI + "/" + end_point + "?callback=?", args, function(result) {
      alert("result is" + JSON.stringify(result));

    });
  });
});

I've also put up a working solution for all other endpoints. Here is the link http://jsfiddle.net/Dantheta/CmKQN/

Hope you find it useful.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
dantheta
  • 1,107
  • 2
  • 13
  • 29
  • Thank you, I will try to test this soon. – Lajos Arpad Feb 05 '13 at 11:53
  • Hey Dan. I think I've got the same issue. I can get "/events/top" to work, but not "export". I get a 400 Bad Request, but I presume my code for making the call, computing the signature, etc. is correct because of the success on the former. Did you ever get a successful export call? BTW your jsfiddle snippet helped, though it's not executing either. – Jason Aug 08 '13 at 14:07
  • Thanks for the fiddle, @dantheta! I've updated here: http://jsfiddle.net/mytovdp9/ as there was a typo on your line 13 for the `on` field, and I updated the external resource to rawgit so the right MIME type is used again after github's change. Actually, I just properly edited yours here now: http://jsfiddle.net/CmKQN/8/ – qix Aug 28 '14 at 01:01
  • Hey, Some is get success to make the 'export' to work?? – Yair hadad Sep 02 '19 at 08:54
2

After squinting at this PHP, I'm pretty sure you need to do an md5 hash of your api signature.

Import an md5 library, like this one

<script type="text/javascript" src="jquery.md5.min.js"></script>

And then do something like this:

var sig = "api_key=" + api_key + "expire=" + expire + "from_date=" + from_date + "to_date=" + to_date + "bigsecret2";
sig = $.md5(sig);

I'm trying to accomplish the same thing you are, but unfortunately I still haven't got it working.

Edit - This is rough. The API will fail if ANY parameter is not hashed with the sig. It will also fail if any parameter is included which is not part of the API. JsonP adds a "callback" and a "_" timestamp parameter so it can do what it does, and this breaks the call. You can hack around this by excluding the timestamp with cache: true and using a special jsonp plugin which allows you to rename the callback parameter. Here I have renamed it to to_date and named the callback function "2012-10-29". It's crazy, and it still doesn't work because the reply is not valid json. It's a series of newline-delimited json objects which can not be evaluated, and I'm still stuck on that part. Here's what I've got so far:

<script type="text/javascript" src="jquery-1.8.2.js"></script>
<script type="text/javascript" src="jquery.md5.min.js"></script>
<script type="text/javascript" src="jquery.jsonp-2.4.0.js"></script>

<script>
    var events = document.getElementById("events");

    var api_key = "secret";
    var expire = "1351811239";
    var from_date = "2012-10-29";
    var to_date = "2012-10-29";

    var sig = "api_key=" + api_key + "expire=" + expire + "from_date=" + from_date + "to_date=" + to_date + "secret2";
    sig = $.md5(sig);


    var path = 'https://data.mixpanel.com/api/2.0/export?api_key=' + api_key + "&expire=" + expire + "&from_date=" + from_date;
    // to_date will be added later as the sneaky callback

    path = path + "&sig=" + sig;

    $.jsonp({
        type: 'GET',
        url: path,
        async: false,
        callback: to_date,  // sneaky bogus shenanigans
        callbackParameter: 'to_date', // more of same
        contentType: "application/json",
        dataType: 'jsonp',
        cache: true,
        success: function(json) {
            alert(json);
        },
        error: function(e) {
            console.log(e.message);
        }
    });

</script>

Ultimately I threw up my hands and wrote a C# program to hit the API and spit out a CSV for me.

Tyler
  • 373
  • 1
  • 14
  • Their documentation says that the callback parameter is not part of the MD5 signature. – Alan Nov 02 '12 at 19:42
  • Uncaught TypeError: Object function (a,b){return new p.fn.init(a,b,c)} has no method 'jsonp' – Lajos Arpad Nov 04 '12 at 19:01
  • I have edited my answer with the new version of the page. What script should be included to be able to use $.jsonp? Thank you. – Lajos Arpad Nov 04 '12 at 19:11
  • The script is here https://github.com/jaubourg/jquery-jsonp but again, it didn't work for me because the output is not valid JSON. – Tyler Nov 05 '12 at 19:34
1

from the documentation:

We do not have a JS client library, but we have implemented jsonp on the API backend. See the Wikipedia article for a brief overview. Our jsonp parameter is 'callback'. This parameter will not be used during signature calculation.

https://mixpanel.com/docs/api-documentation/data-export-api#libs-js

Assuming you calculate the signature correctly, the below example will work:

 $.getJSON('http://mixpanel.com/api/2.0/segmentation/?callback=?', {
            event: event,
            from_date: from_date,
            to_date: to_date,
            expire: expire,
            sig: sig,
            api_key: api_key
        }, function (result) {
            alert(result);
        });
Greg Dean
  • 29,221
  • 14
  • 67
  • 78
0

As Tyler Mentioned, you need to MD5 hash the signature before appending it to the request URL.

In addition, if what you pasted is your code, you have a bug:

path = path + + "&sig=" + sig;

should be:

path = path + "&sig=" + sig

Alan
  • 45,915
  • 17
  • 113
  • 134
0

I've tried many things but I was not successful in sending a request to mixpanel with jsonp, because it generated new parameters. Nobody showed me a working solution, so I guess this problem is unsolvable. If somebody shows me a solution I will gladly remove this answer and accept his/her answer.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
0

The /export endpoint appears as though it does not support JSONP callbacks. If you calculate your signature and call the URL without a callback and without a cache buster (provided by default with an $.ajax call), you'll get results.

Jason
  • 2,223
  • 2
  • 20
  • 28