Git Product home page Git Product logo

mixpanel-node's Introduction

Mixpanel-node

Build Status

This library provides many of the features in the official JavaScript mixpanel library. It is easy to use, and fully async. It is intended to be used on the server (it is not a client module). The in-browser client library is available at https://github.com/mixpanel/mixpanel-js.

Installation

npm install mixpanel

Quick Start

// grab the Mixpanel factory
var Mixpanel = require('mixpanel');

// create an instance of the mixpanel client
var mixpanel = Mixpanel.init('<YOUR_TOKEN>');

// initialize mixpanel client configured to communicate over http instead of https
var mixpanel = Mixpanel.init('<YOUR_TOKEN>', {
    protocol: 'http',
});

// turn off keepAlive (reestablish connection on each request)
var mixpanel = Mixpanel.init('<YOUR_TOKEN>', {
    keepAlive: false,
});

// pass the custom logger (default is console)
var mixpanel = Mixpanel.init('<YOUR_TOKEN>', {
    debug: true,
    logger: pinoLogger, // or bunyan, or any other logger that implements the same interface
});

// track an event with optional properties
mixpanel.track('my event', {
    distinct_id: 'some unique client id',
    as: 'many',
    properties: 'as',
    you: 'want'
});
mixpanel.track('played_game');

// set an IP address to get automatic geolocation info
mixpanel.track('my event', {ip: '127.0.0.1'});

// track an event with a specific timestamp (up to 5 days old;
// use mixpanel.import() for older events)
mixpanel.track('timed event', {time: new Date()});

// create or update a user in Mixpanel Engage
mixpanel.people.set('billybob', {
    $first_name: 'Billy',
    $last_name: 'Bob',
    $created: (new Date('jan 1 2013')).toISOString(),
    plan: 'premium',
    games_played: 1,
    points: 0
});

// create or update a user in Mixpanel Engage without altering $last_seen
// - pass option $ignore_time: true to prevent the $last_seen property from being updated
mixpanel.people.set('billybob', {
    plan: 'premium',
    games_played: 1
}, {
    $ignore_time: true
});

// set a user profile's IP address to get automatic geolocation info
mixpanel.people.set('billybob', {
    plan: 'premium',
    games_played: 1
}, {
    $ip: '127.0.0.1'
});

// set a user profile's latitude and longitude to get automatic geolocation info
mixpanel.people.set('billybob', {
    plan: 'premium',
    games_played: 1
}, {
    $latitude: 40.7127753,
    $longitude: -74.0059728
});

// set a single property on a user
mixpanel.people.set('billybob', 'plan', 'free');

// set a single property on a user, don't override
mixpanel.people.set_once('billybob', 'first_game_play', (new Date('jan 1 2013')).toISOString());

// increment a numeric property
mixpanel.people.increment('billybob', 'games_played');

// increment a numeric property by a different amount
mixpanel.people.increment('billybob', 'points', 15);

// increment multiple properties
mixpanel.people.increment('billybob', {'points': 10, 'games_played': 1});

// append value to a list
mixpanel.people.append('billybob', 'awards', 'Great Player');

// append multiple values to a list
mixpanel.people.append('billybob', {'awards': 'Great Player', 'levels_finished': 'Level 4'});

// merge value to a list (ignoring duplicates)
mixpanel.people.union('billybob', {'browsers': 'ie'});

// merge multiple values to a list (ignoring duplicates)
mixpanel.people.union('billybob', {'browsers': ['ie', 'chrome']});


// record a transaction for revenue analytics
mixpanel.people.track_charge('billybob', 39.99);

// clear a users transaction history
mixpanel.people.clear_charges('billybob');

// delete a user
mixpanel.people.delete_user('billybob');

// delete a user in Mixpanel Engage without altering $last_seen or resolving aliases
// - pass option $ignore_time: true to prevent the $last_seen property from being updated
// (useful if you subsequently re-import data for the same distinct ID)
mixpanel.people.delete_user('billybob', {$ignore_time: true, $ignore_alias: true});

// Create an alias for an existing distinct id
mixpanel.alias('distinct_id', 'your_alias');

// all functions that send data to mixpanel take an optional
// callback as the last argument
mixpanel.track('test', function(err) { if (err) throw err; });

// track multiple events at once
mixpanel.track_batch([
    {
        event: 'recent event',
        properties: {
            time: new Date(),
            distinct_id: 'billybob',
            gender: 'male'
        }
    },
    {
        event: 'another recent event',
        properties: {
            distinct_id: 'billybob',
            color: 'red'
        }
    }
]);

// import an old event
var mixpanel_importer = Mixpanel.init('valid mixpanel token', {
    secret: 'valid api secret for project'
});

// needs to be in the system once for it to show up in the interface
mixpanel_importer.track('old event', { gender: '' });

