mixpanel
Version:
A simple server-side API for mixpanel
359 lines (294 loc) • 9.97 kB
JavaScript
const { merge_modifiers, ProfileHelpers } = require("./profile_helpers");
class MixpanelPeople extends ProfileHelpers() {
constructor(mp_instance) {
super();
this.mixpanel = mp_instance;
this.endpoint = "/engage";
}
/** people.set_once(distinct_id, prop, to, modifiers, callback)
---
The same as people.set but in the words of mixpanel:
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. "
*/
set_once(distinct_id, prop, to, modifiers, callback) {
const identifiers = { $distinct_id: distinct_id };
this._set(prop, to, modifiers, callback, { identifiers, set_once: true });
}
/**
people.set(distinct_id, prop, to, modifiers, callback)
---
set properties on an user record in engage
usage:
mixpanel.people.set('bob', 'gender', 'm');
mixpanel.people.set('joe', {
'company': 'acme',
'plan': 'premium'
});
*/
set(distinct_id, prop, to, modifiers, callback) {
const identifiers = { $distinct_id: distinct_id };
this._set(prop, to, modifiers, callback, { identifiers });
}
/**
people.increment(distinct_id, prop, by, modifiers, callback)
---
increment/decrement properties on an user record in engage
usage:
mixpanel.people.increment('bob', 'page_views', 1);
// or, for convenience, if you're just incrementing a counter by 1, you can
// simply do
mixpanel.people.increment('bob', 'page_views');
// to decrement a counter, pass a negative number
mixpanel.people.increment('bob', 'credits_left', -1);
// like mixpanel.people.set(), you can increment multiple properties at once:
mixpanel.people.increment('bob', {
counter1: 1,
counter2: 3,
counter3: -2
});
*/
increment(distinct_id, prop, by, modifiers, callback) {
// TODO extract to ProfileHelpers
const $add = {};
if (typeof prop === "object") {
if (typeof by === "object") {
callback = modifiers;
modifiers = by;
} else {
callback = by;
}
for (const [key, val] of Object.entries(prop)) {
if (isNaN(parseFloat(val))) {
if (this.mixpanel.config.debug) {
this.mixpanel.config.logger.error(
"Invalid increment value passed to mixpanel.people.increment - must be a number",
{ key, value: val },
);
}
} else {
$add[key] = val;
}
}
} else {
if (typeof by === "number" || !by) {
by = by || 1;
$add[prop] = by;
if (typeof modifiers === "function") {
callback = modifiers;
}
} else if (typeof by === "function") {
callback = by;
$add[prop] = 1;
} else {
callback = modifiers;
modifiers = typeof by === "object" ? by : {};
$add[prop] = 1;
}
}
let data = {
$add: $add,
$token: this.mixpanel.token,
$distinct_id: distinct_id,
};
data = merge_modifiers(data, modifiers);
if (this.mixpanel.config.debug) {
this.mixpanel.config.logger.debug(
"Sending the following data to Mixpanel (Engage)",
{ data },
);
}
this.mixpanel.send_request(
{ method: "GET", endpoint: "/engage", data: data },
callback,
);
}
/**
people.append(distinct_id, prop, value, modifiers, callback)
---
Append a value to a list-valued people analytics property.
usage:
// append a value to a list, creating it if needed
mixpanel.people.append('bob', 'pages_visited', 'homepage');
// like mixpanel.people.set(), you can append multiple properties at once:
mixpanel.people.append('bob', {
list1: 'bob',
list2: 123
});
*/
append(distinct_id, prop, value, modifiers, callback) {
// TODO extract to ProfileHelpers
const $append = {};
if (typeof prop === "object") {
if (typeof value === "object") {
callback = modifiers;
modifiers = value;
} else {
callback = value;
}
Object.keys(prop).forEach(function (key) {
$append[key] = prop[key];
});
} else {
$append[prop] = value;
if (typeof modifiers === "function") {
callback = modifiers;
}
}
let data = {
$append: $append,
$token: this.mixpanel.token,
$distinct_id: distinct_id,
};
data = merge_modifiers(data, modifiers);
if (this.mixpanel.config.debug) {
this.mixpanel.config.logger.debug(
"Sending the following data to Mixpanel (Engage)",
{ data },
);
}
this.mixpanel.send_request(
{ method: "GET", endpoint: "/engage", data: data },
callback,
);
}
/**
people.track_charge(distinct_id, amount, properties, modifiers, callback)
---
Record that you have charged the current user a certain
amount of money.
usage:
// charge a user $29.99
mixpanel.people.track_charge('bob', 29.99);
// charge a user $19 on the 1st of february
mixpanel.people.track_charge('bob', 19, { '$time': new Date('feb 1 2012') });
*/
track_charge(distinct_id, amount, properties, modifiers, callback) {
if (typeof properties === "function" || !properties) {
callback = properties || undefined;
properties = {};
} else {
if (typeof modifiers === "function" || !modifiers) {
callback = modifiers || undefined;
if (properties.$ignore_time || properties.hasOwnProperty("$ip")) {
modifiers = {};
Object.keys(properties).forEach(function (key) {
modifiers[key] = properties[key];
delete properties[key];
});
}
}
}
if (typeof amount !== "number") {
amount = parseFloat(amount);
if (isNaN(amount)) {
this.mixpanel.config.logger.error(
"Invalid value passed to mixpanel.people.track_charge - must be a number",
);
return;
}
}
properties.$amount = amount;
if (properties.hasOwnProperty("$time")) {
const time = properties.$time;
if (Object.prototype.toString.call(time) === "[object Date]") {
properties.$time = time.toISOString();
}
}
let data = {
$append: { $transactions: properties },
$token: this.mixpanel.token,
$distinct_id: distinct_id,
};
data = merge_modifiers(data, modifiers);
if (this.mixpanel.config.debug) {
this.mixpanel.config.logger.debug(
"Sending the following data to Mixpanel (Engage)",
{ data },
);
}
this.mixpanel.send_request(
{ method: "GET", endpoint: "/engage", data: data },
callback,
);
}
/**
people.clear_charges(distinct_id, modifiers, callback)
---
Clear all the current user's transactions.
usage:
mixpanel.people.clear_charges('bob');
*/
clear_charges(distinct_id, modifiers, callback) {
let data = {
$set: { $transactions: [] },
$token: this.mixpanel.token,
$distinct_id: distinct_id,
};
if (typeof modifiers === "function") {
callback = modifiers;
}
data = merge_modifiers(data, modifiers);
if (this.mixpanel.config.debug) {
this.mixpanel.config.logger.debug("Clearing this user's charges", {
$distinct_id: distinct_id,
});
}
this.mixpanel.send_request(
{ method: "GET", endpoint: "/engage", data: data },
callback,
);
}
/**
people.delete_user(distinct_id, modifiers, callback)
---
delete an user record in engage
usage:
mixpanel.people.delete_user('bob');
*/
delete_user(distinct_id, modifiers, callback) {
const identifiers = { $distinct_id: distinct_id };
this._delete_profile({ identifiers, modifiers, callback });
}
/**
people.remove(distinct_id, data, modifiers, callback)
---
remove a value from a list-valued user profile property.
usage:
mixpanel.people.remove('bob', {'browsers': 'firefox'});
mixpanel.people.remove('bob', {'browsers': 'chrome', 'os': 'linux'});
*/
remove(distinct_id, data, modifiers, callback) {
const identifiers = { $distinct_id: distinct_id };
this._remove({ identifiers, data, modifiers, callback });
}
/**
people.union(distinct_id, data, modifiers, callback)
---
merge value(s) into a list-valued people analytics property.
usage:
mixpanel.people.union('bob', {'browsers': 'firefox'});
mixpanel.people.union('bob', {'browsers': ['chrome'], os: ['linux']});
*/
union(distinct_id, data, modifiers, callback) {
const identifiers = { $distinct_id: distinct_id };
this._union({ identifiers, data, modifiers, callback });
}
/**
people.unset(distinct_id, prop, modifiers, callback)
---
delete a property on an user record in engage
usage:
mixpanel.people.unset('bob', 'page_views');
mixpanel.people.unset('bob', ['page_views', 'last_login']);
*/
unset(distinct_id, prop, modifiers, callback) {
const identifiers = { $distinct_id: distinct_id };
this._unset({ identifiers, prop, modifiers, callback });
}
}
exports.MixpanelPeople = MixpanelPeople;