mixpanel_importer.import('old event', new Date(2012, 4, 20, 12, 34, 56), {
    distinct_id: 'billybob',
    gender: 'male'
});

// import multiple events at once
mixpanel_importer.import_batch([
    {
        event: 'old event',
        properties: {
            time: new Date(2012, 4, 20, 12, 34, 56),
            distinct_id: 'billybob',
            gender: 'male'
        }
    },
    {
        event: 'another old event',
        properties: {
            time: new Date(2012, 4, 21, 11, 33, 55),
            distinct_id: 'billybob',
            color: 'red'
        }
    }
]);

FAQ

Where is mixpanel.identify()?

mixpanel-node is a server-side library, optimized for stateless shared usage; e.g., in a web application, the same mixpanel instance is used across requests for all users. Rather than setting a distinct_id through identify() calls like Mixpanel client-side libraries (where a single Mixpanel instance is tied to a single user), this library requires you to pass the distinct_id with every tracking call. See #13.

How do I get or set superproperties?

See the previous answer: the library does not maintain user state internally and so has no concept of superproperties for individual users. If you wish to preserve properties for users between requests, you will need to load these properties from a source specific to your app (e.g., your session store or database) and pass them explicitly with each tracking call.

Tests

# in the mixpanel directory
npm install
npm test

Alternative Clients and Related Tools

Attribution/Credits

Heavily inspired by the original js library copyright Mixpanel, Inc. (http://mixpanel.com/)

Copyright (c) 2014-21 Mixpanel Original Library Copyright (c) 2012-14 Carl Sverre

Contributions from:

License

Released under the MIT license. See file called LICENSE for more details.

mixpanel-node's People

Contributors

carlsverre avatar chiangf avatar colestrode avatar dependabot[bot] avatar freeall avatar gdyr avatar hans-lizihan avatar iatsiuk avatar ishbu avatar isikhi avatar jaredmixpanel avatar jhermsmeier avatar jylauril avatar knupman avatar left47 avatar maeldur avatar markshust avatar mklopets avatar omrilotan avatar pierrickp avatar radotzki avatar sandinmyjoints avatar tdumitrescu avatar tejasmanohar avatar tootallnate avatar veerabio avatar watson avatar wneild avatar yayc avatar zeevl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mixpanel-node's Issues

batch should POST

"To send a batch of messages to an endpoint, you should use a POST instead of a GET request. Instead of sending a single JSON object as the data query parameter, send a JSON list of objects, base64 encoded, as the data parameter of an application/x-www-form-urlencoded POST request body." from https://mixpanel.com/help/reference/http#batch-requests

It seems that the import_batch is using GET with query param.

Official doc for this module

Been using this module recently and find it differs greatly from the client-side module.

The lack of official doc on mixpanel.com can be misleading because developers may incorrectly assume what isn't mentioned here is documented in the client-side doc, eg. the first line is This library provides many of the features in the official JavaScript mixpanel library.

I am happy to help if you are looking for maintainers (as discussed in #54), we are probably going to use mixpanel for quite a bit in our projects.

Misleading doc example

Hi,

While reviewing your code I've noticed that it is not needed to call new for Client constructor. To create a new client, you do:

var client = new mixpanel.Client(token);

But your are using a functional inheritance model where Client function returns a newly created object, called metrics that contains all your module's method. In this case, the new keyword is superflux and should be dropped.

By convention, it would also be a good idea to rename Client to createClient.

Cheers,
Renault

Disable method like the standard js version has

I was wondering if or why the disable method for mix panel, which exists in the regular js library, has not been implemented here yet? I think that it would be very useful for stopping event tracking when using a node site on a test or development server.

Thanks

time property should not trigger /import endpoint

In a server-side implementation of the Mixpanel API, it's reasonable to want to use the client's timestamp (rather than an implicit "now") for the time property. But in the current implementation, that causes the /import endpoint to be used, with the consequence that the event doesn't appear in the Mixpanel Live View.

One alternative: add an endpoint argument to track() (so that import() can use it to force the /import endpoint) and change the time-property test to look for a timestamp older than Mixpanel's 5-day limit for /track.

Add maintainers to avoid stalling

There are too many open issues and pull requests and it seems like a dead project.

Could you please add maintainers to this module so we can keep using it? I don't see a reason that it has to be Mixpanel employees who maintain it.

You can see the usage here: https://www.npmjs.com/package/mixpanel (430 installs in the last day)

Add example with IP address tracking

It would be helpful to have an example of an IP address being passed along with a mixpanel.track or mixpanel.people call, as described in this blog post: https://blog.mixpanel.com/2015/07/06/community-tip-how-to-keep-properties-consistent-across-client-and-server-libraries/

The examples in the blog post are in PHP and I'm not sure how they translate to the Node SDK. I would guess that a track event with an IP address would look like this:

mixpanel.track('sign_up', {
  distinct_id: id,
  ip: '229.92.91.139'
})

And that an IP address added to a people tracking event would look like this;

mixpanel.people.set(
  $first_name: first_name,
}, '229.92.91.139')

Can anyone confirm if this is correct or not?

[documentation] user synchronization with their event based on ($)dinstict_id

I would recommend updating the documentation on the people.set function.

Assuming that you are setting the distinct_id property of all the events tracked based on the user.$distinct_id property.

If one uses something like this: mixpanel.people.set(data.$username, data);
mixpanel would not link correctly on the live view events with their user owners.
(A click on the user button icon on the left of the event metric will display an anonymous user instead.)

However this will do the job: mixpanel.people.set(data.$distinct_id, data);

I would suggest to add as a recommendation to use the user's dinstict id as the key in the people.set function.

Is this stable for production use yet?

From the looks of it, this project seems to be in it's early days, but is the most advanced so far out of the node.js mixpanel solutions.

Currently, the following seems to be missing:

  • Some API calls such as identify and register (not sure if the .people calls are meant as an alternative to this)
  • Automated tests
  • A changelog

So is this project currently fit for production use, or is there still a while to go? Cheers :)

Add support (or documentation) for $ignore_alias

This would be really useful to support for the delete_user call. If it's already supported, I must have missed it in the docs, (both in the library and on the mixpanel http api docs). Can you point me to the docs or update them?

Something like mixpanel.people.delete_user('billybob', {$ignore_time: true, $ignore_alias: true});

See mixpanel/mixpanel-ruby#53

Add User Agent support

Hi,

We're using the library in our project and there are usecases where we want to pass the user agent header (from the requests users made to our server) to mixpanel tracking calls so we can see from which browsers the requests are made.

I can see that the requests mixpanel-node is making have headers set to blank {}. It'd be nice to be able to pass in request headers to the mixpanel calls. Combined with the current ability to manually set ip for the tracking calls, this helps make event tracking more consistent across client, and it makes a nice addition to this article https://blog.mixpanel.com/2015/07/06/community-tip-how-to-keep-properties-consistent-across-client-and-server-libraries/

Code style / Linter

Looks like a lot of this is using 4 spaces and under_score naming (even for helper functions, not exposed/exported). Most wrappers follow the conventions of the language, not API. Does Mixpanel have a strict style guide that they follow for JS, or would you guys be interested in PRs to make the styling a bit more conventional and cleaner (imo/subjective)?

If there's a strict style guide, I would highly recommend a linter, which I can also PR in using (probably) ESLint to fit the existing codebase.

Is mixpanel.people.set_once missing from the node API?

I'd like to use the same "mixpanel.people.set_once" function that's available in the JS library to set People profile properties only once at the time of initial registration. I didn't see it in the documentation on this git repo, and I wasn't able to fire it succesfully when I tested it.

Wondering if it is being added soon or if there's some slightly different syntax when using it on node.

Thanks

$ip versus ip

I'm wondering why although most special properties are handled with $ prefix, the "ip" is not prefixed while everywhere in the mixpanel documentation it is

mixpanel.people.set("billybob", {
    $first_name: "Billy",
    $last_name: "Bob",
    $created: (new Date('jan 1 2013')).toISOString(),
    plan: "premium",
    games_played: 1,
    points: 0
});

If we provide $ip in the people.set, mixpanel service does not process to the reverse location.
The code only handle the "ip" preoperty with:

        if ('ip' in $set) {
            data.$ip = $set.ip;
            delete $set.ip;
        }

Sending increment without 'by' but providing a callback doesn't work

Running this call:

mixpanel.people.increment(user.id, 'events_created', logErrorCallback);

Results in this data being sent to Mixpanel:

Sending the following data to Mixpanel (Engage):
{ '$add': { events_created: [Function: logErrorCallback] },
  '$token': 'redacted',
  '$distinct_id': 'f8489d6a-9249-4d3a-b23b-5a40087d7005' }

As you can see, it's sending the callback function as the increment value, which apparently Mixpanel silently ignores (or maybe it's not silent, and since the callback never fires, I never know). I've worked around this temporarily by just specifying '1' as 'by', but I think this is a bug that should be fixed. Thanks for the awesome library!

ES6 Refactor

Would the maintainers of this module appreciate an ES6 refactor using Babel (transpile on prepublish since not everyone is on Node 4.x.x though it's LTS now)? I'd love to help out by sending PRs for that if of interest. It would not have any significant negative performance implications since we'd transpile via Babel and not use ES6 directly through V8, which hasn't all been optimized yet.

Import Multiple events at once

Im using the importer to set old data into mixpanel, but im doing it one event at the time, which is quite expensive for a couple of thousands events, is there a way to import multiple events at once, their docs say they support a JSON Array but couldnt figure it out on how to call the importer to send an Array

increment is creating anonymous users when distinct_id is not a string

the type of distinct_id at this point:
https://github.com/mixpanel/mixpanel-node/blob/master/lib/mixpanel-node.js#L296
should be checked like so:

if (typeof distinct_id != 'string') {
  return callback(new TypeError('distinct_id must be a string'));
}

I just discovered I created 1000 users because I was passing an object as distinct_id rather than string
I would say that the same issue is also present in any function that expects a distinct_id as parameter.

I can write a pull request when I can see the other pull requests I sent are merged.

cc @joeatwork
cc @carlsverre

add $union support

The $union operator for the /engage endpoint (user profiles) is needed for push-notification tokens. The implementation is pretty much identical to $append except for the $union operator.

Allow $ignore_time and other modifiers when using $unset

I am sure this is something from the main API, but the $unset functionality has no way of adding a $ignore_time according to the documentation (or the code in this library). Why is this the case? It's very frustrating to see that when we update our properties to $unset something, all the user profiles have a 'last seen' of less than a minute ago.

Could you point me in the right direction please?

so how do i put this into a route?

so how do i actually put this into a route, at example

app.get('/', function (req, res) {
    res.render('index', {
        title: 'test',
        user : req.user,
    });
});

just wondering.

Support for using in browser when pulled in via browserify?

Has anyone thought of allowing this to behave like the mixpanel library in terms of using it in the browser? It does work with browserify -- it just doesn't include all of the details that the main mixpanel library does that are specific to running in the browser.

Booleans?

Say I want to pass a boolean property about a user, like {$unsubscribed: true} (from here).

Would I Do:
a) {$unsubscribed: true} // boolean in JS
b) {$unsubscribed: 'true'} // string 'true'
C) {$unsubscribed: 'True'} // string 'True', as noted in the linked docs
C) {$unsubscribed: 'TRUE'} // string 'TRUE', as this is the only way to get the profile of the user to match the screen shot in the docs

Support Mixpanel#identify

The official client libraries for other platorms all seem to support Mixpanel#identify. I inherited a Node codebase that integrates Mixpanel so I'm not clear whether #identify is a newer method, but regardless, it doesn't seem to be supported here (though people analytics is).

Any plans to support #identify?

Missing call set_once

we need this call exposed or documented?

https://mixpanel.com/docs/people-analytics/javascript

mixpanel.people.set_once

This method allows you to set a user attribute, only if it is not currently set. It can be called multiple times safely, so is perfect for storing things like the first date you saw a user, or the referrer that brought them to your website for the first time.

cannot import old events

I am trying to import old events. I created a short script to illustrate the problem. In the example I call mixpanel twice, first with the import function (which it seems I am not using correctly) and once with the track function which works as expected. Any idea?

Thanks
R

var Mixpanel = require('mixpanel');
var mixpanel = Mixpanel.init('token', {
key: 'api key'
});
e=100;
u=1;
ipadd='127.0.0.1';
mixpanel.import(e, new Date(), {
distinct_id:u ,
ip:ipadd
});
mixpanel.track(e, {
distinct_id:u,
ip:ipadd
});
</code

Unit Tests

Target is 100% test coverage. Unit tests should be simple and require few or no dependencies. Mocking of network requests may be necessary to fully test library.

Token validation

Hey,

When i submit a request with a total failing token:

moncullllfjmdqsjkhgflkqdjshfgkjhsdfkjghlskjdhflksjghslkdfjhglskjdfhglksjhdflgkjshdflgkjhsdflkjghslkdfjhglskjdfhglksjdfhglkjsdhfglkjsdfh

I get a success instead of an error. I think it's an API issue.

What can i do?

$-prefix

In the example you have:

// create or update a user in Mixpanel Engage
mixpanel.people.set("billybob", {
    $first_name: "Billy",
    $last_name: "Bob",
    $created: (new Date('jan 1 2013')).toISOString(),
    plan: "premium",
    games_played: 1,
    points: 0
});

Why are some keys prefixed with $? I'm guessing these are special to the mixpanel platform, what would the result be if I left out the $-prefix by mistake?

Init requires a a token not API key

Hello a couple of suggestions to make it a bit easier to understand the documentation.

Would it be possible to update the documentation to explicitly say that the init function requires the token?

In addition it would be helpful if it explained that "billybob" could be substituted for the distinct id of the user. Fairly obvious when you get into it bit just something that you should not have to check.

Happy to add this via pull request if you would like.

Thanks!

Support in-app push notifications

send ios/android push notifications. We frequently use Mixpanels web UI to send out push notifications to our users and were hoping mixpanel-node could support this as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.