mixpanel-browser 2.43.0 → 2.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/mixpanel-jslib-snippet.min.js +3 -3
- package/dist/mixpanel-jslib-snippet.min.test.js +3 -3
- package/dist/mixpanel.amd.js +908 -2782
- package/dist/mixpanel.cjs.js +908 -2782
- package/dist/mixpanel.globals.js +908 -2782
- package/dist/mixpanel.min.js +100 -150
- package/dist/mixpanel.umd.js +908 -2782
- package/mixpanel-jslib-snippet.js +2 -2
- package/package.json +1 -1
- package/src/config.js +1 -1
- package/src/mixpanel-core.js +31 -106
- package/src/mixpanel-persistence.js +0 -21
- package/src/request-batcher.js +45 -8
- package/src/request-queue.js +55 -18
- package/src/utils.js +0 -48
- package/src/mixpanel-notification.js +0 -1309
- package/src/property-filters.js +0 -508
package/dist/mixpanel.globals.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
var Config = {
|
|
5
5
|
DEBUG: false,
|
|
6
|
-
LIB_VERSION: '2.
|
|
6
|
+
LIB_VERSION: '2.45.0'
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
|
|
@@ -37,11 +37,11 @@
|
|
|
37
37
|
var toString = ObjProto.toString;
|
|
38
38
|
var hasOwnProperty = ObjProto.hasOwnProperty;
|
|
39
39
|
var windowConsole = window$1.console;
|
|
40
|
-
var navigator
|
|
40
|
+
var navigator = window$1.navigator;
|
|
41
41
|
var document$1 = window$1.document;
|
|
42
42
|
var windowOpera = window$1.opera;
|
|
43
43
|
var screen = window$1.screen;
|
|
44
|
-
var userAgent = navigator
|
|
44
|
+
var userAgent = navigator.userAgent;
|
|
45
45
|
var nativeBind = FuncProto.bind;
|
|
46
46
|
var nativeForEach = ArrayProto.forEach;
|
|
47
47
|
var nativeIndexOf = ArrayProto.indexOf;
|
|
@@ -153,14 +153,6 @@
|
|
|
153
153
|
return bound;
|
|
154
154
|
};
|
|
155
155
|
|
|
156
|
-
_.bind_instance_methods = function(obj) {
|
|
157
|
-
for (var func in obj) {
|
|
158
|
-
if (typeof(obj[func]) === 'function') {
|
|
159
|
-
obj[func] = _.bind(obj[func], obj);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
};
|
|
163
|
-
|
|
164
156
|
/**
|
|
165
157
|
* @param {*=} obj
|
|
166
158
|
* @param {function(...*)=} iterator
|
|
@@ -189,19 +181,6 @@
|
|
|
189
181
|
}
|
|
190
182
|
};
|
|
191
183
|
|
|
192
|
-
_.escapeHTML = function(s) {
|
|
193
|
-
var escaped = s;
|
|
194
|
-
if (escaped && _.isString(escaped)) {
|
|
195
|
-
escaped = escaped
|
|
196
|
-
.replace(/&/g, '&')
|
|
197
|
-
.replace(/</g, '<')
|
|
198
|
-
.replace(/>/g, '>')
|
|
199
|
-
.replace(/"/g, '"')
|
|
200
|
-
.replace(/'/g, ''');
|
|
201
|
-
}
|
|
202
|
-
return escaped;
|
|
203
|
-
};
|
|
204
|
-
|
|
205
184
|
_.extend = function(obj) {
|
|
206
185
|
_.each(slice.call(arguments, 1), function(source) {
|
|
207
186
|
for (var prop in source) {
|
|
@@ -377,33 +356,6 @@
|
|
|
377
356
|
pad(d.getUTCSeconds());
|
|
378
357
|
};
|
|
379
358
|
|
|
380
|
-
_.safewrap = function(f) {
|
|
381
|
-
return function() {
|
|
382
|
-
try {
|
|
383
|
-
return f.apply(this, arguments);
|
|
384
|
-
} catch (e) {
|
|
385
|
-
console.critical('Implementation error. Please turn on debug and contact support@mixpanel.com.');
|
|
386
|
-
if (Config.DEBUG){
|
|
387
|
-
console.critical(e);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
};
|
|
391
|
-
};
|
|
392
|
-
|
|
393
|
-
_.safewrap_class = function(klass, functions) {
|
|
394
|
-
for (var i = 0; i < functions.length; i++) {
|
|
395
|
-
klass.prototype[functions[i]] = _.safewrap(klass.prototype[functions[i]]);
|
|
396
|
-
}
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
_.safewrap_instance_methods = function(obj) {
|
|
400
|
-
for (var func in obj) {
|
|
401
|
-
if (typeof(obj[func]) === 'function') {
|
|
402
|
-
obj[func] = _.safewrap(obj[func]);
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
|
|
407
359
|
_.strip_empty_properties = function(p) {
|
|
408
360
|
var ret = {};
|
|
409
361
|
_.each(p, function(v, k) {
|
|
@@ -1647,13 +1599,13 @@
|
|
|
1647
1599
|
properties: function() {
|
|
1648
1600
|
return _.extend(_.strip_empty_properties({
|
|
1649
1601
|
'$os': _.info.os(),
|
|
1650
|
-
'$browser': _.info.browser(userAgent, navigator
|
|
1602
|
+
'$browser': _.info.browser(userAgent, navigator.vendor, windowOpera),
|
|
1651
1603
|
'$referrer': document$1.referrer,
|
|
1652
1604
|
'$referring_domain': _.info.referringDomain(document$1.referrer),
|
|
1653
1605
|
'$device': _.info.device(userAgent)
|
|
1654
1606
|
}), {
|
|
1655
1607
|
'$current_url': window$1.location.href,
|
|
1656
|
-
'$browser_version': _.info.browserVersion(userAgent, navigator
|
|
1608
|
+
'$browser_version': _.info.browserVersion(userAgent, navigator.vendor, windowOpera),
|
|
1657
1609
|
'$screen_height': screen.height,
|
|
1658
1610
|
'$screen_width': screen.width,
|
|
1659
1611
|
'mp_lib': 'web',
|
|
@@ -1666,9 +1618,9 @@
|
|
|
1666
1618
|
people_properties: function() {
|
|
1667
1619
|
return _.extend(_.strip_empty_properties({
|
|
1668
1620
|
'$os': _.info.os(),
|
|
1669
|
-
'$browser': _.info.browser(userAgent, navigator
|
|
1621
|
+
'$browser': _.info.browser(userAgent, navigator.vendor, windowOpera)
|
|
1670
1622
|
}), {
|
|
1671
|
-
'$browser_version': _.info.browserVersion(userAgent, navigator
|
|
1623
|
+
'$browser_version': _.info.browserVersion(userAgent, navigator.vendor, windowOpera)
|
|
1672
1624
|
});
|
|
1673
1625
|
},
|
|
1674
1626
|
|
|
@@ -1676,7 +1628,7 @@
|
|
|
1676
1628
|
return _.strip_empty_properties({
|
|
1677
1629
|
'mp_page': page,
|
|
1678
1630
|
'mp_referrer': document$1.referrer,
|
|
1679
|
-
'mp_browser': _.info.browser(userAgent, navigator
|
|
1631
|
+
'mp_browser': _.info.browser(userAgent, navigator.vendor, windowOpera),
|
|
1680
1632
|
'mp_platform': _.info.os()
|
|
1681
1633
|
});
|
|
1682
1634
|
}
|
|
@@ -2058,6 +2010,7 @@
|
|
|
2058
2010
|
options = options || {};
|
|
2059
2011
|
this.storageKey = storageKey;
|
|
2060
2012
|
this.storage = options.storage || window.localStorage;
|
|
2013
|
+
this.reportError = options.errorReporter || _.bind(logger$1.error, logger$1);
|
|
2061
2014
|
this.lock = new SharedLock(storageKey, {storage: this.storage});
|
|
2062
2015
|
|
|
2063
2016
|
this.pid = options.pid || null; // pass pid to test out storage lock contention scenarios
|
|
@@ -2095,18 +2048,18 @@
|
|
|
2095
2048
|
this.memQueue.push(queueEntry);
|
|
2096
2049
|
}
|
|
2097
2050
|
} catch(err) {
|
|
2098
|
-
|
|
2051
|
+
this.reportError('Error enqueueing item', item);
|
|
2099
2052
|
succeeded = false;
|
|
2100
2053
|
}
|
|
2101
2054
|
if (cb) {
|
|
2102
2055
|
cb(succeeded);
|
|
2103
2056
|
}
|
|
2104
|
-
}, this), function lockFailure(err) {
|
|
2105
|
-
|
|
2057
|
+
}, this), _.bind(function lockFailure(err) {
|
|
2058
|
+
this.reportError('Error acquiring storage lock', err);
|
|
2106
2059
|
if (cb) {
|
|
2107
2060
|
cb(false);
|
|
2108
2061
|
}
|
|
2109
|
-
}, this.pid);
|
|
2062
|
+
}, this), this.pid);
|
|
2110
2063
|
};
|
|
2111
2064
|
|
|
2112
2065
|
/**
|
|
@@ -2166,25 +2119,61 @@
|
|
|
2166
2119
|
_.each(ids, function(id) { idSet[id] = true; });
|
|
2167
2120
|
|
|
2168
2121
|
this.memQueue = filterOutIDsAndInvalid(this.memQueue, idSet);
|
|
2169
|
-
|
|
2122
|
+
|
|
2123
|
+
var removeFromStorage = _.bind(function() {
|
|
2170
2124
|
var succeeded;
|
|
2171
2125
|
try {
|
|
2172
2126
|
var storedQueue = this.readFromStorage();
|
|
2173
2127
|
storedQueue = filterOutIDsAndInvalid(storedQueue, idSet);
|
|
2174
2128
|
succeeded = this.saveToStorage(storedQueue);
|
|
2129
|
+
|
|
2130
|
+
// an extra check: did storage report success but somehow
|
|
2131
|
+
// the items are still there?
|
|
2132
|
+
if (succeeded) {
|
|
2133
|
+
storedQueue = this.readFromStorage();
|
|
2134
|
+
for (var i = 0; i < storedQueue.length; i++) {
|
|
2135
|
+
var item = storedQueue[i];
|
|
2136
|
+
if (item['id'] && !!idSet[item['id']]) {
|
|
2137
|
+
this.reportError('Item not removed from storage');
|
|
2138
|
+
return false;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2175
2142
|
} catch(err) {
|
|
2176
|
-
|
|
2143
|
+
this.reportError('Error removing items', ids);
|
|
2177
2144
|
succeeded = false;
|
|
2178
2145
|
}
|
|
2146
|
+
return succeeded;
|
|
2147
|
+
}, this);
|
|
2148
|
+
|
|
2149
|
+
this.lock.withLock(function lockAcquired() {
|
|
2150
|
+
var succeeded = removeFromStorage();
|
|
2179
2151
|
if (cb) {
|
|
2180
2152
|
cb(succeeded);
|
|
2181
2153
|
}
|
|
2182
|
-
},
|
|
2183
|
-
|
|
2154
|
+
}, _.bind(function lockFailure(err) {
|
|
2155
|
+
var succeeded = false;
|
|
2156
|
+
this.reportError('Error acquiring storage lock', err);
|
|
2157
|
+
if (!localStorageSupported(this.storage, true)) {
|
|
2158
|
+
// Looks like localStorage writes have stopped working sometime after
|
|
2159
|
+
// initialization (probably full), and so nobody can acquire locks
|
|
2160
|
+
// anymore. Consider it temporarily safe to remove items without the
|
|
2161
|
+
// lock, since nobody's writing successfully anyway.
|
|
2162
|
+
succeeded = removeFromStorage();
|
|
2163
|
+
if (!succeeded) {
|
|
2164
|
+
// OK, we couldn't even write out the smaller queue. Try clearing it
|
|
2165
|
+
// entirely.
|
|
2166
|
+
try {
|
|
2167
|
+
this.storage.removeItem(this.storageKey);
|
|
2168
|
+
} catch(err) {
|
|
2169
|
+
this.reportError('Error clearing queue', err);
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2184
2173
|
if (cb) {
|
|
2185
|
-
cb(
|
|
2174
|
+
cb(succeeded);
|
|
2186
2175
|
}
|
|
2187
|
-
}, this.pid);
|
|
2176
|
+
}, this), this.pid);
|
|
2188
2177
|
};
|
|
2189
2178
|
|
|
2190
2179
|
// internal helper for RequestQueue.updatePayloads
|
|
@@ -2219,18 +2208,18 @@
|
|
|
2219
2208
|
storedQueue = updatePayloads(storedQueue, itemsToUpdate);
|
|
2220
2209
|
succeeded = this.saveToStorage(storedQueue);
|
|
2221
2210
|
} catch(err) {
|
|
2222
|
-
|
|
2211
|
+
this.reportError('Error updating items', itemsToUpdate);
|
|
2223
2212
|
succeeded = false;
|
|
2224
2213
|
}
|
|
2225
2214
|
if (cb) {
|
|
2226
2215
|
cb(succeeded);
|
|
2227
2216
|
}
|
|
2228
|
-
}, this), function lockFailure(err) {
|
|
2229
|
-
|
|
2217
|
+
}, this), _.bind(function lockFailure(err) {
|
|
2218
|
+
this.reportError('Error acquiring storage lock', err);
|
|
2230
2219
|
if (cb) {
|
|
2231
2220
|
cb(false);
|
|
2232
2221
|
}
|
|
2233
|
-
}, this.pid);
|
|
2222
|
+
}, this), this.pid);
|
|
2234
2223
|
};
|
|
2235
2224
|
|
|
2236
2225
|
/**
|
|
@@ -2244,12 +2233,12 @@
|
|
|
2244
2233
|
if (storageEntry) {
|
|
2245
2234
|
storageEntry = JSONParse(storageEntry);
|
|
2246
2235
|
if (!_.isArray(storageEntry)) {
|
|
2247
|
-
|
|
2236
|
+
this.reportError('Invalid storage entry:', storageEntry);
|
|
2248
2237
|
storageEntry = null;
|
|
2249
2238
|
}
|
|
2250
2239
|
}
|
|
2251
2240
|
} catch (err) {
|
|
2252
|
-
|
|
2241
|
+
this.reportError('Error retrieving queue', err);
|
|
2253
2242
|
storageEntry = null;
|
|
2254
2243
|
}
|
|
2255
2244
|
return storageEntry || [];
|
|
@@ -2263,7 +2252,7 @@
|
|
|
2263
2252
|
this.storage.setItem(this.storageKey, JSONStringify(queue));
|
|
2264
2253
|
return true;
|
|
2265
2254
|
} catch (err) {
|
|
2266
|
-
|
|
2255
|
+
this.reportError('Error saving queue', err);
|
|
2267
2256
|
return false;
|
|
2268
2257
|
}
|
|
2269
2258
|
};
|
|
@@ -2290,17 +2279,23 @@
|
|
|
2290
2279
|
* @constructor
|
|
2291
2280
|
*/
|
|
2292
2281
|
var RequestBatcher = function(storageKey, options) {
|
|
2293
|
-
this.
|
|
2282
|
+
this.errorReporter = options.errorReporter;
|
|
2283
|
+
this.queue = new RequestQueue(storageKey, {
|
|
2284
|
+
errorReporter: _.bind(this.reportError, this),
|
|
2285
|
+
storage: options.storage
|
|
2286
|
+
});
|
|
2294
2287
|
|
|
2295
2288
|
this.libConfig = options.libConfig;
|
|
2296
2289
|
this.sendRequest = options.sendRequestFunc;
|
|
2297
2290
|
this.beforeSendHook = options.beforeSendHook;
|
|
2291
|
+
this.stopAllBatching = options.stopAllBatchingFunc;
|
|
2298
2292
|
|
|
2299
2293
|
// seed variable batch size + flush interval with configured values
|
|
2300
2294
|
this.batchSize = this.libConfig['batch_size'];
|
|
2301
2295
|
this.flushInterval = this.libConfig['batch_flush_interval_ms'];
|
|
2302
2296
|
|
|
2303
2297
|
this.stopped = !this.libConfig['batch_autostart'];
|
|
2298
|
+
this.consecutiveRemovalFailures = 0;
|
|
2304
2299
|
};
|
|
2305
2300
|
|
|
2306
2301
|
/**
|
|
@@ -2316,6 +2311,7 @@
|
|
|
2316
2311
|
*/
|
|
2317
2312
|
RequestBatcher.prototype.start = function() {
|
|
2318
2313
|
this.stopped = false;
|
|
2314
|
+
this.consecutiveRemovalFailures = 0;
|
|
2319
2315
|
this.flush();
|
|
2320
2316
|
};
|
|
2321
2317
|
|
|
@@ -2420,7 +2416,7 @@
|
|
|
2420
2416
|
res.error === 'timeout' &&
|
|
2421
2417
|
new Date().getTime() - startTime >= timeoutMS
|
|
2422
2418
|
) {
|
|
2423
|
-
|
|
2419
|
+
this.reportError('Network timeout; retrying');
|
|
2424
2420
|
this.flush();
|
|
2425
2421
|
} else if (
|
|
2426
2422
|
_.isObject(res) &&
|
|
@@ -2437,17 +2433,17 @@
|
|
|
2437
2433
|
}
|
|
2438
2434
|
}
|
|
2439
2435
|
retryMS = Math.min(MAX_RETRY_INTERVAL_MS, retryMS);
|
|
2440
|
-
|
|
2436
|
+
this.reportError('Error; retry in ' + retryMS + ' ms');
|
|
2441
2437
|
this.scheduleFlush(retryMS);
|
|
2442
2438
|
} else if (_.isObject(res) && res.xhr_req && res.xhr_req['status'] === 413) {
|
|
2443
2439
|
// 413 Payload Too Large
|
|
2444
2440
|
if (batch.length > 1) {
|
|
2445
2441
|
var halvedBatchSize = Math.max(1, Math.floor(currentBatchSize / 2));
|
|
2446
2442
|
this.batchSize = Math.min(this.batchSize, halvedBatchSize, batch.length - 1);
|
|
2447
|
-
|
|
2443
|
+
this.reportError('413 response; reducing batch size to ' + this.batchSize);
|
|
2448
2444
|
this.resetFlush();
|
|
2449
2445
|
} else {
|
|
2450
|
-
|
|
2446
|
+
this.reportError('Single-event request too large; dropping', batch);
|
|
2451
2447
|
this.resetBatchSize();
|
|
2452
2448
|
removeItemsFromQueue = true;
|
|
2453
2449
|
}
|
|
@@ -2460,12 +2456,25 @@
|
|
|
2460
2456
|
if (removeItemsFromQueue) {
|
|
2461
2457
|
this.queue.removeItemsByID(
|
|
2462
2458
|
_.map(batch, function(item) { return item['id']; }),
|
|
2463
|
-
_.bind(
|
|
2459
|
+
_.bind(function(succeeded) {
|
|
2460
|
+
if (succeeded) {
|
|
2461
|
+
this.consecutiveRemovalFailures = 0;
|
|
2462
|
+
this.flush(); // handle next batch if the queue isn't empty
|
|
2463
|
+
} else {
|
|
2464
|
+
this.reportError('Failed to remove items from queue');
|
|
2465
|
+
if (++this.consecutiveRemovalFailures > 5) {
|
|
2466
|
+
this.reportError('Too many queue failures; disabling batching system.');
|
|
2467
|
+
this.stopAllBatching();
|
|
2468
|
+
} else {
|
|
2469
|
+
this.resetFlush();
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
}, this)
|
|
2464
2473
|
);
|
|
2465
2474
|
}
|
|
2466
2475
|
|
|
2467
2476
|
} catch(err) {
|
|
2468
|
-
|
|
2477
|
+
this.reportError('Error handling API response', err);
|
|
2469
2478
|
this.resetFlush();
|
|
2470
2479
|
}
|
|
2471
2480
|
}, this);
|
|
@@ -2482,11 +2491,28 @@
|
|
|
2482
2491
|
this.sendRequest(dataForRequest, requestOptions, batchSendCallback);
|
|
2483
2492
|
|
|
2484
2493
|
} catch(err) {
|
|
2485
|
-
|
|
2494
|
+
this.reportError('Error flushing request queue', err);
|
|
2486
2495
|
this.resetFlush();
|
|
2487
2496
|
}
|
|
2488
2497
|
};
|
|
2489
2498
|
|
|
2499
|
+
/**
|
|
2500
|
+
* Log error to global logger and optional user-defined logger.
|
|
2501
|
+
*/
|
|
2502
|
+
RequestBatcher.prototype.reportError = function(msg, err) {
|
|
2503
|
+
logger.error.apply(logger.error, arguments);
|
|
2504
|
+
if (this.errorReporter) {
|
|
2505
|
+
try {
|
|
2506
|
+
if (!(err instanceof Error)) {
|
|
2507
|
+
err = new Error(msg);
|
|
2508
|
+
}
|
|
2509
|
+
this.errorReporter(msg, err);
|
|
2510
|
+
} catch(err) {
|
|
2511
|
+
logger.error(err);
|
|
2512
|
+
}
|
|
2513
|
+
}
|
|
2514
|
+
};
|
|
2515
|
+
|
|
2490
2516
|
/**
|
|
2491
2517
|
* A function used to track a Mixpanel event (e.g. MixpanelLib.track)
|
|
2492
2518
|
* @callback trackFunction
|
|
@@ -3058,2755 +3084,929 @@
|
|
|
3058
3084
|
MixpanelGroup.prototype['unset'] = MixpanelGroup.prototype.unset;
|
|
3059
3085
|
MixpanelGroup.prototype['toString'] = MixpanelGroup.prototype.toString;
|
|
3060
3086
|
|
|
3061
|
-
/*
|
|
3062
|
-
* Constants
|
|
3063
|
-
*/
|
|
3064
|
-
/** @const */ var SET_QUEUE_KEY = '__mps';
|
|
3065
|
-
/** @const */ var SET_ONCE_QUEUE_KEY = '__mpso';
|
|
3066
|
-
/** @const */ var UNSET_QUEUE_KEY = '__mpus';
|
|
3067
|
-
/** @const */ var ADD_QUEUE_KEY = '__mpa';
|
|
3068
|
-
/** @const */ var APPEND_QUEUE_KEY = '__mpap';
|
|
3069
|
-
/** @const */ var REMOVE_QUEUE_KEY = '__mpr';
|
|
3070
|
-
/** @const */ var UNION_QUEUE_KEY = '__mpu';
|
|
3071
|
-
// This key is deprecated, but we want to check for it to see whether aliasing is allowed.
|
|
3072
|
-
/** @const */ var PEOPLE_DISTINCT_ID_KEY = '$people_distinct_id';
|
|
3073
|
-
/** @const */ var ALIAS_ID_KEY = '__alias';
|
|
3074
|
-
/** @const */ var CAMPAIGN_IDS_KEY = '__cmpns';
|
|
3075
|
-
/** @const */ var EVENT_TIMERS_KEY = '__timers';
|
|
3076
|
-
/** @const */ var RESERVED_PROPERTIES = [
|
|
3077
|
-
SET_QUEUE_KEY,
|
|
3078
|
-
SET_ONCE_QUEUE_KEY,
|
|
3079
|
-
UNSET_QUEUE_KEY,
|
|
3080
|
-
ADD_QUEUE_KEY,
|
|
3081
|
-
APPEND_QUEUE_KEY,
|
|
3082
|
-
REMOVE_QUEUE_KEY,
|
|
3083
|
-
UNION_QUEUE_KEY,
|
|
3084
|
-
PEOPLE_DISTINCT_ID_KEY,
|
|
3085
|
-
ALIAS_ID_KEY,
|
|
3086
|
-
CAMPAIGN_IDS_KEY,
|
|
3087
|
-
EVENT_TIMERS_KEY
|
|
3088
|
-
];
|
|
3089
|
-
|
|
3090
3087
|
/**
|
|
3091
|
-
* Mixpanel
|
|
3088
|
+
* Mixpanel People Object
|
|
3092
3089
|
* @constructor
|
|
3093
3090
|
*/
|
|
3094
|
-
var
|
|
3095
|
-
this['props'] = {};
|
|
3096
|
-
this.campaign_params_saved = false;
|
|
3097
|
-
|
|
3098
|
-
if (config['persistence_name']) {
|
|
3099
|
-
this.name = 'mp_' + config['persistence_name'];
|
|
3100
|
-
} else {
|
|
3101
|
-
this.name = 'mp_' + config['token'] + '_mixpanel';
|
|
3102
|
-
}
|
|
3103
|
-
|
|
3104
|
-
var storage_type = config['persistence'];
|
|
3105
|
-
if (storage_type !== 'cookie' && storage_type !== 'localStorage') {
|
|
3106
|
-
console.critical('Unknown persistence type ' + storage_type + '; falling back to cookie');
|
|
3107
|
-
storage_type = config['persistence'] = 'cookie';
|
|
3108
|
-
}
|
|
3109
|
-
|
|
3110
|
-
if (storage_type === 'localStorage' && _.localStorage.is_supported()) {
|
|
3111
|
-
this.storage = _.localStorage;
|
|
3112
|
-
} else {
|
|
3113
|
-
this.storage = _.cookie;
|
|
3114
|
-
}
|
|
3091
|
+
var MixpanelPeople = function() {};
|
|
3115
3092
|
|
|
3116
|
-
|
|
3117
|
-
this.update_config(config);
|
|
3118
|
-
this.upgrade(config);
|
|
3119
|
-
this.save();
|
|
3120
|
-
};
|
|
3093
|
+
_.extend(MixpanelPeople.prototype, apiActions);
|
|
3121
3094
|
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
// Filter out reserved properties
|
|
3125
|
-
_.each(this['props'], function(v, k) {
|
|
3126
|
-
if (!_.include(RESERVED_PROPERTIES, k)) {
|
|
3127
|
-
p[k] = v;
|
|
3128
|
-
}
|
|
3129
|
-
});
|
|
3130
|
-
return p;
|
|
3095
|
+
MixpanelPeople.prototype._init = function(mixpanel_instance) {
|
|
3096
|
+
this._mixpanel = mixpanel_instance;
|
|
3131
3097
|
};
|
|
3132
3098
|
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3099
|
+
/*
|
|
3100
|
+
* Set properties on a user record.
|
|
3101
|
+
*
|
|
3102
|
+
* ### Usage:
|
|
3103
|
+
*
|
|
3104
|
+
* mixpanel.people.set('gender', 'm');
|
|
3105
|
+
*
|
|
3106
|
+
* // or set multiple properties at once
|
|
3107
|
+
* mixpanel.people.set({
|
|
3108
|
+
* 'Company': 'Acme',
|
|
3109
|
+
* 'Plan': 'Premium',
|
|
3110
|
+
* 'Upgrade date': new Date()
|
|
3111
|
+
* });
|
|
3112
|
+
* // properties can be strings, integers, dates, or lists
|
|
3113
|
+
*
|
|
3114
|
+
* @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
3115
|
+
* @param {*} [to] A value to set on the given property name
|
|
3116
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3117
|
+
*/
|
|
3118
|
+
MixpanelPeople.prototype.set = addOptOutCheckMixpanelPeople(function(prop, to, callback) {
|
|
3119
|
+
var data = this.set_action(prop, to);
|
|
3120
|
+
if (_.isObject(prop)) {
|
|
3121
|
+
callback = to;
|
|
3140
3122
|
}
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
var upgrade_from_old_lib = config['upgrade'],
|
|
3145
|
-
old_cookie_name,
|
|
3146
|
-
old_cookie;
|
|
3147
|
-
|
|
3148
|
-
if (upgrade_from_old_lib) {
|
|
3149
|
-
old_cookie_name = 'mp_super_properties';
|
|
3150
|
-
// Case where they had a custom cookie name before.
|
|
3151
|
-
if (typeof(upgrade_from_old_lib) === 'string') {
|
|
3152
|
-
old_cookie_name = upgrade_from_old_lib;
|
|
3153
|
-
}
|
|
3154
|
-
|
|
3155
|
-
old_cookie = this.storage.parse(old_cookie_name);
|
|
3156
|
-
|
|
3157
|
-
// remove the cookie
|
|
3158
|
-
this.storage.remove(old_cookie_name);
|
|
3159
|
-
this.storage.remove(old_cookie_name, true);
|
|
3160
|
-
|
|
3161
|
-
if (old_cookie) {
|
|
3162
|
-
this['props'] = _.extend(
|
|
3163
|
-
this['props'],
|
|
3164
|
-
old_cookie['all'],
|
|
3165
|
-
old_cookie['events']
|
|
3166
|
-
);
|
|
3167
|
-
}
|
|
3123
|
+
// make sure that the referrer info has been updated and saved
|
|
3124
|
+
if (this._get_config('save_referrer')) {
|
|
3125
|
+
this._mixpanel['persistence'].update_referrer_info(document.referrer);
|
|
3168
3126
|
}
|
|
3169
3127
|
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
|
|
3175
|
-
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3128
|
+
// update $set object with default people properties
|
|
3129
|
+
data[SET_ACTION] = _.extend(
|
|
3130
|
+
{},
|
|
3131
|
+
_.info.people_properties(),
|
|
3132
|
+
this._mixpanel['persistence'].get_referrer_info(),
|
|
3133
|
+
data[SET_ACTION]
|
|
3134
|
+
);
|
|
3135
|
+
return this._send_request(data, callback);
|
|
3136
|
+
});
|
|
3179
3137
|
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3138
|
+
/*
|
|
3139
|
+
* Set properties on a user record, only if they do not yet exist.
|
|
3140
|
+
* This will not overwrite previous people property values, unlike
|
|
3141
|
+
* people.set().
|
|
3142
|
+
*
|
|
3143
|
+
* ### Usage:
|
|
3144
|
+
*
|
|
3145
|
+
* mixpanel.people.set_once('First Login Date', new Date());
|
|
3146
|
+
*
|
|
3147
|
+
* // or set multiple properties at once
|
|
3148
|
+
* mixpanel.people.set_once({
|
|
3149
|
+
* 'First Login Date': new Date(),
|
|
3150
|
+
* 'Starting Plan': 'Premium'
|
|
3151
|
+
* });
|
|
3152
|
+
*
|
|
3153
|
+
* // properties can be strings, integers or dates
|
|
3154
|
+
*
|
|
3155
|
+
* @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
3156
|
+
* @param {*} [to] A value to set on the given property name
|
|
3157
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3158
|
+
*/
|
|
3159
|
+
MixpanelPeople.prototype.set_once = addOptOutCheckMixpanelPeople(function(prop, to, callback) {
|
|
3160
|
+
var data = this.set_once_action(prop, to);
|
|
3161
|
+
if (_.isObject(prop)) {
|
|
3162
|
+
callback = to;
|
|
3184
3163
|
}
|
|
3164
|
+
return this._send_request(data, callback);
|
|
3165
|
+
});
|
|
3185
3166
|
|
|
3186
|
-
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
}
|
|
3167
|
+
/*
|
|
3168
|
+
* Unset properties on a user record (permanently removes the properties and their values from a profile).
|
|
3169
|
+
*
|
|
3170
|
+
* ### Usage:
|
|
3171
|
+
*
|
|
3172
|
+
* mixpanel.people.unset('gender');
|
|
3173
|
+
*
|
|
3174
|
+
* // or unset multiple properties at once
|
|
3175
|
+
* mixpanel.people.unset(['gender', 'Company']);
|
|
3176
|
+
*
|
|
3177
|
+
* @param {Array|String} prop If a string, this is the name of the property. If an array, this is a list of property names.
|
|
3178
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3179
|
+
*/
|
|
3180
|
+
MixpanelPeople.prototype.unset = addOptOutCheckMixpanelPeople(function(prop, callback) {
|
|
3181
|
+
var data = this.unset_action(prop);
|
|
3182
|
+
return this._send_request(data, callback);
|
|
3183
|
+
});
|
|
3197
3184
|
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3215
|
-
|
|
3216
|
-
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3222
|
-
this['props'] = {};
|
|
3223
|
-
};
|
|
3224
|
-
|
|
3225
|
-
/**
|
|
3226
|
-
* @param {Object} props
|
|
3227
|
-
* @param {*=} default_value
|
|
3228
|
-
* @param {number=} days
|
|
3185
|
+
/*
|
|
3186
|
+
* Increment/decrement numeric people analytics properties.
|
|
3187
|
+
*
|
|
3188
|
+
* ### Usage:
|
|
3189
|
+
*
|
|
3190
|
+
* mixpanel.people.increment('page_views', 1);
|
|
3191
|
+
*
|
|
3192
|
+
* // or, for convenience, if you're just incrementing a counter by
|
|
3193
|
+
* // 1, you can simply do
|
|
3194
|
+
* mixpanel.people.increment('page_views');
|
|
3195
|
+
*
|
|
3196
|
+
* // to decrement a counter, pass a negative number
|
|
3197
|
+
* mixpanel.people.increment('credits_left', -1);
|
|
3198
|
+
*
|
|
3199
|
+
* // like mixpanel.people.set(), you can increment multiple
|
|
3200
|
+
* // properties at once:
|
|
3201
|
+
* mixpanel.people.increment({
|
|
3202
|
+
* counter1: 1,
|
|
3203
|
+
* counter2: 6
|
|
3204
|
+
* });
|
|
3205
|
+
*
|
|
3206
|
+
* @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and numeric values.
|
|
3207
|
+
* @param {Number} [by] An amount to increment the given property
|
|
3208
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3229
3209
|
*/
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3210
|
+
MixpanelPeople.prototype.increment = addOptOutCheckMixpanelPeople(function(prop, by, callback) {
|
|
3211
|
+
var data = {};
|
|
3212
|
+
var $add = {};
|
|
3213
|
+
if (_.isObject(prop)) {
|
|
3214
|
+
_.each(prop, function(v, k) {
|
|
3215
|
+
if (!this._is_reserved_property(k)) {
|
|
3216
|
+
if (isNaN(parseFloat(v))) {
|
|
3217
|
+
console.error('Invalid increment value passed to mixpanel.people.increment - must be a number');
|
|
3218
|
+
return;
|
|
3219
|
+
} else {
|
|
3220
|
+
$add[k] = v;
|
|
3221
|
+
}
|
|
3238
3222
|
}
|
|
3239
3223
|
}, this);
|
|
3224
|
+
callback = by;
|
|
3225
|
+
} else {
|
|
3226
|
+
// convenience: mixpanel.people.increment('property'); will
|
|
3227
|
+
// increment 'property' by 1
|
|
3228
|
+
if (_.isUndefined(by)) {
|
|
3229
|
+
by = 1;
|
|
3230
|
+
}
|
|
3231
|
+
$add[prop] = by;
|
|
3232
|
+
}
|
|
3233
|
+
data[ADD_ACTION] = $add;
|
|
3240
3234
|
|
|
3241
|
-
|
|
3235
|
+
return this._send_request(data, callback);
|
|
3236
|
+
});
|
|
3242
3237
|
|
|
3243
|
-
|
|
3238
|
+
/*
|
|
3239
|
+
* Append a value to a list-valued people analytics property.
|
|
3240
|
+
*
|
|
3241
|
+
* ### Usage:
|
|
3242
|
+
*
|
|
3243
|
+
* // append a value to a list, creating it if needed
|
|
3244
|
+
* mixpanel.people.append('pages_visited', 'homepage');
|
|
3245
|
+
*
|
|
3246
|
+
* // like mixpanel.people.set(), you can append multiple
|
|
3247
|
+
* // properties at once:
|
|
3248
|
+
* mixpanel.people.append({
|
|
3249
|
+
* list1: 'bob',
|
|
3250
|
+
* list2: 123
|
|
3251
|
+
* });
|
|
3252
|
+
*
|
|
3253
|
+
* @param {Object|String} list_name If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
3254
|
+
* @param {*} [value] value An item to append to the list
|
|
3255
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3256
|
+
*/
|
|
3257
|
+
MixpanelPeople.prototype.append = addOptOutCheckMixpanelPeople(function(list_name, value, callback) {
|
|
3258
|
+
if (_.isObject(list_name)) {
|
|
3259
|
+
callback = value;
|
|
3244
3260
|
}
|
|
3245
|
-
|
|
3246
|
-
|
|
3261
|
+
var data = this.append_action(list_name, value);
|
|
3262
|
+
return this._send_request(data, callback);
|
|
3263
|
+
});
|
|
3247
3264
|
|
|
3248
|
-
|
|
3249
|
-
*
|
|
3250
|
-
*
|
|
3265
|
+
/*
|
|
3266
|
+
* Remove a value from a list-valued people analytics property.
|
|
3267
|
+
*
|
|
3268
|
+
* ### Usage:
|
|
3269
|
+
*
|
|
3270
|
+
* mixpanel.people.remove('School', 'UCB');
|
|
3271
|
+
*
|
|
3272
|
+
* @param {Object|String} list_name If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
3273
|
+
* @param {*} [value] value Item to remove from the list
|
|
3274
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3251
3275
|
*/
|
|
3252
|
-
|
|
3253
|
-
if (_.isObject(
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
_.extend(this['props'], props);
|
|
3257
|
-
|
|
3258
|
-
this.save();
|
|
3259
|
-
|
|
3260
|
-
return true;
|
|
3276
|
+
MixpanelPeople.prototype.remove = addOptOutCheckMixpanelPeople(function(list_name, value, callback) {
|
|
3277
|
+
if (_.isObject(list_name)) {
|
|
3278
|
+
callback = value;
|
|
3261
3279
|
}
|
|
3262
|
-
|
|
3263
|
-
|
|
3280
|
+
var data = this.remove_action(list_name, value);
|
|
3281
|
+
return this._send_request(data, callback);
|
|
3282
|
+
});
|
|
3264
3283
|
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3284
|
+
/*
|
|
3285
|
+
* Merge a given list with a list-valued people analytics property,
|
|
3286
|
+
* excluding duplicate values.
|
|
3287
|
+
*
|
|
3288
|
+
* ### Usage:
|
|
3289
|
+
*
|
|
3290
|
+
* // merge a value to a list, creating it if needed
|
|
3291
|
+
* mixpanel.people.union('pages_visited', 'homepage');
|
|
3292
|
+
*
|
|
3293
|
+
* // like mixpanel.people.set(), you can append multiple
|
|
3294
|
+
* // properties at once:
|
|
3295
|
+
* mixpanel.people.union({
|
|
3296
|
+
* list1: 'bob',
|
|
3297
|
+
* list2: 123
|
|
3298
|
+
* });
|
|
3299
|
+
*
|
|
3300
|
+
* // like mixpanel.people.append(), you can append multiple
|
|
3301
|
+
* // values to the same list:
|
|
3302
|
+
* mixpanel.people.union({
|
|
3303
|
+
* list1: ['bob', 'billy']
|
|
3304
|
+
* });
|
|
3305
|
+
*
|
|
3306
|
+
* @param {Object|String} list_name If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
3307
|
+
* @param {*} [value] Value / values to merge with the given property
|
|
3308
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3309
|
+
*/
|
|
3310
|
+
MixpanelPeople.prototype.union = addOptOutCheckMixpanelPeople(function(list_name, values, callback) {
|
|
3311
|
+
if (_.isObject(list_name)) {
|
|
3312
|
+
callback = values;
|
|
3269
3313
|
}
|
|
3270
|
-
|
|
3314
|
+
var data = this.union_action(list_name, values);
|
|
3315
|
+
return this._send_request(data, callback);
|
|
3316
|
+
});
|
|
3271
3317
|
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3318
|
+
/*
|
|
3319
|
+
* Record that you have charged the current user a certain amount
|
|
3320
|
+
* of money. Charges recorded with track_charge() will appear in the
|
|
3321
|
+
* Mixpanel revenue report.
|
|
3322
|
+
*
|
|
3323
|
+
* ### Usage:
|
|
3324
|
+
*
|
|
3325
|
+
* // charge a user $50
|
|
3326
|
+
* mixpanel.people.track_charge(50);
|
|
3327
|
+
*
|
|
3328
|
+
* // charge a user $30.50 on the 2nd of january
|
|
3329
|
+
* mixpanel.people.track_charge(30.50, {
|
|
3330
|
+
* '$time': new Date('jan 1 2012')
|
|
3331
|
+
* });
|
|
3332
|
+
*
|
|
3333
|
+
* @param {Number} amount The amount of money charged to the current user
|
|
3334
|
+
* @param {Object} [properties] An associative array of properties associated with the charge
|
|
3335
|
+
* @param {Function} [callback] If provided, the callback will be called when the server responds
|
|
3336
|
+
*/
|
|
3337
|
+
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function(amount, properties, callback) {
|
|
3338
|
+
if (!_.isNumber(amount)) {
|
|
3339
|
+
amount = parseFloat(amount);
|
|
3340
|
+
if (isNaN(amount)) {
|
|
3341
|
+
console.error('Invalid value passed to mixpanel.people.track_charge - must be a number');
|
|
3342
|
+
return;
|
|
3281
3343
|
}
|
|
3282
3344
|
}
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3345
|
+
|
|
3346
|
+
return this.append('$transactions', _.extend({
|
|
3347
|
+
'$amount': amount
|
|
3348
|
+
}, properties), callback);
|
|
3286
3349
|
});
|
|
3287
3350
|
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3351
|
+
/*
|
|
3352
|
+
* Permanently clear all revenue report transactions from the
|
|
3353
|
+
* current user's people analytics profile.
|
|
3354
|
+
*
|
|
3355
|
+
* ### Usage:
|
|
3356
|
+
*
|
|
3357
|
+
* mixpanel.people.clear_charges();
|
|
3358
|
+
*
|
|
3359
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3360
|
+
*/
|
|
3361
|
+
MixpanelPeople.prototype.clear_charges = function(callback) {
|
|
3362
|
+
return this.set('$transactions', [], callback);
|
|
3363
|
+
};
|
|
3364
|
+
|
|
3365
|
+
/*
|
|
3366
|
+
* Permanently deletes the current people analytics profile from
|
|
3367
|
+
* Mixpanel (using the current distinct_id).
|
|
3368
|
+
*
|
|
3369
|
+
* ### Usage:
|
|
3370
|
+
*
|
|
3371
|
+
* // remove the all data you have stored about the current user
|
|
3372
|
+
* mixpanel.people.delete_user();
|
|
3373
|
+
*
|
|
3374
|
+
*/
|
|
3375
|
+
MixpanelPeople.prototype.delete_user = function() {
|
|
3376
|
+
if (!this._identify_called()) {
|
|
3377
|
+
console.error('mixpanel.people.delete_user() requires you to call identify() first');
|
|
3378
|
+
return;
|
|
3292
3379
|
}
|
|
3380
|
+
var data = {'$delete': this._mixpanel.get_distinct_id()};
|
|
3381
|
+
return this._send_request(data);
|
|
3293
3382
|
};
|
|
3294
3383
|
|
|
3295
|
-
|
|
3296
|
-
this.
|
|
3384
|
+
MixpanelPeople.prototype.toString = function() {
|
|
3385
|
+
return this._mixpanel.toString() + '.people';
|
|
3297
3386
|
};
|
|
3298
3387
|
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
this.
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3388
|
+
MixpanelPeople.prototype._send_request = function(data, callback) {
|
|
3389
|
+
data['$token'] = this._get_config('token');
|
|
3390
|
+
data['$distinct_id'] = this._mixpanel.get_distinct_id();
|
|
3391
|
+
var device_id = this._mixpanel.get_property('$device_id');
|
|
3392
|
+
var user_id = this._mixpanel.get_property('$user_id');
|
|
3393
|
+
var had_persisted_distinct_id = this._mixpanel.get_property('$had_persisted_distinct_id');
|
|
3394
|
+
if (device_id) {
|
|
3395
|
+
data['$device_id'] = device_id;
|
|
3396
|
+
}
|
|
3397
|
+
if (user_id) {
|
|
3398
|
+
data['$user_id'] = user_id;
|
|
3399
|
+
}
|
|
3400
|
+
if (had_persisted_distinct_id) {
|
|
3401
|
+
data['$had_persisted_distinct_id'] = had_persisted_distinct_id;
|
|
3402
|
+
}
|
|
3307
3403
|
|
|
3308
|
-
|
|
3309
|
-
return _.strip_empty_properties({
|
|
3310
|
-
'$initial_referrer': this['props']['$initial_referrer'],
|
|
3311
|
-
'$initial_referring_domain': this['props']['$initial_referring_domain']
|
|
3312
|
-
});
|
|
3313
|
-
};
|
|
3404
|
+
var date_encoded_data = _.encodeDates(data);
|
|
3314
3405
|
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3406
|
+
if (!this._identify_called()) {
|
|
3407
|
+
this._enqueue(data);
|
|
3408
|
+
if (!_.isUndefined(callback)) {
|
|
3409
|
+
if (this._get_config('verbose')) {
|
|
3410
|
+
callback({status: -1, error: null});
|
|
3411
|
+
} else {
|
|
3412
|
+
callback(-1);
|
|
3413
|
+
}
|
|
3322
3414
|
}
|
|
3323
|
-
|
|
3415
|
+
return _.truncate(date_encoded_data, 255);
|
|
3416
|
+
}
|
|
3324
3417
|
|
|
3325
|
-
return
|
|
3418
|
+
return this._mixpanel._track_or_batch({
|
|
3419
|
+
type: 'people',
|
|
3420
|
+
data: date_encoded_data,
|
|
3421
|
+
endpoint: this._get_config('api_host') + '/engage/',
|
|
3422
|
+
batcher: this._mixpanel.request_batchers.people
|
|
3423
|
+
}, callback);
|
|
3326
3424
|
};
|
|
3327
3425
|
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
this.set_disabled(config['disable_persistence']);
|
|
3331
|
-
this.set_cookie_domain(config['cookie_domain']);
|
|
3332
|
-
this.set_cross_site(config['cross_site_cookie']);
|
|
3333
|
-
this.set_cross_subdomain(config['cross_subdomain_cookie']);
|
|
3334
|
-
this.set_secure(config['secure_cookie']);
|
|
3426
|
+
MixpanelPeople.prototype._get_config = function(conf_var) {
|
|
3427
|
+
return this._mixpanel.get_config(conf_var);
|
|
3335
3428
|
};
|
|
3336
3429
|
|
|
3337
|
-
|
|
3338
|
-
this.
|
|
3339
|
-
|
|
3340
|
-
|
|
3430
|
+
MixpanelPeople.prototype._identify_called = function() {
|
|
3431
|
+
return this._mixpanel._flags.identify_called === true;
|
|
3432
|
+
};
|
|
3433
|
+
|
|
3434
|
+
// Queue up engage operations if identify hasn't been called yet.
|
|
3435
|
+
MixpanelPeople.prototype._enqueue = function(data) {
|
|
3436
|
+
if (SET_ACTION in data) {
|
|
3437
|
+
this._mixpanel['persistence']._add_to_people_queue(SET_ACTION, data);
|
|
3438
|
+
} else if (SET_ONCE_ACTION in data) {
|
|
3439
|
+
this._mixpanel['persistence']._add_to_people_queue(SET_ONCE_ACTION, data);
|
|
3440
|
+
} else if (UNSET_ACTION in data) {
|
|
3441
|
+
this._mixpanel['persistence']._add_to_people_queue(UNSET_ACTION, data);
|
|
3442
|
+
} else if (ADD_ACTION in data) {
|
|
3443
|
+
this._mixpanel['persistence']._add_to_people_queue(ADD_ACTION, data);
|
|
3444
|
+
} else if (APPEND_ACTION in data) {
|
|
3445
|
+
this._mixpanel['persistence']._add_to_people_queue(APPEND_ACTION, data);
|
|
3446
|
+
} else if (REMOVE_ACTION in data) {
|
|
3447
|
+
this._mixpanel['persistence']._add_to_people_queue(REMOVE_ACTION, data);
|
|
3448
|
+
} else if (UNION_ACTION in data) {
|
|
3449
|
+
this._mixpanel['persistence']._add_to_people_queue(UNION_ACTION, data);
|
|
3341
3450
|
} else {
|
|
3342
|
-
|
|
3451
|
+
console.error('Invalid call to _enqueue():', data);
|
|
3343
3452
|
}
|
|
3344
3453
|
};
|
|
3345
3454
|
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3455
|
+
MixpanelPeople.prototype._flush_one_queue = function(action, action_method, callback, queue_to_params_fn) {
|
|
3456
|
+
var _this = this;
|
|
3457
|
+
var queued_data = _.extend({}, this._mixpanel['persistence']._get_queue(action));
|
|
3458
|
+
var action_params = queued_data;
|
|
3459
|
+
|
|
3460
|
+
if (!_.isUndefined(queued_data) && _.isObject(queued_data) && !_.isEmptyObject(queued_data)) {
|
|
3461
|
+
_this._mixpanel['persistence']._pop_from_people_queue(action, queued_data);
|
|
3462
|
+
if (queue_to_params_fn) {
|
|
3463
|
+
action_params = queue_to_params_fn(queued_data);
|
|
3464
|
+
}
|
|
3465
|
+
action_method.call(_this, action_params, function(response, data) {
|
|
3466
|
+
// on bad response, we want to add it back to the queue
|
|
3467
|
+
if (response === 0) {
|
|
3468
|
+
_this._mixpanel['persistence']._add_to_people_queue(action, queued_data);
|
|
3469
|
+
}
|
|
3470
|
+
if (!_.isUndefined(callback)) {
|
|
3471
|
+
callback(response, data);
|
|
3472
|
+
}
|
|
3473
|
+
});
|
|
3351
3474
|
}
|
|
3352
3475
|
};
|
|
3353
3476
|
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3477
|
+
// Flush queued engage operations - order does not matter,
|
|
3478
|
+
// and there are network level race conditions anyway
|
|
3479
|
+
MixpanelPeople.prototype._flush = function(
|
|
3480
|
+
_set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback
|
|
3481
|
+
) {
|
|
3482
|
+
var _this = this;
|
|
3483
|
+
var $append_queue = this._mixpanel['persistence']._get_queue(APPEND_ACTION);
|
|
3484
|
+
var $remove_queue = this._mixpanel['persistence']._get_queue(REMOVE_ACTION);
|
|
3485
|
+
|
|
3486
|
+
this._flush_one_queue(SET_ACTION, this.set, _set_callback);
|
|
3487
|
+
this._flush_one_queue(SET_ONCE_ACTION, this.set_once, _set_once_callback);
|
|
3488
|
+
this._flush_one_queue(UNSET_ACTION, this.unset, _unset_callback, function(queue) { return _.keys(queue); });
|
|
3489
|
+
this._flush_one_queue(ADD_ACTION, this.increment, _add_callback);
|
|
3490
|
+
this._flush_one_queue(UNION_ACTION, this.union, _union_callback);
|
|
3491
|
+
|
|
3492
|
+
// we have to fire off each $append individually since there is
|
|
3493
|
+
// no concat method server side
|
|
3494
|
+
if (!_.isUndefined($append_queue) && _.isArray($append_queue) && $append_queue.length) {
|
|
3495
|
+
var $append_item;
|
|
3496
|
+
var append_callback = function(response, data) {
|
|
3497
|
+
if (response === 0) {
|
|
3498
|
+
_this._mixpanel['persistence']._add_to_people_queue(APPEND_ACTION, $append_item);
|
|
3499
|
+
}
|
|
3500
|
+
if (!_.isUndefined(_append_callback)) {
|
|
3501
|
+
_append_callback(response, data);
|
|
3502
|
+
}
|
|
3503
|
+
};
|
|
3504
|
+
for (var i = $append_queue.length - 1; i >= 0; i--) {
|
|
3505
|
+
$append_item = $append_queue.pop();
|
|
3506
|
+
if (!_.isEmptyObject($append_item)) {
|
|
3507
|
+
_this.append($append_item, append_callback);
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
// Save the shortened append queue
|
|
3511
|
+
_this._mixpanel['persistence'].save();
|
|
3359
3512
|
}
|
|
3360
|
-
};
|
|
3361
3513
|
|
|
3362
|
-
|
|
3363
|
-
if (
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3514
|
+
// same for $remove
|
|
3515
|
+
if (!_.isUndefined($remove_queue) && _.isArray($remove_queue) && $remove_queue.length) {
|
|
3516
|
+
var $remove_item;
|
|
3517
|
+
var remove_callback = function(response, data) {
|
|
3518
|
+
if (response === 0) {
|
|
3519
|
+
_this._mixpanel['persistence']._add_to_people_queue(REMOVE_ACTION, $remove_item);
|
|
3520
|
+
}
|
|
3521
|
+
if (!_.isUndefined(_remove_callback)) {
|
|
3522
|
+
_remove_callback(response, data);
|
|
3523
|
+
}
|
|
3524
|
+
};
|
|
3525
|
+
for (var j = $remove_queue.length - 1; j >= 0; j--) {
|
|
3526
|
+
$remove_item = $remove_queue.pop();
|
|
3527
|
+
if (!_.isEmptyObject($remove_item)) {
|
|
3528
|
+
_this.remove($remove_item, remove_callback);
|
|
3529
|
+
}
|
|
3530
|
+
}
|
|
3531
|
+
_this._mixpanel['persistence'].save();
|
|
3367
3532
|
}
|
|
3368
3533
|
};
|
|
3369
3534
|
|
|
3370
|
-
|
|
3371
|
-
return
|
|
3535
|
+
MixpanelPeople.prototype._is_reserved_property = function(prop) {
|
|
3536
|
+
return prop === '$distinct_id' || prop === '$token' || prop === '$device_id' || prop === '$user_id' || prop === '$had_persisted_distinct_id';
|
|
3372
3537
|
};
|
|
3373
3538
|
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3539
|
+
// MixpanelPeople Exports
|
|
3540
|
+
MixpanelPeople.prototype['set'] = MixpanelPeople.prototype.set;
|
|
3541
|
+
MixpanelPeople.prototype['set_once'] = MixpanelPeople.prototype.set_once;
|
|
3542
|
+
MixpanelPeople.prototype['unset'] = MixpanelPeople.prototype.unset;
|
|
3543
|
+
MixpanelPeople.prototype['increment'] = MixpanelPeople.prototype.increment;
|
|
3544
|
+
MixpanelPeople.prototype['append'] = MixpanelPeople.prototype.append;
|
|
3545
|
+
MixpanelPeople.prototype['remove'] = MixpanelPeople.prototype.remove;
|
|
3546
|
+
MixpanelPeople.prototype['union'] = MixpanelPeople.prototype.union;
|
|
3547
|
+
MixpanelPeople.prototype['track_charge'] = MixpanelPeople.prototype.track_charge;
|
|
3548
|
+
MixpanelPeople.prototype['clear_charges'] = MixpanelPeople.prototype.clear_charges;
|
|
3549
|
+
MixpanelPeople.prototype['delete_user'] = MixpanelPeople.prototype.delete_user;
|
|
3550
|
+
MixpanelPeople.prototype['toString'] = MixpanelPeople.prototype.toString;
|
|
3551
|
+
|
|
3552
|
+
/*
|
|
3553
|
+
* Constants
|
|
3554
|
+
*/
|
|
3555
|
+
/** @const */ var SET_QUEUE_KEY = '__mps';
|
|
3556
|
+
/** @const */ var SET_ONCE_QUEUE_KEY = '__mpso';
|
|
3557
|
+
/** @const */ var UNSET_QUEUE_KEY = '__mpus';
|
|
3558
|
+
/** @const */ var ADD_QUEUE_KEY = '__mpa';
|
|
3559
|
+
/** @const */ var APPEND_QUEUE_KEY = '__mpap';
|
|
3560
|
+
/** @const */ var REMOVE_QUEUE_KEY = '__mpr';
|
|
3561
|
+
/** @const */ var UNION_QUEUE_KEY = '__mpu';
|
|
3562
|
+
// This key is deprecated, but we want to check for it to see whether aliasing is allowed.
|
|
3563
|
+
/** @const */ var PEOPLE_DISTINCT_ID_KEY = '$people_distinct_id';
|
|
3564
|
+
/** @const */ var ALIAS_ID_KEY = '__alias';
|
|
3565
|
+
/** @const */ var EVENT_TIMERS_KEY = '__timers';
|
|
3566
|
+
/** @const */ var RESERVED_PROPERTIES = [
|
|
3567
|
+
SET_QUEUE_KEY,
|
|
3568
|
+
SET_ONCE_QUEUE_KEY,
|
|
3569
|
+
UNSET_QUEUE_KEY,
|
|
3570
|
+
ADD_QUEUE_KEY,
|
|
3571
|
+
APPEND_QUEUE_KEY,
|
|
3572
|
+
REMOVE_QUEUE_KEY,
|
|
3573
|
+
UNION_QUEUE_KEY,
|
|
3574
|
+
PEOPLE_DISTINCT_ID_KEY,
|
|
3575
|
+
ALIAS_ID_KEY,
|
|
3576
|
+
EVENT_TIMERS_KEY
|
|
3577
|
+
];
|
|
3578
|
+
|
|
3579
|
+
/**
|
|
3580
|
+
* Mixpanel Persistence Object
|
|
3581
|
+
* @constructor
|
|
3582
|
+
*/
|
|
3583
|
+
var MixpanelPersistence = function(config) {
|
|
3584
|
+
this['props'] = {};
|
|
3585
|
+
this.campaign_params_saved = false;
|
|
3586
|
+
|
|
3587
|
+
if (config['persistence_name']) {
|
|
3588
|
+
this.name = 'mp_' + config['persistence_name'];
|
|
3589
|
+
} else {
|
|
3590
|
+
this.name = 'mp_' + config['token'] + '_mixpanel';
|
|
3379
3591
|
}
|
|
3380
|
-
};
|
|
3381
3592
|
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
unset_q = this._get_or_create_queue(UNSET_ACTION),
|
|
3388
|
-
add_q = this._get_or_create_queue(ADD_ACTION),
|
|
3389
|
-
union_q = this._get_or_create_queue(UNION_ACTION),
|
|
3390
|
-
remove_q = this._get_or_create_queue(REMOVE_ACTION, []),
|
|
3391
|
-
append_q = this._get_or_create_queue(APPEND_ACTION, []);
|
|
3593
|
+
var storage_type = config['persistence'];
|
|
3594
|
+
if (storage_type !== 'cookie' && storage_type !== 'localStorage') {
|
|
3595
|
+
console.critical('Unknown persistence type ' + storage_type + '; falling back to cookie');
|
|
3596
|
+
storage_type = config['persistence'] = 'cookie';
|
|
3597
|
+
}
|
|
3392
3598
|
|
|
3393
|
-
if (
|
|
3394
|
-
|
|
3395
|
-
_.extend(set_q, q_data);
|
|
3396
|
-
// if there was a pending increment, override it
|
|
3397
|
-
// with the set.
|
|
3398
|
-
this._pop_from_people_queue(ADD_ACTION, q_data);
|
|
3399
|
-
// if there was a pending union, override it
|
|
3400
|
-
// with the set.
|
|
3401
|
-
this._pop_from_people_queue(UNION_ACTION, q_data);
|
|
3402
|
-
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3403
|
-
} else if (q_key === SET_ONCE_QUEUE_KEY) {
|
|
3404
|
-
// only queue the data if there is not already a set_once call for it.
|
|
3405
|
-
_.each(q_data, function(v, k) {
|
|
3406
|
-
if (!(k in set_once_q)) {
|
|
3407
|
-
set_once_q[k] = v;
|
|
3408
|
-
}
|
|
3409
|
-
});
|
|
3410
|
-
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3411
|
-
} else if (q_key === UNSET_QUEUE_KEY) {
|
|
3412
|
-
_.each(q_data, function(prop) {
|
|
3413
|
-
|
|
3414
|
-
// undo previously-queued actions on this key
|
|
3415
|
-
_.each([set_q, set_once_q, add_q, union_q], function(enqueued_obj) {
|
|
3416
|
-
if (prop in enqueued_obj) {
|
|
3417
|
-
delete enqueued_obj[prop];
|
|
3418
|
-
}
|
|
3419
|
-
});
|
|
3420
|
-
_.each(append_q, function(append_obj) {
|
|
3421
|
-
if (prop in append_obj) {
|
|
3422
|
-
delete append_obj[prop];
|
|
3423
|
-
}
|
|
3424
|
-
});
|
|
3425
|
-
|
|
3426
|
-
unset_q[prop] = true;
|
|
3427
|
-
|
|
3428
|
-
});
|
|
3429
|
-
} else if (q_key === ADD_QUEUE_KEY) {
|
|
3430
|
-
_.each(q_data, function(v, k) {
|
|
3431
|
-
// If it exists in the set queue, increment
|
|
3432
|
-
// the value
|
|
3433
|
-
if (k in set_q) {
|
|
3434
|
-
set_q[k] += v;
|
|
3435
|
-
} else {
|
|
3436
|
-
// If it doesn't exist, update the add
|
|
3437
|
-
// queue
|
|
3438
|
-
if (!(k in add_q)) {
|
|
3439
|
-
add_q[k] = 0;
|
|
3440
|
-
}
|
|
3441
|
-
add_q[k] += v;
|
|
3442
|
-
}
|
|
3443
|
-
}, this);
|
|
3444
|
-
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3445
|
-
} else if (q_key === UNION_QUEUE_KEY) {
|
|
3446
|
-
_.each(q_data, function(v, k) {
|
|
3447
|
-
if (_.isArray(v)) {
|
|
3448
|
-
if (!(k in union_q)) {
|
|
3449
|
-
union_q[k] = [];
|
|
3450
|
-
}
|
|
3451
|
-
// We may send duplicates, the server will dedup them.
|
|
3452
|
-
union_q[k] = union_q[k].concat(v);
|
|
3453
|
-
}
|
|
3454
|
-
});
|
|
3455
|
-
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3456
|
-
} else if (q_key === REMOVE_QUEUE_KEY) {
|
|
3457
|
-
remove_q.push(q_data);
|
|
3458
|
-
this._pop_from_people_queue(APPEND_ACTION, q_data);
|
|
3459
|
-
} else if (q_key === APPEND_QUEUE_KEY) {
|
|
3460
|
-
append_q.push(q_data);
|
|
3461
|
-
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3462
|
-
}
|
|
3463
|
-
|
|
3464
|
-
console.log('MIXPANEL PEOPLE REQUEST (QUEUED, PENDING IDENTIFY):');
|
|
3465
|
-
console.log(data);
|
|
3466
|
-
|
|
3467
|
-
this.save();
|
|
3468
|
-
};
|
|
3469
|
-
|
|
3470
|
-
MixpanelPersistence.prototype._pop_from_people_queue = function(queue, data) {
|
|
3471
|
-
var q = this._get_queue(queue);
|
|
3472
|
-
if (!_.isUndefined(q)) {
|
|
3473
|
-
_.each(data, function(v, k) {
|
|
3474
|
-
if (queue === APPEND_ACTION || queue === REMOVE_ACTION) {
|
|
3475
|
-
// list actions: only remove if both k+v match
|
|
3476
|
-
// e.g. remove should not override append in a case like
|
|
3477
|
-
// append({foo: 'bar'}); remove({foo: 'qux'})
|
|
3478
|
-
_.each(q, function(queued_action) {
|
|
3479
|
-
if (queued_action[k] === v) {
|
|
3480
|
-
delete queued_action[k];
|
|
3481
|
-
}
|
|
3482
|
-
});
|
|
3483
|
-
} else {
|
|
3484
|
-
delete q[k];
|
|
3485
|
-
}
|
|
3486
|
-
}, this);
|
|
3487
|
-
|
|
3488
|
-
this.save();
|
|
3489
|
-
}
|
|
3490
|
-
};
|
|
3491
|
-
|
|
3492
|
-
MixpanelPersistence.prototype._get_queue_key = function(queue) {
|
|
3493
|
-
if (queue === SET_ACTION) {
|
|
3494
|
-
return SET_QUEUE_KEY;
|
|
3495
|
-
} else if (queue === SET_ONCE_ACTION) {
|
|
3496
|
-
return SET_ONCE_QUEUE_KEY;
|
|
3497
|
-
} else if (queue === UNSET_ACTION) {
|
|
3498
|
-
return UNSET_QUEUE_KEY;
|
|
3499
|
-
} else if (queue === ADD_ACTION) {
|
|
3500
|
-
return ADD_QUEUE_KEY;
|
|
3501
|
-
} else if (queue === APPEND_ACTION) {
|
|
3502
|
-
return APPEND_QUEUE_KEY;
|
|
3503
|
-
} else if (queue === REMOVE_ACTION) {
|
|
3504
|
-
return REMOVE_QUEUE_KEY;
|
|
3505
|
-
} else if (queue === UNION_ACTION) {
|
|
3506
|
-
return UNION_QUEUE_KEY;
|
|
3599
|
+
if (storage_type === 'localStorage' && _.localStorage.is_supported()) {
|
|
3600
|
+
this.storage = _.localStorage;
|
|
3507
3601
|
} else {
|
|
3508
|
-
|
|
3602
|
+
this.storage = _.cookie;
|
|
3509
3603
|
}
|
|
3510
|
-
};
|
|
3511
|
-
|
|
3512
|
-
MixpanelPersistence.prototype._get_queue = function(queue) {
|
|
3513
|
-
return this['props'][this._get_queue_key(queue)];
|
|
3514
|
-
};
|
|
3515
|
-
MixpanelPersistence.prototype._get_or_create_queue = function(queue, default_val) {
|
|
3516
|
-
var key = this._get_queue_key(queue);
|
|
3517
|
-
default_val = _.isUndefined(default_val) ? {} : default_val;
|
|
3518
3604
|
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
MixpanelPersistence.prototype.set_event_timer = function(event_name, timestamp) {
|
|
3523
|
-
var timers = this['props'][EVENT_TIMERS_KEY] || {};
|
|
3524
|
-
timers[event_name] = timestamp;
|
|
3525
|
-
this['props'][EVENT_TIMERS_KEY] = timers;
|
|
3605
|
+
this.load();
|
|
3606
|
+
this.update_config(config);
|
|
3607
|
+
this.upgrade(config);
|
|
3526
3608
|
this.save();
|
|
3527
3609
|
};
|
|
3528
3610
|
|
|
3529
|
-
MixpanelPersistence.prototype.
|
|
3530
|
-
var
|
|
3531
|
-
|
|
3532
|
-
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3611
|
+
MixpanelPersistence.prototype.properties = function() {
|
|
3612
|
+
var p = {};
|
|
3613
|
+
// Filter out reserved properties
|
|
3614
|
+
_.each(this['props'], function(v, k) {
|
|
3615
|
+
if (!_.include(RESERVED_PROPERTIES, k)) {
|
|
3616
|
+
p[k] = v;
|
|
3617
|
+
}
|
|
3618
|
+
});
|
|
3619
|
+
return p;
|
|
3537
3620
|
};
|
|
3538
3621
|
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
*/
|
|
3622
|
+
MixpanelPersistence.prototype.load = function() {
|
|
3623
|
+
if (this.disabled) { return; }
|
|
3542
3624
|
|
|
3543
|
-
|
|
3544
|
-
* Constants
|
|
3545
|
-
*/
|
|
3546
|
-
// Metadata keys
|
|
3547
|
-
/** @const */ var OPERATOR_KEY = 'operator';
|
|
3548
|
-
/** @const */ var PROPERTY_KEY = 'property';
|
|
3549
|
-
/** @const */ var WINDOW_KEY = 'window';
|
|
3550
|
-
/** @const */ var UNIT_KEY = 'unit';
|
|
3551
|
-
/** @const */ var VALUE_KEY = 'value';
|
|
3552
|
-
/** @const */ var HOUR_KEY = 'hour';
|
|
3553
|
-
/** @const */ var DAY_KEY = 'day';
|
|
3554
|
-
/** @const */ var WEEK_KEY = 'week';
|
|
3555
|
-
/** @const */ var MONTH_KEY = 'month';
|
|
3556
|
-
|
|
3557
|
-
// Operands
|
|
3558
|
-
/** @const */ var EVENT_PROPERTY = 'event';
|
|
3559
|
-
/** @const */ var LITERAL_PROPERTY = 'literal';
|
|
3560
|
-
|
|
3561
|
-
// Binary Operators
|
|
3562
|
-
/** @const */ var AND_OPERATOR = 'and';
|
|
3563
|
-
/** @const */ var OR_OPERATOR = 'or';
|
|
3564
|
-
/** @const */ var IN_OPERATOR = 'in';
|
|
3565
|
-
/** @const */ var NOT_IN_OPERATOR = 'not in';
|
|
3566
|
-
/** @const */ var PLUS_OPERATOR = '+';
|
|
3567
|
-
/** @const */ var MINUS_OPERATOR = '-';
|
|
3568
|
-
/** @const */ var MUL_OPERATOR = '*';
|
|
3569
|
-
/** @const */ var DIV_OPERATOR = '/';
|
|
3570
|
-
/** @const */ var MOD_OPERATOR = '%';
|
|
3571
|
-
/** @const */ var EQUALS_OPERATOR = '==';
|
|
3572
|
-
/** @const */ var NOT_EQUALS_OPERATOR = '!=';
|
|
3573
|
-
/** @const */ var GREATER_OPERATOR = '>';
|
|
3574
|
-
/** @const */ var LESS_OPERATOR = '<';
|
|
3575
|
-
/** @const */ var GREATER_EQUAL_OPERATOR = '>=';
|
|
3576
|
-
/** @const */ var LESS_EQUAL_OPERATOR = '<=';
|
|
3577
|
-
|
|
3578
|
-
// Typecast Operators
|
|
3579
|
-
/** @const */ var BOOLEAN_OPERATOR = 'boolean';
|
|
3580
|
-
/** @const */ var DATETIME_OPERATOR = 'datetime';
|
|
3581
|
-
/** @const */ var LIST_OPERATOR = 'list';
|
|
3582
|
-
/** @const */ var NUMBER_OPERATOR = 'number';
|
|
3583
|
-
/** @const */ var STRING_OPERATOR = 'string';
|
|
3584
|
-
|
|
3585
|
-
// Unary Operators
|
|
3586
|
-
/** @const */ var NOT_OPERATOR = 'not';
|
|
3587
|
-
/** @const */ var DEFINED_OPERATOR = 'defined';
|
|
3588
|
-
/** @const */ var NOT_DEFINED_OPERATOR = 'not defined';
|
|
3589
|
-
|
|
3590
|
-
// Special literals
|
|
3591
|
-
/** @const */ var NOW_LITERAL = 'now';
|
|
3592
|
-
|
|
3593
|
-
// Type cast functions
|
|
3594
|
-
function toNumber(value) {
|
|
3595
|
-
if (value === null) {
|
|
3596
|
-
return null;
|
|
3597
|
-
}
|
|
3625
|
+
var entry = this.storage.parse(this.name);
|
|
3598
3626
|
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
if (_.isDate(value) && value.getTime() >= 0) {
|
|
3602
|
-
return value.getTime();
|
|
3603
|
-
}
|
|
3604
|
-
return null;
|
|
3605
|
-
case 'boolean':
|
|
3606
|
-
return Number(value);
|
|
3607
|
-
case 'number':
|
|
3608
|
-
return value;
|
|
3609
|
-
case 'string':
|
|
3610
|
-
value = Number(value);
|
|
3611
|
-
if (!isNaN(value)) {
|
|
3612
|
-
return value;
|
|
3613
|
-
}
|
|
3614
|
-
return 0;
|
|
3627
|
+
if (entry) {
|
|
3628
|
+
this['props'] = _.extend({}, entry);
|
|
3615
3629
|
}
|
|
3616
|
-
|
|
3617
|
-
}
|
|
3630
|
+
};
|
|
3618
3631
|
|
|
3619
|
-
function
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3632
|
+
MixpanelPersistence.prototype.upgrade = function(config) {
|
|
3633
|
+
var upgrade_from_old_lib = config['upgrade'],
|
|
3634
|
+
old_cookie_name,
|
|
3635
|
+
old_cookie;
|
|
3623
3636
|
|
|
3624
|
-
|
|
3625
|
-
|
|
3637
|
+
if (upgrade_from_old_lib) {
|
|
3638
|
+
old_cookie_name = 'mp_super_properties';
|
|
3639
|
+
// Case where they had a custom cookie name before.
|
|
3640
|
+
if (typeof(upgrade_from_old_lib) === 'string') {
|
|
3641
|
+
old_cookie_name = upgrade_from_old_lib;
|
|
3642
|
+
}
|
|
3626
3643
|
|
|
3627
|
-
|
|
3628
|
-
if (value === null) {
|
|
3629
|
-
return false;
|
|
3630
|
-
}
|
|
3644
|
+
old_cookie = this.storage.parse(old_cookie_name);
|
|
3631
3645
|
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
case 'number':
|
|
3636
|
-
return value !== 0.0;
|
|
3637
|
-
case 'string':
|
|
3638
|
-
return value.length > 0;
|
|
3639
|
-
case 'object':
|
|
3640
|
-
if (_.isArray(value) && value.length > 0) {
|
|
3641
|
-
return true;
|
|
3642
|
-
}
|
|
3643
|
-
if (_.isDate(value) && value.getTime() > 0) {
|
|
3644
|
-
return true;
|
|
3645
|
-
}
|
|
3646
|
-
if (_.isObject(value) && !_.isEmptyObject(value)) {
|
|
3647
|
-
return true;
|
|
3648
|
-
}
|
|
3649
|
-
return false;
|
|
3650
|
-
}
|
|
3651
|
-
return false;
|
|
3652
|
-
}
|
|
3646
|
+
// remove the cookie
|
|
3647
|
+
this.storage.remove(old_cookie_name);
|
|
3648
|
+
this.storage.remove(old_cookie_name, true);
|
|
3653
3649
|
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3650
|
+
if (old_cookie) {
|
|
3651
|
+
this['props'] = _.extend(
|
|
3652
|
+
this['props'],
|
|
3653
|
+
old_cookie['all'],
|
|
3654
|
+
old_cookie['events']
|
|
3655
|
+
);
|
|
3656
|
+
}
|
|
3657
3657
|
}
|
|
3658
3658
|
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
throw ('Invalid cast operator: datetime ' + op);
|
|
3665
|
-
}
|
|
3659
|
+
if (!config['cookie_name'] && config['name'] !== 'mixpanel') {
|
|
3660
|
+
// special case to handle people with cookies of the form
|
|
3661
|
+
// mp_TOKEN_INSTANCENAME from the first release of this library
|
|
3662
|
+
old_cookie_name = 'mp_' + config['token'] + '_' + config['name'];
|
|
3663
|
+
old_cookie = this.storage.parse(old_cookie_name);
|
|
3666
3664
|
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
}
|
|
3665
|
+
if (old_cookie) {
|
|
3666
|
+
this.storage.remove(old_cookie_name);
|
|
3667
|
+
this.storage.remove(old_cookie_name, true);
|
|
3671
3668
|
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
if (isNaN(d.getTime())) {
|
|
3677
|
-
return null;
|
|
3678
|
-
}
|
|
3679
|
-
return d;
|
|
3680
|
-
case 'object':
|
|
3681
|
-
if (_.isDate(v)) {
|
|
3682
|
-
return v;
|
|
3683
|
-
}
|
|
3669
|
+
// Save the prop values that were in the cookie from before -
|
|
3670
|
+
// this should only happen once as we delete the old one.
|
|
3671
|
+
this.register_once(old_cookie);
|
|
3672
|
+
}
|
|
3684
3673
|
}
|
|
3685
3674
|
|
|
3686
|
-
|
|
3687
|
-
|
|
3675
|
+
if (this.storage === _.localStorage) {
|
|
3676
|
+
old_cookie = _.cookie.parse(this.name);
|
|
3688
3677
|
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
throw ('Invalid cast operator: list ' + op);
|
|
3692
|
-
}
|
|
3678
|
+
_.cookie.remove(this.name);
|
|
3679
|
+
_.cookie.remove(this.name, true);
|
|
3693
3680
|
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3681
|
+
if (old_cookie) {
|
|
3682
|
+
this.register_once(old_cookie);
|
|
3683
|
+
}
|
|
3697
3684
|
}
|
|
3685
|
+
};
|
|
3698
3686
|
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3687
|
+
MixpanelPersistence.prototype.save = function() {
|
|
3688
|
+
if (this.disabled) { return; }
|
|
3689
|
+
this.storage.set(
|
|
3690
|
+
this.name,
|
|
3691
|
+
_.JSONEncode(this['props']),
|
|
3692
|
+
this.expire_days,
|
|
3693
|
+
this.cross_subdomain,
|
|
3694
|
+
this.secure,
|
|
3695
|
+
this.cross_site,
|
|
3696
|
+
this.cookie_domain
|
|
3697
|
+
);
|
|
3698
|
+
};
|
|
3702
3699
|
|
|
3703
|
-
|
|
3704
|
-
|
|
3700
|
+
MixpanelPersistence.prototype.remove = function() {
|
|
3701
|
+
// remove both domain and subdomain cookies
|
|
3702
|
+
this.storage.remove(this.name, false, this.cookie_domain);
|
|
3703
|
+
this.storage.remove(this.name, true, this.cookie_domain);
|
|
3704
|
+
};
|
|
3705
3705
|
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3706
|
+
// removes the storage entry and deletes all loaded data
|
|
3707
|
+
// forced name for tests
|
|
3708
|
+
MixpanelPersistence.prototype.clear = function() {
|
|
3709
|
+
this.remove();
|
|
3710
|
+
this['props'] = {};
|
|
3711
|
+
};
|
|
3710
3712
|
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
}
|
|
3721
|
-
|
|
3722
|
-
// Operators
|
|
3723
|
-
function evaluateAnd(op, properties) {
|
|
3724
|
-
if (!op['operator'] || op['operator'] !== AND_OPERATOR || !op['children'] || op['children'].length !== 2) {
|
|
3725
|
-
throw ('Invalid operator: AND ' + op);
|
|
3726
|
-
}
|
|
3727
|
-
|
|
3728
|
-
return toBoolean(evaluateSelector(op['children'][0], properties)) && toBoolean(evaluateSelector(op['children'][1], properties));
|
|
3729
|
-
}
|
|
3730
|
-
|
|
3731
|
-
function evaluateOr(op, properties) {
|
|
3732
|
-
if (!op['operator'] || op['operator'] !== OR_OPERATOR || !op['children'] || op['children'].length !== 2) {
|
|
3733
|
-
throw ('Invalid operator: OR ' + op);
|
|
3734
|
-
}
|
|
3735
|
-
|
|
3736
|
-
return toBoolean(evaluateSelector(op['children'][0], properties)) || toBoolean(evaluateSelector(op['children'][1], properties));
|
|
3737
|
-
}
|
|
3738
|
-
|
|
3739
|
-
function evaluateIn(op, properties) {
|
|
3740
|
-
if (!op['operator'] || [IN_OPERATOR, NOT_IN_OPERATOR].indexOf(op['operator']) === -1 || !op['children'] || op['children'].length !== 2) {
|
|
3741
|
-
throw ('Invalid operator: IN/NOT IN ' + op);
|
|
3742
|
-
}
|
|
3743
|
-
var leftValue = evaluateSelector(op['children'][0], properties);
|
|
3744
|
-
var rightValue = evaluateSelector(op['children'][1], properties);
|
|
3745
|
-
|
|
3746
|
-
if (!_.isArray(rightValue) && !_.isString(rightValue)) {
|
|
3747
|
-
throw ('Invalid operand for operator IN: invalid type' + rightValue);
|
|
3748
|
-
}
|
|
3749
|
-
|
|
3750
|
-
var v = rightValue.indexOf(leftValue) > -1;
|
|
3751
|
-
if (op['operator'] === NOT_IN_OPERATOR) {
|
|
3752
|
-
return !v;
|
|
3753
|
-
}
|
|
3754
|
-
return v;
|
|
3755
|
-
}
|
|
3756
|
-
|
|
3757
|
-
function evaluatePlus(op, properties) {
|
|
3758
|
-
if (!op['operator'] || op['operator'] !== PLUS_OPERATOR || !op['children'] || op['children'].length < 2) {
|
|
3759
|
-
throw ('Invalid operator: PLUS ' + op);
|
|
3760
|
-
}
|
|
3761
|
-
var l = evaluateSelector(op['children'][0], properties);
|
|
3762
|
-
var r = evaluateSelector(op['children'][1], properties);
|
|
3763
|
-
|
|
3764
|
-
if (typeof l === 'number' && typeof r === 'number') {
|
|
3765
|
-
return l + r;
|
|
3766
|
-
}
|
|
3767
|
-
if (typeof l === 'string' && typeof r === 'string') {
|
|
3768
|
-
return l + r;
|
|
3769
|
-
}
|
|
3770
|
-
return null;
|
|
3771
|
-
}
|
|
3772
|
-
|
|
3773
|
-
function evaluateArithmetic(op, properties) {
|
|
3774
|
-
if (!op['operator'] || [MINUS_OPERATOR, MUL_OPERATOR, DIV_OPERATOR, MOD_OPERATOR].indexOf(op['operator']) === -1 ||
|
|
3775
|
-
!op['children'] || op['children'].length < 2) {
|
|
3776
|
-
throw ('Invalid arithmetic operator ' + op);
|
|
3777
|
-
}
|
|
3778
|
-
|
|
3779
|
-
var l = evaluateSelector(op['children'][0], properties);
|
|
3780
|
-
var r = evaluateSelector(op['children'][1], properties);
|
|
3781
|
-
|
|
3782
|
-
if (typeof l === 'number' && typeof r === 'number') {
|
|
3783
|
-
switch (op['operator']) {
|
|
3784
|
-
case MINUS_OPERATOR:
|
|
3785
|
-
return l - r;
|
|
3786
|
-
case MUL_OPERATOR:
|
|
3787
|
-
return l * r;
|
|
3788
|
-
case DIV_OPERATOR:
|
|
3789
|
-
if (r !== 0) {
|
|
3790
|
-
return l / r;
|
|
3791
|
-
}
|
|
3792
|
-
return null;
|
|
3793
|
-
case MOD_OPERATOR:
|
|
3794
|
-
if (r === 0) {
|
|
3795
|
-
return null;
|
|
3796
|
-
}
|
|
3797
|
-
if (l === 0) {
|
|
3798
|
-
return 0;
|
|
3799
|
-
}
|
|
3800
|
-
if ((l < 0 && r > 0) || (l > 0 && r < 0)) {
|
|
3801
|
-
/* Mimic python modulo - result takes sign of the divisor
|
|
3802
|
-
* if one operand is negative. */
|
|
3803
|
-
return -(Math.floor(l / r) * r - l);
|
|
3804
|
-
}
|
|
3805
|
-
return l % r;
|
|
3806
|
-
default:
|
|
3807
|
-
throw('Unknown operator: ' + op['operator']);
|
|
3808
|
-
}
|
|
3809
|
-
}
|
|
3810
|
-
|
|
3811
|
-
return null;
|
|
3812
|
-
}
|
|
3813
|
-
|
|
3814
|
-
function _isArrayEqual(l, r) {
|
|
3815
|
-
if (l === r) return true;
|
|
3816
|
-
if (l === null || r === null) return false;
|
|
3817
|
-
if (l.length !== r.length) return false;
|
|
3713
|
+
/**
|
|
3714
|
+
* @param {Object} props
|
|
3715
|
+
* @param {*=} default_value
|
|
3716
|
+
* @param {number=} days
|
|
3717
|
+
*/
|
|
3718
|
+
MixpanelPersistence.prototype.register_once = function(props, default_value, days) {
|
|
3719
|
+
if (_.isObject(props)) {
|
|
3720
|
+
if (typeof(default_value) === 'undefined') { default_value = 'None'; }
|
|
3721
|
+
this.expire_days = (typeof(days) === 'undefined') ? this.default_expiry : days;
|
|
3818
3722
|
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3723
|
+
_.each(props, function(val, prop) {
|
|
3724
|
+
if (!this['props'].hasOwnProperty(prop) || this['props'][prop] === default_value) {
|
|
3725
|
+
this['props'][prop] = val;
|
|
3726
|
+
}
|
|
3727
|
+
}, this);
|
|
3824
3728
|
|
|
3825
|
-
|
|
3826
|
-
}
|
|
3729
|
+
this.save();
|
|
3827
3730
|
|
|
3828
|
-
function _isEqual(l, r) {
|
|
3829
|
-
if ( l === null && l === r ) {
|
|
3830
3731
|
return true;
|
|
3831
3732
|
}
|
|
3832
|
-
if (typeof l === typeof r) {
|
|
3833
|
-
switch (typeof l) {
|
|
3834
|
-
case 'number':
|
|
3835
|
-
case 'string':
|
|
3836
|
-
case 'boolean':
|
|
3837
|
-
return l === r;
|
|
3838
|
-
case 'object':
|
|
3839
|
-
if (_.isArray(l) && _.isArray(r)) {
|
|
3840
|
-
return _isArrayEqual(l, r);
|
|
3841
|
-
}
|
|
3842
|
-
if (_.isDate(l) && _.isDate(r)) {
|
|
3843
|
-
return l.getTime() === r.getTime();
|
|
3844
|
-
}
|
|
3845
|
-
if (_.isObject(l) && _.isObject(r)) {
|
|
3846
|
-
return JSON.stringify(l) === JSON.stringify(r);
|
|
3847
|
-
}
|
|
3848
|
-
}
|
|
3849
|
-
}
|
|
3850
3733
|
return false;
|
|
3851
|
-
}
|
|
3852
|
-
|
|
3853
|
-
function evaluateEquality(op, properties) {
|
|
3854
|
-
if (!op['operator'] || [EQUALS_OPERATOR, NOT_EQUALS_OPERATOR].indexOf(op['operator']) === -1 || !op['children'] || op['children'].length !== 2) {
|
|
3855
|
-
throw ('Invalid equality operator ' + op);
|
|
3856
|
-
}
|
|
3857
|
-
|
|
3858
|
-
var v = _isEqual(evaluateSelector(op['children'][0], properties), evaluateSelector(op['children'][1], properties));
|
|
3859
|
-
|
|
3860
|
-
switch (op['operator']) {
|
|
3861
|
-
case EQUALS_OPERATOR:
|
|
3862
|
-
return v;
|
|
3863
|
-
case NOT_EQUALS_OPERATOR:
|
|
3864
|
-
return !v;
|
|
3865
|
-
}
|
|
3866
|
-
}
|
|
3867
|
-
|
|
3868
|
-
function evaluateComparison(op, properties) {
|
|
3869
|
-
if (!op['operator'] ||
|
|
3870
|
-
[GREATER_OPERATOR, GREATER_EQUAL_OPERATOR, LESS_OPERATOR, LESS_EQUAL_OPERATOR].indexOf(op['operator']) === -1 ||
|
|
3871
|
-
!op['children'] || op['children'].length !== 2) {
|
|
3872
|
-
throw ('Invalid comparison operator ' + op);
|
|
3873
|
-
}
|
|
3874
|
-
var l = evaluateSelector(op['children'][0], properties);
|
|
3875
|
-
var r = evaluateSelector(op['children'][1], properties);
|
|
3876
|
-
|
|
3877
|
-
if (typeof(l) === typeof(r)) {
|
|
3878
|
-
if (typeof(r) === 'number' || _.isDate(r)) {
|
|
3879
|
-
l = toNumber(l);
|
|
3880
|
-
r = toNumber(r);
|
|
3881
|
-
switch (op['operator']) {
|
|
3882
|
-
case GREATER_OPERATOR:
|
|
3883
|
-
return l > r;
|
|
3884
|
-
case GREATER_EQUAL_OPERATOR:
|
|
3885
|
-
return l >= r;
|
|
3886
|
-
case LESS_OPERATOR:
|
|
3887
|
-
return l < r;
|
|
3888
|
-
case LESS_EQUAL_OPERATOR:
|
|
3889
|
-
return l <= r;
|
|
3890
|
-
}
|
|
3891
|
-
} else if (typeof(r) === 'string') {
|
|
3892
|
-
var compare = l.localeCompare(r);
|
|
3893
|
-
switch (op['operator']) {
|
|
3894
|
-
case GREATER_OPERATOR:
|
|
3895
|
-
return compare > 0;
|
|
3896
|
-
case GREATER_EQUAL_OPERATOR:
|
|
3897
|
-
return compare >= 0;
|
|
3898
|
-
case LESS_OPERATOR:
|
|
3899
|
-
return compare < 0;
|
|
3900
|
-
case LESS_EQUAL_OPERATOR:
|
|
3901
|
-
return compare <= 0;
|
|
3902
|
-
}
|
|
3903
|
-
}
|
|
3904
|
-
}
|
|
3905
|
-
|
|
3906
|
-
return null;
|
|
3907
|
-
}
|
|
3908
|
-
|
|
3909
|
-
function evaluateDefined(op, properties) {
|
|
3910
|
-
if (!op['operator'] || [DEFINED_OPERATOR, NOT_DEFINED_OPERATOR].indexOf(op['operator']) === -1 ||
|
|
3911
|
-
!op['children'] || op['children'].length !== 1) {
|
|
3912
|
-
throw ('Invalid defined/not defined operator: ' + op);
|
|
3913
|
-
}
|
|
3734
|
+
};
|
|
3914
3735
|
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3736
|
+
/**
|
|
3737
|
+
* @param {Object} props
|
|
3738
|
+
* @param {number=} days
|
|
3739
|
+
*/
|
|
3740
|
+
MixpanelPersistence.prototype.register = function(props, days) {
|
|
3741
|
+
if (_.isObject(props)) {
|
|
3742
|
+
this.expire_days = (typeof(days) === 'undefined') ? this.default_expiry : days;
|
|
3919
3743
|
|
|
3920
|
-
|
|
3921
|
-
}
|
|
3744
|
+
_.extend(this['props'], props);
|
|
3922
3745
|
|
|
3923
|
-
|
|
3924
|
-
if (!op['operator'] || op['operator'] !== NOT_OPERATOR || !op['children'] || op['children'].length !== 1) {
|
|
3925
|
-
throw ('Invalid not operator: ' + op);
|
|
3926
|
-
}
|
|
3746
|
+
this.save();
|
|
3927
3747
|
|
|
3928
|
-
var v = evaluateSelector(op['children'][0], properties);
|
|
3929
|
-
if (v === null) {
|
|
3930
3748
|
return true;
|
|
3931
3749
|
}
|
|
3750
|
+
return false;
|
|
3751
|
+
};
|
|
3932
3752
|
|
|
3933
|
-
|
|
3934
|
-
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
return null;
|
|
3938
|
-
}
|
|
3939
|
-
|
|
3940
|
-
function evaluateOperator(op, properties) {
|
|
3941
|
-
if (!op['operator']) {
|
|
3942
|
-
throw ('Invalid operator: operator key missing ' + op);
|
|
3943
|
-
}
|
|
3944
|
-
|
|
3945
|
-
switch (op['operator']) {
|
|
3946
|
-
case AND_OPERATOR:
|
|
3947
|
-
return evaluateAnd(op, properties);
|
|
3948
|
-
case OR_OPERATOR:
|
|
3949
|
-
return evaluateOr(op, properties);
|
|
3950
|
-
case IN_OPERATOR:
|
|
3951
|
-
case NOT_IN_OPERATOR:
|
|
3952
|
-
return evaluateIn(op, properties);
|
|
3953
|
-
case PLUS_OPERATOR:
|
|
3954
|
-
return evaluatePlus(op, properties);
|
|
3955
|
-
case MINUS_OPERATOR:
|
|
3956
|
-
case MUL_OPERATOR:
|
|
3957
|
-
case DIV_OPERATOR:
|
|
3958
|
-
case MOD_OPERATOR:
|
|
3959
|
-
return evaluateArithmetic(op, properties);
|
|
3960
|
-
case EQUALS_OPERATOR:
|
|
3961
|
-
case NOT_EQUALS_OPERATOR:
|
|
3962
|
-
return evaluateEquality(op, properties);
|
|
3963
|
-
case GREATER_OPERATOR:
|
|
3964
|
-
case LESS_OPERATOR:
|
|
3965
|
-
case GREATER_EQUAL_OPERATOR:
|
|
3966
|
-
case LESS_EQUAL_OPERATOR:
|
|
3967
|
-
return evaluateComparison(op, properties);
|
|
3968
|
-
case BOOLEAN_OPERATOR:
|
|
3969
|
-
return evaluateBoolean(op, properties);
|
|
3970
|
-
case DATETIME_OPERATOR:
|
|
3971
|
-
return evaluateDateTime(op, properties);
|
|
3972
|
-
case LIST_OPERATOR:
|
|
3973
|
-
return evaluateList(op, properties);
|
|
3974
|
-
case NUMBER_OPERATOR:
|
|
3975
|
-
return evaluateNumber(op, properties);
|
|
3976
|
-
case STRING_OPERATOR:
|
|
3977
|
-
return evaluateString(op, properties);
|
|
3978
|
-
case DEFINED_OPERATOR:
|
|
3979
|
-
case NOT_DEFINED_OPERATOR:
|
|
3980
|
-
return evaluateDefined(op, properties);
|
|
3981
|
-
case NOT_OPERATOR:
|
|
3982
|
-
return evaluateNot(op, properties);
|
|
3983
|
-
}
|
|
3984
|
-
}
|
|
3985
|
-
|
|
3986
|
-
function evaluateWindow(value) {
|
|
3987
|
-
var win = value[WINDOW_KEY];
|
|
3988
|
-
if (!win || !win[UNIT_KEY] || !win[VALUE_KEY]) {
|
|
3989
|
-
throw('Invalid window: missing required keys ' + JSON.stringify(value));
|
|
3990
|
-
}
|
|
3991
|
-
var out = new Date();
|
|
3992
|
-
switch (win[UNIT_KEY]) {
|
|
3993
|
-
case HOUR_KEY:
|
|
3994
|
-
out.setTime(out.getTime() + (win[VALUE_KEY]*-1*60*60*1000));
|
|
3995
|
-
break;
|
|
3996
|
-
case DAY_KEY:
|
|
3997
|
-
out.setTime(out.getTime() + (win[VALUE_KEY]*-1*24*60*60*1000));
|
|
3998
|
-
break;
|
|
3999
|
-
case WEEK_KEY:
|
|
4000
|
-
out.setTime(out.getTime() + (win[VALUE_KEY]*-1*7*24*60*60*1000));
|
|
4001
|
-
break;
|
|
4002
|
-
case MONTH_KEY:
|
|
4003
|
-
out.setTime(out.getTime() + (win[VALUE_KEY]*-1*30*24*60*60*1000));
|
|
4004
|
-
break;
|
|
4005
|
-
default:
|
|
4006
|
-
throw('Invalid unit: ' + win[UNIT_KEY]);
|
|
4007
|
-
}
|
|
4008
|
-
|
|
4009
|
-
return out;
|
|
4010
|
-
}
|
|
4011
|
-
|
|
4012
|
-
function evaluateOperand(op, properties) {
|
|
4013
|
-
if (!op['property'] || !op['value']) {
|
|
4014
|
-
throw('Invalid operand: missing required keys ' + op);
|
|
4015
|
-
}
|
|
4016
|
-
switch (op['property']) {
|
|
4017
|
-
case EVENT_PROPERTY:
|
|
4018
|
-
if (properties[op['value']] !== undefined) {
|
|
4019
|
-
return properties[op['value']];
|
|
4020
|
-
}
|
|
4021
|
-
return null;
|
|
4022
|
-
case LITERAL_PROPERTY:
|
|
4023
|
-
if (op['value'] === NOW_LITERAL) {
|
|
4024
|
-
return new Date();
|
|
4025
|
-
}
|
|
4026
|
-
if (typeof(op['value']) === 'object') {
|
|
4027
|
-
return evaluateWindow(op['value']);
|
|
4028
|
-
}
|
|
4029
|
-
return op['value'];
|
|
4030
|
-
default:
|
|
4031
|
-
throw('Invalid operand: Invalid property type ' + op['property']);
|
|
4032
|
-
}
|
|
4033
|
-
}
|
|
4034
|
-
|
|
4035
|
-
function evaluateSelector(filters, properties) {
|
|
4036
|
-
if (filters[PROPERTY_KEY]) {
|
|
4037
|
-
return evaluateOperand(filters, properties);
|
|
4038
|
-
}
|
|
4039
|
-
if (filters[OPERATOR_KEY]) {
|
|
4040
|
-
return evaluateOperator(filters, properties);
|
|
4041
|
-
}
|
|
4042
|
-
}
|
|
4043
|
-
|
|
4044
|
-
// Internal class for notification display
|
|
4045
|
-
|
|
4046
|
-
var MixpanelNotification = function(notif_data, mixpanel_instance) {
|
|
4047
|
-
_.bind_instance_methods(this);
|
|
4048
|
-
|
|
4049
|
-
this.mixpanel = mixpanel_instance;
|
|
4050
|
-
this.persistence = this.mixpanel['persistence'];
|
|
4051
|
-
this.resource_protocol = this.mixpanel.get_config('inapp_protocol');
|
|
4052
|
-
this.cdn_host = this.mixpanel.get_config('cdn');
|
|
4053
|
-
|
|
4054
|
-
this.campaign_id = _.escapeHTML(notif_data['id']);
|
|
4055
|
-
this.message_id = _.escapeHTML(notif_data['message_id']);
|
|
4056
|
-
|
|
4057
|
-
this.body = (_.escapeHTML(notif_data['body']) || '').replace(/\n/g, '<br/>');
|
|
4058
|
-
this.cta = _.escapeHTML(notif_data['cta']) || 'Close';
|
|
4059
|
-
this.notif_type = _.escapeHTML(notif_data['type']) || 'takeover';
|
|
4060
|
-
this.style = _.escapeHTML(notif_data['style']) || 'light';
|
|
4061
|
-
this.title = _.escapeHTML(notif_data['title']) || '';
|
|
4062
|
-
this.video_width = MixpanelNotification.VIDEO_WIDTH;
|
|
4063
|
-
this.video_height = MixpanelNotification.VIDEO_HEIGHT;
|
|
4064
|
-
|
|
4065
|
-
this.display_triggers = notif_data['display_triggers'] || [];
|
|
4066
|
-
|
|
4067
|
-
// These fields are url-sanitized in the backend already.
|
|
4068
|
-
this.dest_url = notif_data['cta_url'] || null;
|
|
4069
|
-
this.image_url = notif_data['image_url'] || null;
|
|
4070
|
-
this.thumb_image_url = notif_data['thumb_image_url'] || null;
|
|
4071
|
-
this.video_url = notif_data['video_url'] || null;
|
|
4072
|
-
|
|
4073
|
-
if (this.thumb_image_url && this.thumb_image_url.indexOf('//') === 0) {
|
|
4074
|
-
this.thumb_image_url = this.thumb_image_url.replace('//', this.resource_protocol);
|
|
4075
|
-
}
|
|
4076
|
-
|
|
4077
|
-
this.clickthrough = true;
|
|
4078
|
-
if (!this.dest_url) {
|
|
4079
|
-
this.dest_url = '#dismiss';
|
|
4080
|
-
this.clickthrough = false;
|
|
3753
|
+
MixpanelPersistence.prototype.unregister = function(prop) {
|
|
3754
|
+
if (prop in this['props']) {
|
|
3755
|
+
delete this['props'][prop];
|
|
3756
|
+
this.save();
|
|
4081
3757
|
}
|
|
3758
|
+
};
|
|
4082
3759
|
|
|
4083
|
-
|
|
4084
|
-
if (!this.
|
|
4085
|
-
this.
|
|
3760
|
+
MixpanelPersistence.prototype.update_campaign_params = function() {
|
|
3761
|
+
if (!this.campaign_params_saved) {
|
|
3762
|
+
this.register_once(_.info.campaignParams());
|
|
3763
|
+
this.campaign_params_saved = true;
|
|
4086
3764
|
}
|
|
4087
|
-
this.notif_width = !this.mini ? MixpanelNotification.NOTIF_WIDTH : MixpanelNotification.NOTIF_WIDTH_MINI;
|
|
4088
|
-
|
|
4089
|
-
this._set_client_config();
|
|
4090
|
-
this.imgs_to_preload = this._init_image_html();
|
|
4091
|
-
this._init_video();
|
|
4092
3765
|
};
|
|
4093
3766
|
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
MixpanelNotification.NOTIF_TOP = 25;
|
|
4098
|
-
MixpanelNotification.NOTIF_START_TOP = 200;
|
|
4099
|
-
MixpanelNotification.NOTIF_WIDTH = 388;
|
|
4100
|
-
MixpanelNotification.NOTIF_WIDTH_MINI = 420;
|
|
4101
|
-
MixpanelNotification.NOTIF_HEIGHT_MINI = 85;
|
|
4102
|
-
MixpanelNotification.THUMB_BORDER_SIZE = 5;
|
|
4103
|
-
MixpanelNotification.THUMB_IMG_SIZE = 60;
|
|
4104
|
-
MixpanelNotification.THUMB_OFFSET = Math.round(MixpanelNotification.THUMB_IMG_SIZE / 2);
|
|
4105
|
-
MixpanelNotification.VIDEO_WIDTH = 595;
|
|
4106
|
-
MixpanelNotification.VIDEO_HEIGHT = 334;
|
|
3767
|
+
MixpanelPersistence.prototype.update_search_keyword = function(referrer) {
|
|
3768
|
+
this.register(_.info.searchInfo(referrer));
|
|
3769
|
+
};
|
|
4107
3770
|
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
3771
|
+
// EXPORTED METHOD, we test this directly.
|
|
3772
|
+
MixpanelPersistence.prototype.update_referrer_info = function(referrer) {
|
|
3773
|
+
// If referrer doesn't exist, we want to note the fact that it was type-in traffic.
|
|
3774
|
+
this.register_once({
|
|
3775
|
+
'$initial_referrer': referrer || '$direct',
|
|
3776
|
+
'$initial_referring_domain': _.info.referringDomain(referrer) || '$direct'
|
|
3777
|
+
}, '');
|
|
3778
|
+
};
|
|
4111
3779
|
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
}
|
|
3780
|
+
MixpanelPersistence.prototype.get_referrer_info = function() {
|
|
3781
|
+
return _.strip_empty_properties({
|
|
3782
|
+
'$initial_referrer': this['props']['$initial_referrer'],
|
|
3783
|
+
'$initial_referring_domain': this['props']['$initial_referring_domain']
|
|
3784
|
+
});
|
|
3785
|
+
};
|
|
4117
3786
|
|
|
4118
|
-
|
|
4119
|
-
|
|
3787
|
+
// safely fills the passed in object with stored properties,
|
|
3788
|
+
// does not override any properties defined in both
|
|
3789
|
+
// returns the passed in object
|
|
3790
|
+
MixpanelPersistence.prototype.safe_merge = function(props) {
|
|
3791
|
+
_.each(this['props'], function(val, prop) {
|
|
3792
|
+
if (!(prop in props)) {
|
|
3793
|
+
props[prop] = val;
|
|
3794
|
+
}
|
|
3795
|
+
});
|
|
4120
3796
|
|
|
4121
|
-
|
|
4122
|
-
this._preload_images(this._attach_and_animate);
|
|
3797
|
+
return props;
|
|
4123
3798
|
};
|
|
4124
3799
|
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
3800
|
+
MixpanelPersistence.prototype.update_config = function(config) {
|
|
3801
|
+
this.default_expiry = this.expire_days = config['cookie_expiration'];
|
|
3802
|
+
this.set_disabled(config['disable_persistence']);
|
|
3803
|
+
this.set_cookie_domain(config['cookie_domain']);
|
|
3804
|
+
this.set_cross_site(config['cross_site_cookie']);
|
|
3805
|
+
this.set_cross_subdomain(config['cross_subdomain_cookie']);
|
|
3806
|
+
this.set_secure(config['secure_cookie']);
|
|
3807
|
+
};
|
|
4131
3808
|
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
4135
|
-
this.
|
|
4136
|
-
setTimeout(this._remove_notification_el, MixpanelNotification.ANIM_TIME);
|
|
3809
|
+
MixpanelPersistence.prototype.set_disabled = function(disabled) {
|
|
3810
|
+
this.disabled = disabled;
|
|
3811
|
+
if (this.disabled) {
|
|
3812
|
+
this.remove();
|
|
4137
3813
|
} else {
|
|
4138
|
-
|
|
4139
|
-
if (this.mini) {
|
|
4140
|
-
notif_attr = 'right';
|
|
4141
|
-
notif_start = 20;
|
|
4142
|
-
notif_goal = -100;
|
|
4143
|
-
} else {
|
|
4144
|
-
notif_attr = 'top';
|
|
4145
|
-
notif_start = MixpanelNotification.NOTIF_TOP;
|
|
4146
|
-
notif_goal = MixpanelNotification.NOTIF_START_TOP + MixpanelNotification.NOTIF_TOP;
|
|
4147
|
-
}
|
|
4148
|
-
this._animate_els([
|
|
4149
|
-
{
|
|
4150
|
-
el: this._get_el('bg'),
|
|
4151
|
-
attr: 'opacity',
|
|
4152
|
-
start: MixpanelNotification.BG_OPACITY,
|
|
4153
|
-
goal: 0.0
|
|
4154
|
-
},
|
|
4155
|
-
{
|
|
4156
|
-
el: exiting_el,
|
|
4157
|
-
attr: 'opacity',
|
|
4158
|
-
start: 1.0,
|
|
4159
|
-
goal: 0.0
|
|
4160
|
-
},
|
|
4161
|
-
{
|
|
4162
|
-
el: exiting_el,
|
|
4163
|
-
attr: notif_attr,
|
|
4164
|
-
start: notif_start,
|
|
4165
|
-
goal: notif_goal
|
|
4166
|
-
}
|
|
4167
|
-
], MixpanelNotification.ANIM_TIME, this._remove_notification_el);
|
|
4168
|
-
}
|
|
4169
|
-
});
|
|
4170
|
-
|
|
4171
|
-
MixpanelNotification.prototype._add_class = _.safewrap(function(el, class_name) {
|
|
4172
|
-
class_name = MixpanelNotification.MARKUP_PREFIX + '-' + class_name;
|
|
4173
|
-
if (typeof el === 'string') {
|
|
4174
|
-
el = this._get_el(el);
|
|
4175
|
-
}
|
|
4176
|
-
if (!el.className) {
|
|
4177
|
-
el.className = class_name;
|
|
4178
|
-
} else if (!~(' ' + el.className + ' ').indexOf(' ' + class_name + ' ')) {
|
|
4179
|
-
el.className += ' ' + class_name;
|
|
4180
|
-
}
|
|
4181
|
-
});
|
|
4182
|
-
MixpanelNotification.prototype._remove_class = _.safewrap(function(el, class_name) {
|
|
4183
|
-
class_name = MixpanelNotification.MARKUP_PREFIX + '-' + class_name;
|
|
4184
|
-
if (typeof el === 'string') {
|
|
4185
|
-
el = this._get_el(el);
|
|
4186
|
-
}
|
|
4187
|
-
if (el.className) {
|
|
4188
|
-
el.className = (' ' + el.className + ' ')
|
|
4189
|
-
.replace(' ' + class_name + ' ', '')
|
|
4190
|
-
.replace(/^[\s\xA0]+/, '')
|
|
4191
|
-
.replace(/[\s\xA0]+$/, '');
|
|
3814
|
+
this.save();
|
|
4192
3815
|
}
|
|
4193
|
-
}
|
|
4194
|
-
|
|
4195
|
-
MixpanelNotification.prototype._animate_els = _.safewrap(function(anims, mss, done_cb, start_time) {
|
|
4196
|
-
var self = this,
|
|
4197
|
-
in_progress = false,
|
|
4198
|
-
ai, anim,
|
|
4199
|
-
cur_time = 1 * new Date(), time_diff;
|
|
4200
|
-
|
|
4201
|
-
start_time = start_time || cur_time;
|
|
4202
|
-
time_diff = cur_time - start_time;
|
|
3816
|
+
};
|
|
4203
3817
|
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
if (anim.val !== anim.goal) {
|
|
4210
|
-
in_progress = true;
|
|
4211
|
-
var anim_diff = anim.goal - anim.start,
|
|
4212
|
-
anim_dir = anim.goal >= anim.start ? 1 : -1;
|
|
4213
|
-
anim.val = anim.start + anim_diff * time_diff / mss;
|
|
4214
|
-
if (anim.attr !== 'opacity') {
|
|
4215
|
-
anim.val = Math.round(anim.val);
|
|
4216
|
-
}
|
|
4217
|
-
if ((anim_dir > 0 && anim.val >= anim.goal) || (anim_dir < 0 && anim.val <= anim.goal)) {
|
|
4218
|
-
anim.val = anim.goal;
|
|
4219
|
-
}
|
|
4220
|
-
}
|
|
4221
|
-
}
|
|
4222
|
-
if (!in_progress) {
|
|
4223
|
-
if (done_cb) {
|
|
4224
|
-
done_cb();
|
|
4225
|
-
}
|
|
4226
|
-
return;
|
|
3818
|
+
MixpanelPersistence.prototype.set_cookie_domain = function(cookie_domain) {
|
|
3819
|
+
if (cookie_domain !== this.cookie_domain) {
|
|
3820
|
+
this.remove();
|
|
3821
|
+
this.cookie_domain = cookie_domain;
|
|
3822
|
+
this.save();
|
|
4227
3823
|
}
|
|
3824
|
+
};
|
|
4228
3825
|
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
}
|
|
3826
|
+
MixpanelPersistence.prototype.set_cross_site = function(cross_site) {
|
|
3827
|
+
if (cross_site !== this.cross_site) {
|
|
3828
|
+
this.cross_site = cross_site;
|
|
3829
|
+
this.remove();
|
|
3830
|
+
this.save();
|
|
4235
3831
|
}
|
|
4236
|
-
|
|
4237
|
-
});
|
|
4238
|
-
|
|
4239
|
-
MixpanelNotification.prototype._attach_and_animate = _.safewrap(function() {
|
|
4240
|
-
var self = this;
|
|
3832
|
+
};
|
|
4241
3833
|
|
|
4242
|
-
|
|
4243
|
-
if (
|
|
4244
|
-
|
|
3834
|
+
MixpanelPersistence.prototype.set_cross_subdomain = function(cross_subdomain) {
|
|
3835
|
+
if (cross_subdomain !== this.cross_subdomain) {
|
|
3836
|
+
this.cross_subdomain = cross_subdomain;
|
|
3837
|
+
this.remove();
|
|
3838
|
+
this.save();
|
|
4245
3839
|
}
|
|
4246
|
-
this.shown = true;
|
|
4247
|
-
|
|
4248
|
-
this.body_el.appendChild(this.notification_el);
|
|
4249
|
-
setTimeout(function() {
|
|
4250
|
-
var notif_el = self._get_notification_display_el();
|
|
4251
|
-
if (self.use_transitions) {
|
|
4252
|
-
if (!self.mini) {
|
|
4253
|
-
self._add_class('bg', 'visible');
|
|
4254
|
-
}
|
|
4255
|
-
self._add_class(notif_el, 'visible');
|
|
4256
|
-
self._mark_as_shown();
|
|
4257
|
-
} else {
|
|
4258
|
-
var notif_attr, notif_start, notif_goal;
|
|
4259
|
-
if (self.mini) {
|
|
4260
|
-
notif_attr = 'right';
|
|
4261
|
-
notif_start = -100;
|
|
4262
|
-
notif_goal = 20;
|
|
4263
|
-
} else {
|
|
4264
|
-
notif_attr = 'top';
|
|
4265
|
-
notif_start = MixpanelNotification.NOTIF_START_TOP + MixpanelNotification.NOTIF_TOP;
|
|
4266
|
-
notif_goal = MixpanelNotification.NOTIF_TOP;
|
|
4267
|
-
}
|
|
4268
|
-
self._animate_els([
|
|
4269
|
-
{
|
|
4270
|
-
el: self._get_el('bg'),
|
|
4271
|
-
attr: 'opacity',
|
|
4272
|
-
start: 0.0,
|
|
4273
|
-
goal: MixpanelNotification.BG_OPACITY
|
|
4274
|
-
},
|
|
4275
|
-
{
|
|
4276
|
-
el: notif_el,
|
|
4277
|
-
attr: 'opacity',
|
|
4278
|
-
start: 0.0,
|
|
4279
|
-
goal: 1.0
|
|
4280
|
-
},
|
|
4281
|
-
{
|
|
4282
|
-
el: notif_el,
|
|
4283
|
-
attr: notif_attr,
|
|
4284
|
-
start: notif_start,
|
|
4285
|
-
goal: notif_goal
|
|
4286
|
-
}
|
|
4287
|
-
], MixpanelNotification.ANIM_TIME, self._mark_as_shown);
|
|
4288
|
-
}
|
|
4289
|
-
}, 100);
|
|
4290
|
-
_.register_event(self._get_el('cancel'), 'click', function(e) {
|
|
4291
|
-
e.preventDefault();
|
|
4292
|
-
self.dismiss();
|
|
4293
|
-
});
|
|
4294
|
-
var click_el = self._get_el('button') ||
|
|
4295
|
-
self._get_el('mini-content');
|
|
4296
|
-
_.register_event(click_el, 'click', function(e) {
|
|
4297
|
-
e.preventDefault();
|
|
4298
|
-
if (self.show_video) {
|
|
4299
|
-
self._track_event('$campaign_open', {'$resource_type': 'video'});
|
|
4300
|
-
self._switch_to_video();
|
|
4301
|
-
} else {
|
|
4302
|
-
self.dismiss();
|
|
4303
|
-
if (self.clickthrough) {
|
|
4304
|
-
var tracking_cb = null;
|
|
4305
|
-
if (self.mixpanel.get_config('inapp_link_new_window')) {
|
|
4306
|
-
window.open(self.dest_url);
|
|
4307
|
-
} else {
|
|
4308
|
-
tracking_cb = function() {
|
|
4309
|
-
window.location.href = self.dest_url;
|
|
4310
|
-
};
|
|
4311
|
-
}
|
|
4312
|
-
self._track_event('$campaign_open', {'$resource_type': 'link'}, tracking_cb);
|
|
4313
|
-
}
|
|
4314
|
-
}
|
|
4315
|
-
});
|
|
4316
|
-
});
|
|
4317
|
-
|
|
4318
|
-
MixpanelNotification.prototype._get_el = function(id) {
|
|
4319
|
-
return document.getElementById(MixpanelNotification.MARKUP_PREFIX + '-' + id);
|
|
4320
3840
|
};
|
|
4321
3841
|
|
|
4322
|
-
|
|
4323
|
-
return this.
|
|
3842
|
+
MixpanelPersistence.prototype.get_cross_subdomain = function() {
|
|
3843
|
+
return this.cross_subdomain;
|
|
4324
3844
|
};
|
|
4325
3845
|
|
|
4326
|
-
|
|
4327
|
-
|
|
3846
|
+
MixpanelPersistence.prototype.set_secure = function(secure) {
|
|
3847
|
+
if (secure !== this.secure) {
|
|
3848
|
+
this.secure = secure ? true : false;
|
|
3849
|
+
this.remove();
|
|
3850
|
+
this.save();
|
|
3851
|
+
}
|
|
4328
3852
|
};
|
|
4329
3853
|
|
|
4330
|
-
|
|
4331
|
-
var
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
|
|
4335
|
-
|
|
4336
|
-
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
} else {
|
|
4341
|
-
return true;
|
|
4342
|
-
}
|
|
4343
|
-
}
|
|
4344
|
-
}
|
|
4345
|
-
return false;
|
|
4346
|
-
});
|
|
4347
|
-
|
|
4348
|
-
|
|
4349
|
-
MixpanelNotification.prototype._browser_lte = function(browser, version) {
|
|
4350
|
-
return this.browser_versions[browser] && this.browser_versions[browser] <= version;
|
|
4351
|
-
};
|
|
4352
|
-
|
|
4353
|
-
MixpanelNotification.prototype._init_image_html = function() {
|
|
4354
|
-
var imgs_to_preload = [];
|
|
4355
|
-
|
|
4356
|
-
if (!this.mini) {
|
|
4357
|
-
if (this.image_url) {
|
|
4358
|
-
imgs_to_preload.push(this.image_url);
|
|
4359
|
-
this.img_html = '<img id="img" src="' + this.image_url + '"/>';
|
|
4360
|
-
} else {
|
|
4361
|
-
this.img_html = '';
|
|
4362
|
-
}
|
|
4363
|
-
if (this.thumb_image_url) {
|
|
4364
|
-
imgs_to_preload.push(this.thumb_image_url);
|
|
4365
|
-
this.thumb_img_html =
|
|
4366
|
-
'<div id="thumbborder-wrapper"><div id="thumbborder"></div></div>' +
|
|
4367
|
-
'<img id="thumbnail"' +
|
|
4368
|
-
' src="' + this.thumb_image_url + '"' +
|
|
4369
|
-
' width="' + MixpanelNotification.THUMB_IMG_SIZE + '"' +
|
|
4370
|
-
' height="' + MixpanelNotification.THUMB_IMG_SIZE + '"' +
|
|
4371
|
-
'/>' +
|
|
4372
|
-
'<div id="thumbspacer"></div>';
|
|
4373
|
-
} else {
|
|
4374
|
-
this.thumb_img_html = '';
|
|
4375
|
-
}
|
|
4376
|
-
} else {
|
|
4377
|
-
this.thumb_image_url = this.thumb_image_url || (this.cdn_host + '/site_media/images/icons/notifications/mini-news-dark.png');
|
|
4378
|
-
imgs_to_preload.push(this.thumb_image_url);
|
|
4379
|
-
}
|
|
4380
|
-
|
|
4381
|
-
return imgs_to_preload;
|
|
4382
|
-
};
|
|
4383
|
-
|
|
4384
|
-
MixpanelNotification.prototype._init_notification_el = function() {
|
|
4385
|
-
var notification_html = '';
|
|
4386
|
-
var video_src = '';
|
|
4387
|
-
var video_html = '';
|
|
4388
|
-
var cancel_html = '<div id="cancel">' +
|
|
4389
|
-
'<div id="cancel-icon"></div>' +
|
|
4390
|
-
'</div>';
|
|
4391
|
-
|
|
4392
|
-
this.notification_el = document.createElement('div');
|
|
4393
|
-
this.notification_el.id = MixpanelNotification.MARKUP_PREFIX + '-wrapper';
|
|
4394
|
-
if (!this.mini) {
|
|
4395
|
-
// TAKEOVER notification
|
|
4396
|
-
var close_html = (this.clickthrough || this.show_video) ? '' : '<div id="button-close"></div>',
|
|
4397
|
-
play_html = this.show_video ? '<div id="button-play"></div>' : '';
|
|
4398
|
-
if (this._browser_lte('ie', 7)) {
|
|
4399
|
-
close_html = '';
|
|
4400
|
-
play_html = '';
|
|
4401
|
-
}
|
|
4402
|
-
notification_html =
|
|
4403
|
-
'<div id="takeover">' +
|
|
4404
|
-
this.thumb_img_html +
|
|
4405
|
-
'<div id="mainbox">' +
|
|
4406
|
-
cancel_html +
|
|
4407
|
-
'<div id="content">' +
|
|
4408
|
-
this.img_html +
|
|
4409
|
-
'<div id="title">' + this.title + '</div>' +
|
|
4410
|
-
'<div id="body">' + this.body + '</div>' +
|
|
4411
|
-
'<div id="tagline">' +
|
|
4412
|
-
'<a href="http://mixpanel.com?from=inapp" target="_blank">POWERED BY MIXPANEL</a>' +
|
|
4413
|
-
'</div>' +
|
|
4414
|
-
'</div>' +
|
|
4415
|
-
'<div id="button">' +
|
|
4416
|
-
close_html +
|
|
4417
|
-
'<a id="button-link" href="' + this.dest_url + '">' + this.cta + '</a>' +
|
|
4418
|
-
play_html +
|
|
4419
|
-
'</div>' +
|
|
4420
|
-
'</div>' +
|
|
4421
|
-
'</div>';
|
|
4422
|
-
} else {
|
|
4423
|
-
// MINI notification
|
|
4424
|
-
notification_html =
|
|
4425
|
-
'<div id="mini">' +
|
|
4426
|
-
'<div id="mainbox">' +
|
|
4427
|
-
cancel_html +
|
|
4428
|
-
'<div id="mini-content">' +
|
|
4429
|
-
'<div id="mini-icon">' +
|
|
4430
|
-
'<div id="mini-icon-img"></div>' +
|
|
4431
|
-
'</div>' +
|
|
4432
|
-
'<div id="body">' +
|
|
4433
|
-
'<div id="body-text"><div>' + this.body + '</div></div>' +
|
|
4434
|
-
'</div>' +
|
|
4435
|
-
'</div>' +
|
|
4436
|
-
'</div>' +
|
|
4437
|
-
'<div id="mini-border"></div>' +
|
|
4438
|
-
'</div>';
|
|
4439
|
-
}
|
|
4440
|
-
if (this.youtube_video) {
|
|
4441
|
-
video_src = this.resource_protocol + 'www.youtube.com/embed/' + this.youtube_video +
|
|
4442
|
-
'?wmode=transparent&showinfo=0&modestbranding=0&rel=0&autoplay=1&loop=0&vq=hd1080';
|
|
4443
|
-
if (this.yt_custom) {
|
|
4444
|
-
video_src += '&enablejsapi=1&html5=1&controls=0';
|
|
4445
|
-
video_html =
|
|
4446
|
-
'<div id="video-controls">' +
|
|
4447
|
-
'<div id="video-progress" class="video-progress-el">' +
|
|
4448
|
-
'<div id="video-progress-total" class="video-progress-el"></div>' +
|
|
4449
|
-
'<div id="video-elapsed" class="video-progress-el"></div>' +
|
|
4450
|
-
'</div>' +
|
|
4451
|
-
'<div id="video-time" class="video-progress-el"></div>' +
|
|
4452
|
-
'</div>';
|
|
4453
|
-
}
|
|
4454
|
-
} else if (this.vimeo_video) {
|
|
4455
|
-
video_src = this.resource_protocol + 'player.vimeo.com/video/' + this.vimeo_video + '?autoplay=1&title=0&byline=0&portrait=0';
|
|
4456
|
-
}
|
|
4457
|
-
if (this.show_video) {
|
|
4458
|
-
this.video_iframe =
|
|
4459
|
-
'<iframe id="' + MixpanelNotification.MARKUP_PREFIX + '-video-frame" ' +
|
|
4460
|
-
'width="' + this.video_width + '" height="' + this.video_height + '" ' +
|
|
4461
|
-
' src="' + video_src + '"' +
|
|
4462
|
-
' frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen="1" scrolling="no"' +
|
|
4463
|
-
'></iframe>';
|
|
4464
|
-
video_html =
|
|
4465
|
-
'<div id="video-' + (this.flip_animate ? '' : 'no') + 'flip">' +
|
|
4466
|
-
'<div id="video">' +
|
|
4467
|
-
'<div id="video-holder"></div>' +
|
|
4468
|
-
video_html +
|
|
4469
|
-
'</div>' +
|
|
4470
|
-
'</div>';
|
|
4471
|
-
}
|
|
4472
|
-
var main_html = video_html + notification_html;
|
|
4473
|
-
if (this.flip_animate) {
|
|
4474
|
-
main_html =
|
|
4475
|
-
(this.mini ? notification_html : '') +
|
|
4476
|
-
'<div id="flipcontainer"><div id="flipper">' +
|
|
4477
|
-
(this.mini ? video_html : main_html) +
|
|
4478
|
-
'</div></div>';
|
|
4479
|
-
}
|
|
4480
|
-
|
|
4481
|
-
this.notification_el.innerHTML =
|
|
4482
|
-
('<div id="overlay" class="' + this.notif_type + '">' +
|
|
4483
|
-
'<div id="campaignid-' + this.campaign_id + '">' +
|
|
4484
|
-
'<div id="bgwrapper">' +
|
|
4485
|
-
'<div id="bg"></div>' +
|
|
4486
|
-
main_html +
|
|
4487
|
-
'</div>' +
|
|
4488
|
-
'</div>' +
|
|
4489
|
-
'</div>')
|
|
4490
|
-
.replace(/class="/g, 'class="' + MixpanelNotification.MARKUP_PREFIX + '-')
|
|
4491
|
-
.replace(/id="/g, 'id="' + MixpanelNotification.MARKUP_PREFIX + '-');
|
|
4492
|
-
};
|
|
4493
|
-
|
|
4494
|
-
MixpanelNotification.prototype._init_styles = function() {
|
|
4495
|
-
if (this.style === 'dark') {
|
|
4496
|
-
this.style_vals = {
|
|
4497
|
-
bg: '#1d1f25',
|
|
4498
|
-
bg_actions: '#282b32',
|
|
4499
|
-
bg_hover: '#3a4147',
|
|
4500
|
-
bg_light: '#4a5157',
|
|
4501
|
-
border_gray: '#32353c',
|
|
4502
|
-
cancel_opacity: '0.4',
|
|
4503
|
-
mini_hover: '#2a3137',
|
|
4504
|
-
text_title: '#fff',
|
|
4505
|
-
text_main: '#9498a3',
|
|
4506
|
-
text_tagline: '#464851',
|
|
4507
|
-
text_hover: '#ddd'
|
|
4508
|
-
};
|
|
4509
|
-
} else {
|
|
4510
|
-
this.style_vals = {
|
|
4511
|
-
bg: '#fff',
|
|
4512
|
-
bg_actions: '#e7eaee',
|
|
4513
|
-
bg_hover: '#eceff3',
|
|
4514
|
-
bg_light: '#f5f5f5',
|
|
4515
|
-
border_gray: '#e4ecf2',
|
|
4516
|
-
cancel_opacity: '1.0',
|
|
4517
|
-
mini_hover: '#fafafa',
|
|
4518
|
-
text_title: '#5c6578',
|
|
4519
|
-
text_main: '#8b949b',
|
|
4520
|
-
text_tagline: '#ced9e6',
|
|
4521
|
-
text_hover: '#7c8598'
|
|
4522
|
-
};
|
|
4523
|
-
}
|
|
4524
|
-
var shadow = '0px 0px 35px 0px rgba(45, 49, 56, 0.7)',
|
|
4525
|
-
video_shadow = shadow,
|
|
4526
|
-
mini_shadow = shadow,
|
|
4527
|
-
thumb_total_size = MixpanelNotification.THUMB_IMG_SIZE + MixpanelNotification.THUMB_BORDER_SIZE * 2,
|
|
4528
|
-
anim_seconds = (MixpanelNotification.ANIM_TIME / 1000) + 's';
|
|
4529
|
-
if (this.mini) {
|
|
4530
|
-
shadow = 'none';
|
|
4531
|
-
}
|
|
4532
|
-
|
|
4533
|
-
// don't display on small viewports
|
|
4534
|
-
var notif_media_queries = {},
|
|
4535
|
-
min_width = MixpanelNotification.NOTIF_WIDTH_MINI + 20;
|
|
4536
|
-
notif_media_queries['@media only screen and (max-width: ' + (min_width - 1) + 'px)'] = {
|
|
4537
|
-
'#overlay': {
|
|
4538
|
-
'display': 'none'
|
|
4539
|
-
}
|
|
4540
|
-
};
|
|
4541
|
-
var notif_styles = {
|
|
4542
|
-
'.flipped': {
|
|
4543
|
-
'transform': 'rotateY(180deg)'
|
|
4544
|
-
},
|
|
4545
|
-
'#overlay': {
|
|
4546
|
-
'position': 'fixed',
|
|
4547
|
-
'top': '0',
|
|
4548
|
-
'left': '0',
|
|
4549
|
-
'width': '100%',
|
|
4550
|
-
'height': '100%',
|
|
4551
|
-
'overflow': 'auto',
|
|
4552
|
-
'text-align': 'center',
|
|
4553
|
-
'z-index': '10000',
|
|
4554
|
-
'font-family': '"Helvetica", "Arial", sans-serif',
|
|
4555
|
-
'-webkit-font-smoothing': 'antialiased',
|
|
4556
|
-
'-moz-osx-font-smoothing': 'grayscale'
|
|
4557
|
-
},
|
|
4558
|
-
'#overlay.mini': {
|
|
4559
|
-
'height': '0',
|
|
4560
|
-
'overflow': 'visible'
|
|
4561
|
-
},
|
|
4562
|
-
'#overlay a': {
|
|
4563
|
-
'width': 'initial',
|
|
4564
|
-
'padding': '0',
|
|
4565
|
-
'text-decoration': 'none',
|
|
4566
|
-
'text-transform': 'none',
|
|
4567
|
-
'color': 'inherit'
|
|
4568
|
-
},
|
|
4569
|
-
'#bgwrapper': {
|
|
4570
|
-
'position': 'relative',
|
|
4571
|
-
'width': '100%',
|
|
4572
|
-
'height': '100%'
|
|
4573
|
-
},
|
|
4574
|
-
'#bg': {
|
|
4575
|
-
'position': 'fixed',
|
|
4576
|
-
'top': '0',
|
|
4577
|
-
'left': '0',
|
|
4578
|
-
'width': '100%',
|
|
4579
|
-
'height': '100%',
|
|
4580
|
-
'min-width': this.doc_width * 4 + 'px',
|
|
4581
|
-
'min-height': this.doc_height * 4 + 'px',
|
|
4582
|
-
'background-color': 'black',
|
|
4583
|
-
'opacity': '0.0',
|
|
4584
|
-
'-ms-filter': 'progid:DXImageTransform.Microsoft.Alpha(Opacity=60)', // IE8
|
|
4585
|
-
'filter': 'alpha(opacity=60)', // IE5-7
|
|
4586
|
-
'transition': 'opacity ' + anim_seconds
|
|
4587
|
-
},
|
|
4588
|
-
'#bg.visible': {
|
|
4589
|
-
'opacity': MixpanelNotification.BG_OPACITY
|
|
4590
|
-
},
|
|
4591
|
-
'.mini #bg': {
|
|
4592
|
-
'width': '0',
|
|
4593
|
-
'height': '0',
|
|
4594
|
-
'min-width': '0'
|
|
4595
|
-
},
|
|
4596
|
-
'#flipcontainer': {
|
|
4597
|
-
'perspective': '1000px',
|
|
4598
|
-
'position': 'absolute',
|
|
4599
|
-
'width': '100%'
|
|
4600
|
-
},
|
|
4601
|
-
'#flipper': {
|
|
4602
|
-
'position': 'relative',
|
|
4603
|
-
'transform-style': 'preserve-3d',
|
|
4604
|
-
'transition': '0.3s'
|
|
4605
|
-
},
|
|
4606
|
-
'#takeover': {
|
|
4607
|
-
'position': 'absolute',
|
|
4608
|
-
'left': '50%',
|
|
4609
|
-
'width': MixpanelNotification.NOTIF_WIDTH + 'px',
|
|
4610
|
-
'margin-left': Math.round(-MixpanelNotification.NOTIF_WIDTH / 2) + 'px',
|
|
4611
|
-
'backface-visibility': 'hidden',
|
|
4612
|
-
'transform': 'rotateY(0deg)',
|
|
4613
|
-
'opacity': '0.0',
|
|
4614
|
-
'top': MixpanelNotification.NOTIF_START_TOP + 'px',
|
|
4615
|
-
'transition': 'opacity ' + anim_seconds + ', top ' + anim_seconds
|
|
4616
|
-
},
|
|
4617
|
-
'#takeover.visible': {
|
|
4618
|
-
'opacity': '1.0',
|
|
4619
|
-
'top': MixpanelNotification.NOTIF_TOP + 'px'
|
|
4620
|
-
},
|
|
4621
|
-
'#takeover.exiting': {
|
|
4622
|
-
'opacity': '0.0',
|
|
4623
|
-
'top': MixpanelNotification.NOTIF_START_TOP + 'px'
|
|
4624
|
-
},
|
|
4625
|
-
'#thumbspacer': {
|
|
4626
|
-
'height': MixpanelNotification.THUMB_OFFSET + 'px'
|
|
4627
|
-
},
|
|
4628
|
-
'#thumbborder-wrapper': {
|
|
4629
|
-
'position': 'absolute',
|
|
4630
|
-
'top': (-MixpanelNotification.THUMB_BORDER_SIZE) + 'px',
|
|
4631
|
-
'left': (MixpanelNotification.NOTIF_WIDTH / 2 - MixpanelNotification.THUMB_OFFSET - MixpanelNotification.THUMB_BORDER_SIZE) + 'px',
|
|
4632
|
-
'width': thumb_total_size + 'px',
|
|
4633
|
-
'height': (thumb_total_size / 2) + 'px',
|
|
4634
|
-
'overflow': 'hidden'
|
|
4635
|
-
},
|
|
4636
|
-
'#thumbborder': {
|
|
4637
|
-
'position': 'absolute',
|
|
4638
|
-
'width': thumb_total_size + 'px',
|
|
4639
|
-
'height': thumb_total_size + 'px',
|
|
4640
|
-
'border-radius': thumb_total_size + 'px',
|
|
4641
|
-
'background-color': this.style_vals.bg_actions,
|
|
4642
|
-
'opacity': '0.5'
|
|
4643
|
-
},
|
|
4644
|
-
'#thumbnail': {
|
|
4645
|
-
'position': 'absolute',
|
|
4646
|
-
'top': '0px',
|
|
4647
|
-
'left': (MixpanelNotification.NOTIF_WIDTH / 2 - MixpanelNotification.THUMB_OFFSET) + 'px',
|
|
4648
|
-
'width': MixpanelNotification.THUMB_IMG_SIZE + 'px',
|
|
4649
|
-
'height': MixpanelNotification.THUMB_IMG_SIZE + 'px',
|
|
4650
|
-
'overflow': 'hidden',
|
|
4651
|
-
'z-index': '100',
|
|
4652
|
-
'border-radius': MixpanelNotification.THUMB_IMG_SIZE + 'px'
|
|
4653
|
-
},
|
|
4654
|
-
'#mini': {
|
|
4655
|
-
'position': 'absolute',
|
|
4656
|
-
'right': '20px',
|
|
4657
|
-
'top': MixpanelNotification.NOTIF_TOP + 'px',
|
|
4658
|
-
'width': this.notif_width + 'px',
|
|
4659
|
-
'height': MixpanelNotification.NOTIF_HEIGHT_MINI * 2 + 'px',
|
|
4660
|
-
'margin-top': 20 - MixpanelNotification.NOTIF_HEIGHT_MINI + 'px',
|
|
4661
|
-
'backface-visibility': 'hidden',
|
|
4662
|
-
'opacity': '0.0',
|
|
4663
|
-
'transform': 'rotateX(90deg)',
|
|
4664
|
-
'transition': 'opacity 0.3s, transform 0.3s, right 0.3s'
|
|
4665
|
-
},
|
|
4666
|
-
'#mini.visible': {
|
|
4667
|
-
'opacity': '1.0',
|
|
4668
|
-
'transform': 'rotateX(0deg)'
|
|
4669
|
-
},
|
|
4670
|
-
'#mini.exiting': {
|
|
4671
|
-
'opacity': '0.0',
|
|
4672
|
-
'right': '-150px'
|
|
4673
|
-
},
|
|
4674
|
-
'#mainbox': {
|
|
4675
|
-
'border-radius': '4px',
|
|
4676
|
-
'box-shadow': shadow,
|
|
4677
|
-
'text-align': 'center',
|
|
4678
|
-
'background-color': this.style_vals.bg,
|
|
4679
|
-
'font-size': '14px',
|
|
4680
|
-
'color': this.style_vals.text_main
|
|
4681
|
-
},
|
|
4682
|
-
'#mini #mainbox': {
|
|
4683
|
-
'height': MixpanelNotification.NOTIF_HEIGHT_MINI + 'px',
|
|
4684
|
-
'margin-top': MixpanelNotification.NOTIF_HEIGHT_MINI + 'px',
|
|
4685
|
-
'border-radius': '3px',
|
|
4686
|
-
'transition': 'background-color ' + anim_seconds
|
|
4687
|
-
},
|
|
4688
|
-
'#mini-border': {
|
|
4689
|
-
'height': (MixpanelNotification.NOTIF_HEIGHT_MINI + 6) + 'px',
|
|
4690
|
-
'width': (MixpanelNotification.NOTIF_WIDTH_MINI + 6) + 'px',
|
|
4691
|
-
'position': 'absolute',
|
|
4692
|
-
'top': '-3px',
|
|
4693
|
-
'left': '-3px',
|
|
4694
|
-
'margin-top': MixpanelNotification.NOTIF_HEIGHT_MINI + 'px',
|
|
4695
|
-
'border-radius': '6px',
|
|
4696
|
-
'opacity': '0.25',
|
|
4697
|
-
'background-color': '#fff',
|
|
4698
|
-
'z-index': '-1',
|
|
4699
|
-
'box-shadow': mini_shadow
|
|
4700
|
-
},
|
|
4701
|
-
'#mini-icon': {
|
|
4702
|
-
'position': 'relative',
|
|
4703
|
-
'display': 'inline-block',
|
|
4704
|
-
'width': '75px',
|
|
4705
|
-
'height': MixpanelNotification.NOTIF_HEIGHT_MINI + 'px',
|
|
4706
|
-
'border-radius': '3px 0 0 3px',
|
|
4707
|
-
'background-color': this.style_vals.bg_actions,
|
|
4708
|
-
'background': 'linear-gradient(135deg, ' + this.style_vals.bg_light + ' 0%, ' + this.style_vals.bg_actions + ' 100%)',
|
|
4709
|
-
'transition': 'background-color ' + anim_seconds
|
|
4710
|
-
},
|
|
4711
|
-
'#mini:hover #mini-icon': {
|
|
4712
|
-
'background-color': this.style_vals.mini_hover
|
|
4713
|
-
},
|
|
4714
|
-
'#mini:hover #mainbox': {
|
|
4715
|
-
'background-color': this.style_vals.mini_hover
|
|
4716
|
-
},
|
|
4717
|
-
'#mini-icon-img': {
|
|
4718
|
-
'position': 'absolute',
|
|
4719
|
-
'background-image': 'url(' + this.thumb_image_url + ')',
|
|
4720
|
-
'width': '48px',
|
|
4721
|
-
'height': '48px',
|
|
4722
|
-
'top': '20px',
|
|
4723
|
-
'left': '12px'
|
|
4724
|
-
},
|
|
4725
|
-
'#content': {
|
|
4726
|
-
'padding': '30px 20px 0px 20px'
|
|
4727
|
-
},
|
|
4728
|
-
'#mini-content': {
|
|
4729
|
-
'text-align': 'left',
|
|
4730
|
-
'height': MixpanelNotification.NOTIF_HEIGHT_MINI + 'px',
|
|
4731
|
-
'cursor': 'pointer'
|
|
4732
|
-
},
|
|
4733
|
-
'#img': {
|
|
4734
|
-
'width': '328px',
|
|
4735
|
-
'margin-top': '30px',
|
|
4736
|
-
'border-radius': '5px'
|
|
4737
|
-
},
|
|
4738
|
-
'#title': {
|
|
4739
|
-
'max-height': '600px',
|
|
4740
|
-
'overflow': 'hidden',
|
|
4741
|
-
'word-wrap': 'break-word',
|
|
4742
|
-
'padding': '25px 0px 20px 0px',
|
|
4743
|
-
'font-size': '19px',
|
|
4744
|
-
'font-weight': 'bold',
|
|
4745
|
-
'color': this.style_vals.text_title
|
|
4746
|
-
},
|
|
4747
|
-
'#body': {
|
|
4748
|
-
'max-height': '600px',
|
|
4749
|
-
'margin-bottom': '25px',
|
|
4750
|
-
'overflow': 'hidden',
|
|
4751
|
-
'word-wrap': 'break-word',
|
|
4752
|
-
'line-height': '21px',
|
|
4753
|
-
'font-size': '15px',
|
|
4754
|
-
'font-weight': 'normal',
|
|
4755
|
-
'text-align': 'left'
|
|
4756
|
-
},
|
|
4757
|
-
'#mini #body': {
|
|
4758
|
-
'display': 'inline-block',
|
|
4759
|
-
'max-width': '250px',
|
|
4760
|
-
'margin': '0 0 0 30px',
|
|
4761
|
-
'height': MixpanelNotification.NOTIF_HEIGHT_MINI + 'px',
|
|
4762
|
-
'font-size': '16px',
|
|
4763
|
-
'letter-spacing': '0.8px',
|
|
4764
|
-
'color': this.style_vals.text_title
|
|
4765
|
-
},
|
|
4766
|
-
'#mini #body-text': {
|
|
4767
|
-
'display': 'table',
|
|
4768
|
-
'height': MixpanelNotification.NOTIF_HEIGHT_MINI + 'px'
|
|
4769
|
-
},
|
|
4770
|
-
'#mini #body-text div': {
|
|
4771
|
-
'display': 'table-cell',
|
|
4772
|
-
'vertical-align': 'middle'
|
|
4773
|
-
},
|
|
4774
|
-
'#tagline': {
|
|
4775
|
-
'margin-bottom': '15px',
|
|
4776
|
-
'font-size': '10px',
|
|
4777
|
-
'font-weight': '600',
|
|
4778
|
-
'letter-spacing': '0.8px',
|
|
4779
|
-
'color': '#ccd7e0',
|
|
4780
|
-
'text-align': 'left'
|
|
4781
|
-
},
|
|
4782
|
-
'#tagline a': {
|
|
4783
|
-
'color': this.style_vals.text_tagline,
|
|
4784
|
-
'transition': 'color ' + anim_seconds
|
|
4785
|
-
},
|
|
4786
|
-
'#tagline a:hover': {
|
|
4787
|
-
'color': this.style_vals.text_hover
|
|
4788
|
-
},
|
|
4789
|
-
'#cancel': {
|
|
4790
|
-
'position': 'absolute',
|
|
4791
|
-
'right': '0',
|
|
4792
|
-
'width': '8px',
|
|
4793
|
-
'height': '8px',
|
|
4794
|
-
'padding': '10px',
|
|
4795
|
-
'border-radius': '20px',
|
|
4796
|
-
'margin': '12px 12px 0 0',
|
|
4797
|
-
'box-sizing': 'content-box',
|
|
4798
|
-
'cursor': 'pointer',
|
|
4799
|
-
'transition': 'background-color ' + anim_seconds
|
|
4800
|
-
},
|
|
4801
|
-
'#mini #cancel': {
|
|
4802
|
-
'margin': '7px 7px 0 0'
|
|
4803
|
-
},
|
|
4804
|
-
'#cancel-icon': {
|
|
4805
|
-
'width': '8px',
|
|
4806
|
-
'height': '8px',
|
|
4807
|
-
'overflow': 'hidden',
|
|
4808
|
-
'background-image': 'url(' + this.cdn_host + '/site_media/images/icons/notifications/cancel-x.png)',
|
|
4809
|
-
'opacity': this.style_vals.cancel_opacity
|
|
4810
|
-
},
|
|
4811
|
-
'#cancel:hover': {
|
|
4812
|
-
'background-color': this.style_vals.bg_hover
|
|
4813
|
-
},
|
|
4814
|
-
'#button': {
|
|
4815
|
-
'display': 'block',
|
|
4816
|
-
'height': '60px',
|
|
4817
|
-
'line-height': '60px',
|
|
4818
|
-
'text-align': 'center',
|
|
4819
|
-
'background-color': this.style_vals.bg_actions,
|
|
4820
|
-
'border-radius': '0 0 4px 4px',
|
|
4821
|
-
'overflow': 'hidden',
|
|
4822
|
-
'cursor': 'pointer',
|
|
4823
|
-
'transition': 'background-color ' + anim_seconds
|
|
4824
|
-
},
|
|
4825
|
-
'#button-close': {
|
|
4826
|
-
'display': 'inline-block',
|
|
4827
|
-
'width': '9px',
|
|
4828
|
-
'height': '60px',
|
|
4829
|
-
'margin-right': '8px',
|
|
4830
|
-
'vertical-align': 'top',
|
|
4831
|
-
'background-image': 'url(' + this.cdn_host + '/site_media/images/icons/notifications/close-x-' + this.style + '.png)',
|
|
4832
|
-
'background-repeat': 'no-repeat',
|
|
4833
|
-
'background-position': '0px 25px'
|
|
4834
|
-
},
|
|
4835
|
-
'#button-play': {
|
|
4836
|
-
'display': 'inline-block',
|
|
4837
|
-
'width': '30px',
|
|
4838
|
-
'height': '60px',
|
|
4839
|
-
'margin-left': '15px',
|
|
4840
|
-
'background-image': 'url(' + this.cdn_host + '/site_media/images/icons/notifications/play-' + this.style + '-small.png)',
|
|
4841
|
-
'background-repeat': 'no-repeat',
|
|
4842
|
-
'background-position': '0px 15px'
|
|
4843
|
-
},
|
|
4844
|
-
'a#button-link': {
|
|
4845
|
-
'display': 'inline-block',
|
|
4846
|
-
'vertical-align': 'top',
|
|
4847
|
-
'text-align': 'center',
|
|
4848
|
-
'font-size': '17px',
|
|
4849
|
-
'font-weight': 'bold',
|
|
4850
|
-
'overflow': 'hidden',
|
|
4851
|
-
'word-wrap': 'break-word',
|
|
4852
|
-
'color': this.style_vals.text_title,
|
|
4853
|
-
'transition': 'color ' + anim_seconds
|
|
4854
|
-
},
|
|
4855
|
-
'#button:hover': {
|
|
4856
|
-
'background-color': this.style_vals.bg_hover,
|
|
4857
|
-
'color': this.style_vals.text_hover
|
|
4858
|
-
},
|
|
4859
|
-
'#button:hover a': {
|
|
4860
|
-
'color': this.style_vals.text_hover
|
|
4861
|
-
},
|
|
4862
|
-
|
|
4863
|
-
'#video-noflip': {
|
|
4864
|
-
'position': 'relative',
|
|
4865
|
-
'top': (-this.video_height * 2) + 'px'
|
|
4866
|
-
},
|
|
4867
|
-
'#video-flip': {
|
|
4868
|
-
'backface-visibility': 'hidden',
|
|
4869
|
-
'transform': 'rotateY(180deg)'
|
|
4870
|
-
},
|
|
4871
|
-
'#video': {
|
|
4872
|
-
'position': 'absolute',
|
|
4873
|
-
'width': (this.video_width - 1) + 'px',
|
|
4874
|
-
'height': this.video_height + 'px',
|
|
4875
|
-
'top': MixpanelNotification.NOTIF_TOP + 'px',
|
|
4876
|
-
'margin-top': '100px',
|
|
4877
|
-
'left': '50%',
|
|
4878
|
-
'margin-left': Math.round(-this.video_width / 2) + 'px',
|
|
4879
|
-
'overflow': 'hidden',
|
|
4880
|
-
'border-radius': '5px',
|
|
4881
|
-
'box-shadow': video_shadow,
|
|
4882
|
-
'transform': 'translateZ(1px)', // webkit rendering bug http://stackoverflow.com/questions/18167981/clickable-link-area-unexpectedly-smaller-after-css-transform
|
|
4883
|
-
'transition': 'opacity ' + anim_seconds + ', top ' + anim_seconds
|
|
4884
|
-
},
|
|
4885
|
-
'#video.exiting': {
|
|
4886
|
-
'opacity': '0.0',
|
|
4887
|
-
'top': this.video_height + 'px'
|
|
4888
|
-
},
|
|
4889
|
-
'#video-holder': {
|
|
4890
|
-
'position': 'absolute',
|
|
4891
|
-
'width': (this.video_width - 1) + 'px',
|
|
4892
|
-
'height': this.video_height + 'px',
|
|
4893
|
-
'overflow': 'hidden',
|
|
4894
|
-
'border-radius': '5px'
|
|
4895
|
-
},
|
|
4896
|
-
'#video-frame': {
|
|
4897
|
-
'margin-left': '-1px',
|
|
4898
|
-
'width': this.video_width + 'px'
|
|
4899
|
-
},
|
|
4900
|
-
'#video-controls': {
|
|
4901
|
-
'opacity': '0',
|
|
4902
|
-
'transition': 'opacity 0.5s'
|
|
4903
|
-
},
|
|
4904
|
-
'#video:hover #video-controls': {
|
|
4905
|
-
'opacity': '1.0'
|
|
4906
|
-
},
|
|
4907
|
-
'#video .video-progress-el': {
|
|
4908
|
-
'position': 'absolute',
|
|
4909
|
-
'bottom': '0',
|
|
4910
|
-
'height': '25px',
|
|
4911
|
-
'border-radius': '0 0 0 5px'
|
|
4912
|
-
},
|
|
4913
|
-
'#video-progress': {
|
|
4914
|
-
'width': '90%'
|
|
4915
|
-
},
|
|
4916
|
-
'#video-progress-total': {
|
|
4917
|
-
'width': '100%',
|
|
4918
|
-
'background-color': this.style_vals.bg,
|
|
4919
|
-
'opacity': '0.7'
|
|
4920
|
-
},
|
|
4921
|
-
'#video-elapsed': {
|
|
4922
|
-
'width': '0',
|
|
4923
|
-
'background-color': '#6cb6f5',
|
|
4924
|
-
'opacity': '0.9'
|
|
4925
|
-
},
|
|
4926
|
-
'#video #video-time': {
|
|
4927
|
-
'width': '10%',
|
|
4928
|
-
'right': '0',
|
|
4929
|
-
'font-size': '11px',
|
|
4930
|
-
'line-height': '25px',
|
|
4931
|
-
'color': this.style_vals.text_main,
|
|
4932
|
-
'background-color': '#666',
|
|
4933
|
-
'border-radius': '0 0 5px 0'
|
|
4934
|
-
}
|
|
4935
|
-
};
|
|
4936
|
-
|
|
4937
|
-
// IE hacks
|
|
4938
|
-
if (this._browser_lte('ie', 8)) {
|
|
4939
|
-
_.extend(notif_styles, {
|
|
4940
|
-
'* html #overlay': {
|
|
4941
|
-
'position': 'absolute'
|
|
4942
|
-
},
|
|
4943
|
-
'* html #bg': {
|
|
4944
|
-
'position': 'absolute'
|
|
4945
|
-
},
|
|
4946
|
-
'html, body': {
|
|
4947
|
-
'height': '100%'
|
|
4948
|
-
}
|
|
4949
|
-
});
|
|
4950
|
-
}
|
|
4951
|
-
if (this._browser_lte('ie', 7)) {
|
|
4952
|
-
_.extend(notif_styles, {
|
|
4953
|
-
'#mini #body': {
|
|
4954
|
-
'display': 'inline',
|
|
4955
|
-
'zoom': '1',
|
|
4956
|
-
'border': '1px solid ' + this.style_vals.bg_hover
|
|
4957
|
-
},
|
|
4958
|
-
'#mini #body-text': {
|
|
4959
|
-
'padding': '20px'
|
|
4960
|
-
},
|
|
4961
|
-
'#mini #mini-icon': {
|
|
4962
|
-
'display': 'none'
|
|
4963
|
-
}
|
|
4964
|
-
});
|
|
4965
|
-
}
|
|
4966
|
-
|
|
4967
|
-
// add vendor-prefixed style rules
|
|
4968
|
-
var VENDOR_STYLES = [
|
|
4969
|
-
'backface-visibility', 'border-radius', 'box-shadow', 'opacity',
|
|
4970
|
-
'perspective', 'transform', 'transform-style', 'transition'
|
|
4971
|
-
],
|
|
4972
|
-
VENDOR_PREFIXES = ['khtml', 'moz', 'ms', 'o', 'webkit'];
|
|
4973
|
-
for (var selector in notif_styles) {
|
|
4974
|
-
for (var si = 0; si < VENDOR_STYLES.length; si++) {
|
|
4975
|
-
var prop = VENDOR_STYLES[si];
|
|
4976
|
-
if (prop in notif_styles[selector]) {
|
|
4977
|
-
var val = notif_styles[selector][prop];
|
|
4978
|
-
for (var pi = 0; pi < VENDOR_PREFIXES.length; pi++) {
|
|
4979
|
-
notif_styles[selector]['-' + VENDOR_PREFIXES[pi] + '-' + prop] = val;
|
|
4980
|
-
}
|
|
4981
|
-
}
|
|
4982
|
-
}
|
|
4983
|
-
}
|
|
4984
|
-
|
|
4985
|
-
var inject_styles = function(styles, media_queries) {
|
|
4986
|
-
var create_style_text = function(style_defs) {
|
|
4987
|
-
var st = '';
|
|
4988
|
-
for (var selector in style_defs) {
|
|
4989
|
-
var mp_selector = selector
|
|
4990
|
-
.replace(/#/g, '#' + MixpanelNotification.MARKUP_PREFIX + '-')
|
|
4991
|
-
.replace(/\./g, '.' + MixpanelNotification.MARKUP_PREFIX + '-');
|
|
4992
|
-
st += '\n' + mp_selector + ' {';
|
|
4993
|
-
var props = style_defs[selector];
|
|
4994
|
-
for (var k in props) {
|
|
4995
|
-
st += k + ':' + props[k] + ';';
|
|
4996
|
-
}
|
|
4997
|
-
st += '}';
|
|
4998
|
-
}
|
|
4999
|
-
return st;
|
|
5000
|
-
};
|
|
5001
|
-
var create_media_query_text = function(mq_defs) {
|
|
5002
|
-
var mqt = '';
|
|
5003
|
-
for (var mq in mq_defs) {
|
|
5004
|
-
mqt += '\n' + mq + ' {' + create_style_text(mq_defs[mq]) + '\n}';
|
|
5005
|
-
}
|
|
5006
|
-
return mqt;
|
|
5007
|
-
};
|
|
5008
|
-
|
|
5009
|
-
var style_text = create_style_text(styles) + create_media_query_text(media_queries),
|
|
5010
|
-
head_el = document.head || document.getElementsByTagName('head')[0] || document.documentElement,
|
|
5011
|
-
style_el = document.createElement('style');
|
|
5012
|
-
head_el.appendChild(style_el);
|
|
5013
|
-
style_el.setAttribute('type', 'text/css');
|
|
5014
|
-
if (style_el.styleSheet) { // IE
|
|
5015
|
-
style_el.styleSheet.cssText = style_text;
|
|
5016
|
-
} else {
|
|
5017
|
-
style_el.textContent = style_text;
|
|
5018
|
-
}
|
|
5019
|
-
};
|
|
5020
|
-
inject_styles(notif_styles, notif_media_queries);
|
|
5021
|
-
};
|
|
5022
|
-
|
|
5023
|
-
MixpanelNotification.prototype._init_video = _.safewrap(function() {
|
|
5024
|
-
if (!this.video_url) {
|
|
5025
|
-
return;
|
|
5026
|
-
}
|
|
5027
|
-
var self = this;
|
|
5028
|
-
|
|
5029
|
-
// Youtube iframe API compatibility
|
|
5030
|
-
self.yt_custom = 'postMessage' in window;
|
|
5031
|
-
|
|
5032
|
-
self.dest_url = self.video_url;
|
|
5033
|
-
var youtube_match = self.video_url.match(
|
|
5034
|
-
// http://stackoverflow.com/questions/2936467/parse-youtube-video-id-using-preg-match
|
|
5035
|
-
/(?:youtube(?:-nocookie)?\.com\/(?:[^/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?/ ]{11})/i
|
|
5036
|
-
),
|
|
5037
|
-
vimeo_match = self.video_url.match(
|
|
5038
|
-
/vimeo\.com\/.*?(\d+)/i
|
|
5039
|
-
);
|
|
5040
|
-
if (youtube_match) {
|
|
5041
|
-
self.show_video = true;
|
|
5042
|
-
self.youtube_video = youtube_match[1];
|
|
5043
|
-
|
|
5044
|
-
if (self.yt_custom) {
|
|
5045
|
-
window['onYouTubeIframeAPIReady'] = function() {
|
|
5046
|
-
if (self._get_el('video-frame')) {
|
|
5047
|
-
self._yt_video_ready();
|
|
5048
|
-
}
|
|
5049
|
-
};
|
|
5050
|
-
|
|
5051
|
-
// load Youtube iframe API; see https://developers.google.com/youtube/iframe_api_reference
|
|
5052
|
-
var tag = document.createElement('script');
|
|
5053
|
-
tag.src = self.resource_protocol + 'www.youtube.com/iframe_api';
|
|
5054
|
-
var firstScriptTag = document.getElementsByTagName('script')[0];
|
|
5055
|
-
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
|
5056
|
-
}
|
|
5057
|
-
} else if (vimeo_match) {
|
|
5058
|
-
self.show_video = true;
|
|
5059
|
-
self.vimeo_video = vimeo_match[1];
|
|
5060
|
-
}
|
|
5061
|
-
|
|
5062
|
-
// IE <= 7, FF <= 3: fall through to video link rather than embedded player
|
|
5063
|
-
if (self._browser_lte('ie', 7) || self._browser_lte('firefox', 3)) {
|
|
5064
|
-
self.show_video = false;
|
|
5065
|
-
self.clickthrough = true;
|
|
5066
|
-
}
|
|
5067
|
-
});
|
|
5068
|
-
|
|
5069
|
-
MixpanelNotification.prototype._mark_as_shown = _.safewrap(function() {
|
|
5070
|
-
// click on background to dismiss
|
|
5071
|
-
var self = this;
|
|
5072
|
-
_.register_event(self._get_el('bg'), 'click', function() {
|
|
5073
|
-
self.dismiss();
|
|
5074
|
-
});
|
|
5075
|
-
|
|
5076
|
-
var get_style = function(el, style_name) {
|
|
5077
|
-
var styles = {};
|
|
5078
|
-
if (document.defaultView && document.defaultView.getComputedStyle) {
|
|
5079
|
-
styles = document.defaultView.getComputedStyle(el, null); // FF3 requires both args
|
|
5080
|
-
} else if (el.currentStyle) { // IE
|
|
5081
|
-
styles = el.currentStyle;
|
|
5082
|
-
}
|
|
5083
|
-
return styles[style_name];
|
|
5084
|
-
};
|
|
5085
|
-
|
|
5086
|
-
if (this.campaign_id) {
|
|
5087
|
-
var notif_el = this._get_el('overlay');
|
|
5088
|
-
if (notif_el && get_style(notif_el, 'visibility') !== 'hidden' && get_style(notif_el, 'display') !== 'none') {
|
|
5089
|
-
this._mark_delivery();
|
|
5090
|
-
}
|
|
5091
|
-
}
|
|
5092
|
-
});
|
|
5093
|
-
|
|
5094
|
-
MixpanelNotification.prototype._mark_delivery = _.safewrap(function(extra_props) {
|
|
5095
|
-
if (!this.marked_as_shown) {
|
|
5096
|
-
this.marked_as_shown = true;
|
|
5097
|
-
|
|
5098
|
-
if (this.campaign_id) {
|
|
5099
|
-
// mark notification shown (local cache)
|
|
5100
|
-
this._get_shown_campaigns()[this.campaign_id] = 1 * new Date();
|
|
5101
|
-
this.persistence.save();
|
|
5102
|
-
}
|
|
3854
|
+
MixpanelPersistence.prototype._add_to_people_queue = function(queue, data) {
|
|
3855
|
+
var q_key = this._get_queue_key(queue),
|
|
3856
|
+
q_data = data[queue],
|
|
3857
|
+
set_q = this._get_or_create_queue(SET_ACTION),
|
|
3858
|
+
set_once_q = this._get_or_create_queue(SET_ONCE_ACTION),
|
|
3859
|
+
unset_q = this._get_or_create_queue(UNSET_ACTION),
|
|
3860
|
+
add_q = this._get_or_create_queue(ADD_ACTION),
|
|
3861
|
+
union_q = this._get_or_create_queue(UNION_ACTION),
|
|
3862
|
+
remove_q = this._get_or_create_queue(REMOVE_ACTION, []),
|
|
3863
|
+
append_q = this._get_or_create_queue(APPEND_ACTION, []);
|
|
5103
3864
|
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
//
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
3865
|
+
if (q_key === SET_QUEUE_KEY) {
|
|
3866
|
+
// Update the set queue - we can override any existing values
|
|
3867
|
+
_.extend(set_q, q_data);
|
|
3868
|
+
// if there was a pending increment, override it
|
|
3869
|
+
// with the set.
|
|
3870
|
+
this._pop_from_people_queue(ADD_ACTION, q_data);
|
|
3871
|
+
// if there was a pending union, override it
|
|
3872
|
+
// with the set.
|
|
3873
|
+
this._pop_from_people_queue(UNION_ACTION, q_data);
|
|
3874
|
+
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3875
|
+
} else if (q_key === SET_ONCE_QUEUE_KEY) {
|
|
3876
|
+
// only queue the data if there is not already a set_once call for it.
|
|
3877
|
+
_.each(q_data, function(v, k) {
|
|
3878
|
+
if (!(k in set_once_q)) {
|
|
3879
|
+
set_once_q[k] = v;
|
|
5115
3880
|
}
|
|
5116
3881
|
});
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
MixpanelNotification.prototype._preload_images = function(all_loaded_cb) {
|
|
5121
|
-
var self = this;
|
|
5122
|
-
if (this.imgs_to_preload.length === 0) {
|
|
5123
|
-
all_loaded_cb();
|
|
5124
|
-
return;
|
|
5125
|
-
}
|
|
5126
|
-
|
|
5127
|
-
var preloaded_imgs = 0;
|
|
5128
|
-
var img_objs = [];
|
|
5129
|
-
var onload = function() {
|
|
5130
|
-
preloaded_imgs++;
|
|
5131
|
-
if (preloaded_imgs === self.imgs_to_preload.length && all_loaded_cb) {
|
|
5132
|
-
all_loaded_cb();
|
|
5133
|
-
all_loaded_cb = null;
|
|
5134
|
-
}
|
|
5135
|
-
};
|
|
5136
|
-
for (var i = 0; i < this.imgs_to_preload.length; i++) {
|
|
5137
|
-
var img = new Image();
|
|
5138
|
-
img.onload = onload;
|
|
5139
|
-
img.src = this.imgs_to_preload[i];
|
|
5140
|
-
if (img.complete) {
|
|
5141
|
-
onload();
|
|
5142
|
-
}
|
|
5143
|
-
img_objs.push(img);
|
|
5144
|
-
}
|
|
3882
|
+
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3883
|
+
} else if (q_key === UNSET_QUEUE_KEY) {
|
|
3884
|
+
_.each(q_data, function(prop) {
|
|
5145
3885
|
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
for (i = 0; i < img_objs.length; i++) {
|
|
5151
|
-
if (!img_objs[i].complete) {
|
|
5152
|
-
imgs_loaded = false;
|
|
3886
|
+
// undo previously-queued actions on this key
|
|
3887
|
+
_.each([set_q, set_once_q, add_q, union_q], function(enqueued_obj) {
|
|
3888
|
+
if (prop in enqueued_obj) {
|
|
3889
|
+
delete enqueued_obj[prop];
|
|
5153
3890
|
}
|
|
5154
|
-
}
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
}
|
|
5159
|
-
}, 500);
|
|
5160
|
-
}
|
|
5161
|
-
};
|
|
5162
|
-
|
|
5163
|
-
MixpanelNotification.prototype._remove_notification_el = _.safewrap(function() {
|
|
5164
|
-
window.clearInterval(this._video_progress_checker);
|
|
5165
|
-
this.notification_el.style.visibility = 'hidden';
|
|
5166
|
-
this.body_el.removeChild(this.notification_el);
|
|
5167
|
-
});
|
|
5168
|
-
|
|
5169
|
-
MixpanelNotification.prototype._set_client_config = function() {
|
|
5170
|
-
var get_browser_version = function(browser_ex) {
|
|
5171
|
-
var match = navigator.userAgent.match(browser_ex);
|
|
5172
|
-
return match && match[1];
|
|
5173
|
-
};
|
|
5174
|
-
this.browser_versions = {};
|
|
5175
|
-
this.browser_versions['chrome'] = get_browser_version(/Chrome\/(\d+)/);
|
|
5176
|
-
this.browser_versions['firefox'] = get_browser_version(/Firefox\/(\d+)/);
|
|
5177
|
-
this.browser_versions['ie'] = get_browser_version(/MSIE (\d+).+/);
|
|
5178
|
-
if (!this.browser_versions['ie'] && !(window.ActiveXObject) && 'ActiveXObject' in window) {
|
|
5179
|
-
this.browser_versions['ie'] = 11;
|
|
5180
|
-
}
|
|
5181
|
-
|
|
5182
|
-
this.body_el = document.body || document.getElementsByTagName('body')[0];
|
|
5183
|
-
if (this.body_el) {
|
|
5184
|
-
this.doc_width = Math.max(
|
|
5185
|
-
this.body_el.scrollWidth, document.documentElement.scrollWidth,
|
|
5186
|
-
this.body_el.offsetWidth, document.documentElement.offsetWidth,
|
|
5187
|
-
this.body_el.clientWidth, document.documentElement.clientWidth
|
|
5188
|
-
);
|
|
5189
|
-
this.doc_height = Math.max(
|
|
5190
|
-
this.body_el.scrollHeight, document.documentElement.scrollHeight,
|
|
5191
|
-
this.body_el.offsetHeight, document.documentElement.offsetHeight,
|
|
5192
|
-
this.body_el.clientHeight, document.documentElement.clientHeight
|
|
5193
|
-
);
|
|
5194
|
-
}
|
|
5195
|
-
|
|
5196
|
-
// detect CSS compatibility
|
|
5197
|
-
var ie_ver = this.browser_versions['ie'];
|
|
5198
|
-
var sample_styles = document.createElement('div').style,
|
|
5199
|
-
is_css_compatible = function(rule) {
|
|
5200
|
-
if (rule in sample_styles) {
|
|
5201
|
-
return true;
|
|
5202
|
-
}
|
|
5203
|
-
if (!ie_ver) {
|
|
5204
|
-
rule = rule[0].toUpperCase() + rule.slice(1);
|
|
5205
|
-
var props = ['O' + rule, 'Webkit' + rule, 'Moz' + rule];
|
|
5206
|
-
for (var i = 0; i < props.length; i++) {
|
|
5207
|
-
if (props[i] in sample_styles) {
|
|
5208
|
-
return true;
|
|
5209
|
-
}
|
|
3891
|
+
});
|
|
3892
|
+
_.each(append_q, function(append_obj) {
|
|
3893
|
+
if (prop in append_obj) {
|
|
3894
|
+
delete append_obj[prop];
|
|
5210
3895
|
}
|
|
5211
|
-
}
|
|
5212
|
-
return false;
|
|
5213
|
-
};
|
|
5214
|
-
this.use_transitions = this.body_el &&
|
|
5215
|
-
is_css_compatible('transition') &&
|
|
5216
|
-
is_css_compatible('transform');
|
|
5217
|
-
this.flip_animate = (this.browser_versions['chrome'] >= 33 || this.browser_versions['firefox'] >= 15) &&
|
|
5218
|
-
this.body_el &&
|
|
5219
|
-
is_css_compatible('backfaceVisibility') &&
|
|
5220
|
-
is_css_compatible('perspective') &&
|
|
5221
|
-
is_css_compatible('transform');
|
|
5222
|
-
};
|
|
5223
|
-
|
|
5224
|
-
MixpanelNotification.prototype._switch_to_video = _.safewrap(function() {
|
|
5225
|
-
var self = this,
|
|
5226
|
-
anims = [
|
|
5227
|
-
{
|
|
5228
|
-
el: self._get_notification_display_el(),
|
|
5229
|
-
attr: 'opacity',
|
|
5230
|
-
start: 1.0,
|
|
5231
|
-
goal: 0.0
|
|
5232
|
-
},
|
|
5233
|
-
{
|
|
5234
|
-
el: self._get_notification_display_el(),
|
|
5235
|
-
attr: 'top',
|
|
5236
|
-
start: MixpanelNotification.NOTIF_TOP,
|
|
5237
|
-
goal: -500
|
|
5238
|
-
},
|
|
5239
|
-
{
|
|
5240
|
-
el: self._get_el('video-noflip'),
|
|
5241
|
-
attr: 'opacity',
|
|
5242
|
-
start: 0.0,
|
|
5243
|
-
goal: 1.0
|
|
5244
|
-
},
|
|
5245
|
-
{
|
|
5246
|
-
el: self._get_el('video-noflip'),
|
|
5247
|
-
attr: 'top',
|
|
5248
|
-
start: -self.video_height * 2,
|
|
5249
|
-
goal: 0
|
|
5250
|
-
}
|
|
5251
|
-
];
|
|
5252
|
-
|
|
5253
|
-
if (self.mini) {
|
|
5254
|
-
var bg = self._get_el('bg'),
|
|
5255
|
-
overlay = self._get_el('overlay');
|
|
5256
|
-
bg.style.width = '100%';
|
|
5257
|
-
bg.style.height = '100%';
|
|
5258
|
-
overlay.style.width = '100%';
|
|
5259
|
-
|
|
5260
|
-
self._add_class(self._get_notification_display_el(), 'exiting');
|
|
5261
|
-
self._add_class(bg, 'visible');
|
|
5262
|
-
|
|
5263
|
-
anims.push({
|
|
5264
|
-
el: self._get_el('bg'),
|
|
5265
|
-
attr: 'opacity',
|
|
5266
|
-
start: 0.0,
|
|
5267
|
-
goal: MixpanelNotification.BG_OPACITY
|
|
5268
|
-
});
|
|
5269
|
-
}
|
|
5270
|
-
|
|
5271
|
-
var video_el = self._get_el('video-holder');
|
|
5272
|
-
video_el.innerHTML = self.video_iframe;
|
|
5273
|
-
|
|
5274
|
-
var video_ready = function() {
|
|
5275
|
-
if (window['YT'] && window['YT']['loaded']) {
|
|
5276
|
-
self._yt_video_ready();
|
|
5277
|
-
}
|
|
5278
|
-
self.showing_video = true;
|
|
5279
|
-
self._get_notification_display_el().style.visibility = 'hidden';
|
|
5280
|
-
};
|
|
5281
|
-
if (self.flip_animate) {
|
|
5282
|
-
self._add_class('flipper', 'flipped');
|
|
5283
|
-
setTimeout(video_ready, MixpanelNotification.ANIM_TIME);
|
|
5284
|
-
} else {
|
|
5285
|
-
self._animate_els(anims, MixpanelNotification.ANIM_TIME, video_ready);
|
|
5286
|
-
}
|
|
5287
|
-
});
|
|
5288
|
-
|
|
5289
|
-
MixpanelNotification.prototype._track_event = function(event_name, properties, cb) {
|
|
5290
|
-
if (this.campaign_id) {
|
|
5291
|
-
properties = properties || {};
|
|
5292
|
-
properties = _.extend(properties, {
|
|
5293
|
-
'campaign_id': this.campaign_id,
|
|
5294
|
-
'message_id': this.message_id,
|
|
5295
|
-
'message_type': 'web_inapp',
|
|
5296
|
-
'message_subtype': this.notif_type
|
|
5297
|
-
});
|
|
5298
|
-
this.mixpanel['track'](event_name, properties, cb);
|
|
5299
|
-
} else if (cb) {
|
|
5300
|
-
cb.call();
|
|
5301
|
-
}
|
|
5302
|
-
};
|
|
5303
|
-
|
|
5304
|
-
MixpanelNotification.prototype._yt_video_ready = _.safewrap(function() {
|
|
5305
|
-
var self = this;
|
|
5306
|
-
if (self.video_inited) {
|
|
5307
|
-
return;
|
|
5308
|
-
}
|
|
5309
|
-
self.video_inited = true;
|
|
5310
|
-
|
|
5311
|
-
var progress_bar = self._get_el('video-elapsed'),
|
|
5312
|
-
progress_time = self._get_el('video-time'),
|
|
5313
|
-
progress_el = self._get_el('video-progress');
|
|
5314
|
-
|
|
5315
|
-
new window['YT']['Player'](MixpanelNotification.MARKUP_PREFIX + '-video-frame', {
|
|
5316
|
-
'events': {
|
|
5317
|
-
'onReady': function(event) {
|
|
5318
|
-
var ytplayer = event['target'],
|
|
5319
|
-
video_duration = ytplayer['getDuration'](),
|
|
5320
|
-
pad = function(i) {
|
|
5321
|
-
return ('00' + i).slice(-2);
|
|
5322
|
-
},
|
|
5323
|
-
update_video_time = function(current_time) {
|
|
5324
|
-
var secs = Math.round(video_duration - current_time),
|
|
5325
|
-
mins = Math.floor(secs / 60),
|
|
5326
|
-
hours = Math.floor(mins / 60);
|
|
5327
|
-
secs -= mins * 60;
|
|
5328
|
-
mins -= hours * 60;
|
|
5329
|
-
progress_time.innerHTML = '-' + (hours ? hours + ':' : '') + pad(mins) + ':' + pad(secs);
|
|
5330
|
-
};
|
|
5331
|
-
update_video_time(0);
|
|
5332
|
-
self._video_progress_checker = window.setInterval(function() {
|
|
5333
|
-
var current_time = ytplayer['getCurrentTime']();
|
|
5334
|
-
progress_bar.style.width = (current_time / video_duration * 100) + '%';
|
|
5335
|
-
update_video_time(current_time);
|
|
5336
|
-
}, 250);
|
|
5337
|
-
_.register_event(progress_el, 'click', function(e) {
|
|
5338
|
-
var clickx = Math.max(0, e.pageX - progress_el.getBoundingClientRect().left);
|
|
5339
|
-
ytplayer['seekTo'](video_duration * clickx / progress_el.clientWidth, true);
|
|
5340
|
-
});
|
|
5341
|
-
}
|
|
5342
|
-
}
|
|
5343
|
-
});
|
|
5344
|
-
});
|
|
5345
|
-
|
|
5346
|
-
/**
|
|
5347
|
-
* Mixpanel People Object
|
|
5348
|
-
* @constructor
|
|
5349
|
-
*/
|
|
5350
|
-
var MixpanelPeople = function() {};
|
|
5351
|
-
|
|
5352
|
-
_.extend(MixpanelPeople.prototype, apiActions);
|
|
5353
|
-
|
|
5354
|
-
MixpanelPeople.prototype._init = function(mixpanel_instance) {
|
|
5355
|
-
this._mixpanel = mixpanel_instance;
|
|
5356
|
-
};
|
|
5357
|
-
|
|
5358
|
-
/*
|
|
5359
|
-
* Set properties on a user record.
|
|
5360
|
-
*
|
|
5361
|
-
* ### Usage:
|
|
5362
|
-
*
|
|
5363
|
-
* mixpanel.people.set('gender', 'm');
|
|
5364
|
-
*
|
|
5365
|
-
* // or set multiple properties at once
|
|
5366
|
-
* mixpanel.people.set({
|
|
5367
|
-
* 'Company': 'Acme',
|
|
5368
|
-
* 'Plan': 'Premium',
|
|
5369
|
-
* 'Upgrade date': new Date()
|
|
5370
|
-
* });
|
|
5371
|
-
* // properties can be strings, integers, dates, or lists
|
|
5372
|
-
*
|
|
5373
|
-
* @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
5374
|
-
* @param {*} [to] A value to set on the given property name
|
|
5375
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
5376
|
-
*/
|
|
5377
|
-
MixpanelPeople.prototype.set = addOptOutCheckMixpanelPeople(function(prop, to, callback) {
|
|
5378
|
-
var data = this.set_action(prop, to);
|
|
5379
|
-
if (_.isObject(prop)) {
|
|
5380
|
-
callback = to;
|
|
5381
|
-
}
|
|
5382
|
-
// make sure that the referrer info has been updated and saved
|
|
5383
|
-
if (this._get_config('save_referrer')) {
|
|
5384
|
-
this._mixpanel['persistence'].update_referrer_info(document.referrer);
|
|
5385
|
-
}
|
|
5386
|
-
|
|
5387
|
-
// update $set object with default people properties
|
|
5388
|
-
data[SET_ACTION] = _.extend(
|
|
5389
|
-
{},
|
|
5390
|
-
_.info.people_properties(),
|
|
5391
|
-
this._mixpanel['persistence'].get_referrer_info(),
|
|
5392
|
-
data[SET_ACTION]
|
|
5393
|
-
);
|
|
5394
|
-
return this._send_request(data, callback);
|
|
5395
|
-
});
|
|
5396
|
-
|
|
5397
|
-
/*
|
|
5398
|
-
* Set properties on a user record, only if they do not yet exist.
|
|
5399
|
-
* This will not overwrite previous people property values, unlike
|
|
5400
|
-
* people.set().
|
|
5401
|
-
*
|
|
5402
|
-
* ### Usage:
|
|
5403
|
-
*
|
|
5404
|
-
* mixpanel.people.set_once('First Login Date', new Date());
|
|
5405
|
-
*
|
|
5406
|
-
* // or set multiple properties at once
|
|
5407
|
-
* mixpanel.people.set_once({
|
|
5408
|
-
* 'First Login Date': new Date(),
|
|
5409
|
-
* 'Starting Plan': 'Premium'
|
|
5410
|
-
* });
|
|
5411
|
-
*
|
|
5412
|
-
* // properties can be strings, integers or dates
|
|
5413
|
-
*
|
|
5414
|
-
* @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
5415
|
-
* @param {*} [to] A value to set on the given property name
|
|
5416
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
5417
|
-
*/
|
|
5418
|
-
MixpanelPeople.prototype.set_once = addOptOutCheckMixpanelPeople(function(prop, to, callback) {
|
|
5419
|
-
var data = this.set_once_action(prop, to);
|
|
5420
|
-
if (_.isObject(prop)) {
|
|
5421
|
-
callback = to;
|
|
5422
|
-
}
|
|
5423
|
-
return this._send_request(data, callback);
|
|
5424
|
-
});
|
|
5425
|
-
|
|
5426
|
-
/*
|
|
5427
|
-
* Unset properties on a user record (permanently removes the properties and their values from a profile).
|
|
5428
|
-
*
|
|
5429
|
-
* ### Usage:
|
|
5430
|
-
*
|
|
5431
|
-
* mixpanel.people.unset('gender');
|
|
5432
|
-
*
|
|
5433
|
-
* // or unset multiple properties at once
|
|
5434
|
-
* mixpanel.people.unset(['gender', 'Company']);
|
|
5435
|
-
*
|
|
5436
|
-
* @param {Array|String} prop If a string, this is the name of the property. If an array, this is a list of property names.
|
|
5437
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
5438
|
-
*/
|
|
5439
|
-
MixpanelPeople.prototype.unset = addOptOutCheckMixpanelPeople(function(prop, callback) {
|
|
5440
|
-
var data = this.unset_action(prop);
|
|
5441
|
-
return this._send_request(data, callback);
|
|
5442
|
-
});
|
|
5443
|
-
|
|
5444
|
-
/*
|
|
5445
|
-
* Increment/decrement numeric people analytics properties.
|
|
5446
|
-
*
|
|
5447
|
-
* ### Usage:
|
|
5448
|
-
*
|
|
5449
|
-
* mixpanel.people.increment('page_views', 1);
|
|
5450
|
-
*
|
|
5451
|
-
* // or, for convenience, if you're just incrementing a counter by
|
|
5452
|
-
* // 1, you can simply do
|
|
5453
|
-
* mixpanel.people.increment('page_views');
|
|
5454
|
-
*
|
|
5455
|
-
* // to decrement a counter, pass a negative number
|
|
5456
|
-
* mixpanel.people.increment('credits_left', -1);
|
|
5457
|
-
*
|
|
5458
|
-
* // like mixpanel.people.set(), you can increment multiple
|
|
5459
|
-
* // properties at once:
|
|
5460
|
-
* mixpanel.people.increment({
|
|
5461
|
-
* counter1: 1,
|
|
5462
|
-
* counter2: 6
|
|
5463
|
-
* });
|
|
5464
|
-
*
|
|
5465
|
-
* @param {Object|String} prop If a string, this is the name of the property. If an object, this is an associative array of names and numeric values.
|
|
5466
|
-
* @param {Number} [by] An amount to increment the given property
|
|
5467
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
5468
|
-
*/
|
|
5469
|
-
MixpanelPeople.prototype.increment = addOptOutCheckMixpanelPeople(function(prop, by, callback) {
|
|
5470
|
-
var data = {};
|
|
5471
|
-
var $add = {};
|
|
5472
|
-
if (_.isObject(prop)) {
|
|
5473
|
-
_.each(prop, function(v, k) {
|
|
5474
|
-
if (!this._is_reserved_property(k)) {
|
|
5475
|
-
if (isNaN(parseFloat(v))) {
|
|
5476
|
-
console.error('Invalid increment value passed to mixpanel.people.increment - must be a number');
|
|
5477
|
-
return;
|
|
5478
|
-
} else {
|
|
5479
|
-
$add[k] = v;
|
|
5480
|
-
}
|
|
5481
|
-
}
|
|
5482
|
-
}, this);
|
|
5483
|
-
callback = by;
|
|
5484
|
-
} else {
|
|
5485
|
-
// convenience: mixpanel.people.increment('property'); will
|
|
5486
|
-
// increment 'property' by 1
|
|
5487
|
-
if (_.isUndefined(by)) {
|
|
5488
|
-
by = 1;
|
|
5489
|
-
}
|
|
5490
|
-
$add[prop] = by;
|
|
5491
|
-
}
|
|
5492
|
-
data[ADD_ACTION] = $add;
|
|
5493
|
-
|
|
5494
|
-
return this._send_request(data, callback);
|
|
5495
|
-
});
|
|
5496
|
-
|
|
5497
|
-
/*
|
|
5498
|
-
* Append a value to a list-valued people analytics property.
|
|
5499
|
-
*
|
|
5500
|
-
* ### Usage:
|
|
5501
|
-
*
|
|
5502
|
-
* // append a value to a list, creating it if needed
|
|
5503
|
-
* mixpanel.people.append('pages_visited', 'homepage');
|
|
5504
|
-
*
|
|
5505
|
-
* // like mixpanel.people.set(), you can append multiple
|
|
5506
|
-
* // properties at once:
|
|
5507
|
-
* mixpanel.people.append({
|
|
5508
|
-
* list1: 'bob',
|
|
5509
|
-
* list2: 123
|
|
5510
|
-
* });
|
|
5511
|
-
*
|
|
5512
|
-
* @param {Object|String} list_name If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
5513
|
-
* @param {*} [value] value An item to append to the list
|
|
5514
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
5515
|
-
*/
|
|
5516
|
-
MixpanelPeople.prototype.append = addOptOutCheckMixpanelPeople(function(list_name, value, callback) {
|
|
5517
|
-
if (_.isObject(list_name)) {
|
|
5518
|
-
callback = value;
|
|
5519
|
-
}
|
|
5520
|
-
var data = this.append_action(list_name, value);
|
|
5521
|
-
return this._send_request(data, callback);
|
|
5522
|
-
});
|
|
5523
|
-
|
|
5524
|
-
/*
|
|
5525
|
-
* Remove a value from a list-valued people analytics property.
|
|
5526
|
-
*
|
|
5527
|
-
* ### Usage:
|
|
5528
|
-
*
|
|
5529
|
-
* mixpanel.people.remove('School', 'UCB');
|
|
5530
|
-
*
|
|
5531
|
-
* @param {Object|String} list_name If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
5532
|
-
* @param {*} [value] value Item to remove from the list
|
|
5533
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
5534
|
-
*/
|
|
5535
|
-
MixpanelPeople.prototype.remove = addOptOutCheckMixpanelPeople(function(list_name, value, callback) {
|
|
5536
|
-
if (_.isObject(list_name)) {
|
|
5537
|
-
callback = value;
|
|
5538
|
-
}
|
|
5539
|
-
var data = this.remove_action(list_name, value);
|
|
5540
|
-
return this._send_request(data, callback);
|
|
5541
|
-
});
|
|
5542
|
-
|
|
5543
|
-
/*
|
|
5544
|
-
* Merge a given list with a list-valued people analytics property,
|
|
5545
|
-
* excluding duplicate values.
|
|
5546
|
-
*
|
|
5547
|
-
* ### Usage:
|
|
5548
|
-
*
|
|
5549
|
-
* // merge a value to a list, creating it if needed
|
|
5550
|
-
* mixpanel.people.union('pages_visited', 'homepage');
|
|
5551
|
-
*
|
|
5552
|
-
* // like mixpanel.people.set(), you can append multiple
|
|
5553
|
-
* // properties at once:
|
|
5554
|
-
* mixpanel.people.union({
|
|
5555
|
-
* list1: 'bob',
|
|
5556
|
-
* list2: 123
|
|
5557
|
-
* });
|
|
5558
|
-
*
|
|
5559
|
-
* // like mixpanel.people.append(), you can append multiple
|
|
5560
|
-
* // values to the same list:
|
|
5561
|
-
* mixpanel.people.union({
|
|
5562
|
-
* list1: ['bob', 'billy']
|
|
5563
|
-
* });
|
|
5564
|
-
*
|
|
5565
|
-
* @param {Object|String} list_name If a string, this is the name of the property. If an object, this is an associative array of names and values.
|
|
5566
|
-
* @param {*} [value] Value / values to merge with the given property
|
|
5567
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
5568
|
-
*/
|
|
5569
|
-
MixpanelPeople.prototype.union = addOptOutCheckMixpanelPeople(function(list_name, values, callback) {
|
|
5570
|
-
if (_.isObject(list_name)) {
|
|
5571
|
-
callback = values;
|
|
5572
|
-
}
|
|
5573
|
-
var data = this.union_action(list_name, values);
|
|
5574
|
-
return this._send_request(data, callback);
|
|
5575
|
-
});
|
|
5576
|
-
|
|
5577
|
-
/*
|
|
5578
|
-
* Record that you have charged the current user a certain amount
|
|
5579
|
-
* of money. Charges recorded with track_charge() will appear in the
|
|
5580
|
-
* Mixpanel revenue report.
|
|
5581
|
-
*
|
|
5582
|
-
* ### Usage:
|
|
5583
|
-
*
|
|
5584
|
-
* // charge a user $50
|
|
5585
|
-
* mixpanel.people.track_charge(50);
|
|
5586
|
-
*
|
|
5587
|
-
* // charge a user $30.50 on the 2nd of january
|
|
5588
|
-
* mixpanel.people.track_charge(30.50, {
|
|
5589
|
-
* '$time': new Date('jan 1 2012')
|
|
5590
|
-
* });
|
|
5591
|
-
*
|
|
5592
|
-
* @param {Number} amount The amount of money charged to the current user
|
|
5593
|
-
* @param {Object} [properties] An associative array of properties associated with the charge
|
|
5594
|
-
* @param {Function} [callback] If provided, the callback will be called when the server responds
|
|
5595
|
-
*/
|
|
5596
|
-
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function(amount, properties, callback) {
|
|
5597
|
-
if (!_.isNumber(amount)) {
|
|
5598
|
-
amount = parseFloat(amount);
|
|
5599
|
-
if (isNaN(amount)) {
|
|
5600
|
-
console.error('Invalid value passed to mixpanel.people.track_charge - must be a number');
|
|
5601
|
-
return;
|
|
5602
|
-
}
|
|
5603
|
-
}
|
|
5604
|
-
|
|
5605
|
-
return this.append('$transactions', _.extend({
|
|
5606
|
-
'$amount': amount
|
|
5607
|
-
}, properties), callback);
|
|
5608
|
-
});
|
|
5609
|
-
|
|
5610
|
-
/*
|
|
5611
|
-
* Permanently clear all revenue report transactions from the
|
|
5612
|
-
* current user's people analytics profile.
|
|
5613
|
-
*
|
|
5614
|
-
* ### Usage:
|
|
5615
|
-
*
|
|
5616
|
-
* mixpanel.people.clear_charges();
|
|
5617
|
-
*
|
|
5618
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
5619
|
-
*/
|
|
5620
|
-
MixpanelPeople.prototype.clear_charges = function(callback) {
|
|
5621
|
-
return this.set('$transactions', [], callback);
|
|
5622
|
-
};
|
|
5623
|
-
|
|
5624
|
-
/*
|
|
5625
|
-
* Permanently deletes the current people analytics profile from
|
|
5626
|
-
* Mixpanel (using the current distinct_id).
|
|
5627
|
-
*
|
|
5628
|
-
* ### Usage:
|
|
5629
|
-
*
|
|
5630
|
-
* // remove the all data you have stored about the current user
|
|
5631
|
-
* mixpanel.people.delete_user();
|
|
5632
|
-
*
|
|
5633
|
-
*/
|
|
5634
|
-
MixpanelPeople.prototype.delete_user = function() {
|
|
5635
|
-
if (!this._identify_called()) {
|
|
5636
|
-
console.error('mixpanel.people.delete_user() requires you to call identify() first');
|
|
5637
|
-
return;
|
|
5638
|
-
}
|
|
5639
|
-
var data = {'$delete': this._mixpanel.get_distinct_id()};
|
|
5640
|
-
return this._send_request(data);
|
|
5641
|
-
};
|
|
5642
|
-
|
|
5643
|
-
MixpanelPeople.prototype.toString = function() {
|
|
5644
|
-
return this._mixpanel.toString() + '.people';
|
|
5645
|
-
};
|
|
5646
|
-
|
|
5647
|
-
MixpanelPeople.prototype._send_request = function(data, callback) {
|
|
5648
|
-
data['$token'] = this._get_config('token');
|
|
5649
|
-
data['$distinct_id'] = this._mixpanel.get_distinct_id();
|
|
5650
|
-
var device_id = this._mixpanel.get_property('$device_id');
|
|
5651
|
-
var user_id = this._mixpanel.get_property('$user_id');
|
|
5652
|
-
var had_persisted_distinct_id = this._mixpanel.get_property('$had_persisted_distinct_id');
|
|
5653
|
-
if (device_id) {
|
|
5654
|
-
data['$device_id'] = device_id;
|
|
5655
|
-
}
|
|
5656
|
-
if (user_id) {
|
|
5657
|
-
data['$user_id'] = user_id;
|
|
5658
|
-
}
|
|
5659
|
-
if (had_persisted_distinct_id) {
|
|
5660
|
-
data['$had_persisted_distinct_id'] = had_persisted_distinct_id;
|
|
5661
|
-
}
|
|
3896
|
+
});
|
|
5662
3897
|
|
|
5663
|
-
|
|
3898
|
+
unset_q[prop] = true;
|
|
5664
3899
|
|
|
5665
|
-
|
|
5666
|
-
|
|
5667
|
-
|
|
5668
|
-
|
|
5669
|
-
|
|
3900
|
+
});
|
|
3901
|
+
} else if (q_key === ADD_QUEUE_KEY) {
|
|
3902
|
+
_.each(q_data, function(v, k) {
|
|
3903
|
+
// If it exists in the set queue, increment
|
|
3904
|
+
// the value
|
|
3905
|
+
if (k in set_q) {
|
|
3906
|
+
set_q[k] += v;
|
|
5670
3907
|
} else {
|
|
5671
|
-
|
|
3908
|
+
// If it doesn't exist, update the add
|
|
3909
|
+
// queue
|
|
3910
|
+
if (!(k in add_q)) {
|
|
3911
|
+
add_q[k] = 0;
|
|
3912
|
+
}
|
|
3913
|
+
add_q[k] += v;
|
|
5672
3914
|
}
|
|
5673
|
-
}
|
|
5674
|
-
|
|
3915
|
+
}, this);
|
|
3916
|
+
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3917
|
+
} else if (q_key === UNION_QUEUE_KEY) {
|
|
3918
|
+
_.each(q_data, function(v, k) {
|
|
3919
|
+
if (_.isArray(v)) {
|
|
3920
|
+
if (!(k in union_q)) {
|
|
3921
|
+
union_q[k] = [];
|
|
3922
|
+
}
|
|
3923
|
+
// We may send duplicates, the server will dedup them.
|
|
3924
|
+
union_q[k] = union_q[k].concat(v);
|
|
3925
|
+
}
|
|
3926
|
+
});
|
|
3927
|
+
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
3928
|
+
} else if (q_key === REMOVE_QUEUE_KEY) {
|
|
3929
|
+
remove_q.push(q_data);
|
|
3930
|
+
this._pop_from_people_queue(APPEND_ACTION, q_data);
|
|
3931
|
+
} else if (q_key === APPEND_QUEUE_KEY) {
|
|
3932
|
+
append_q.push(q_data);
|
|
3933
|
+
this._pop_from_people_queue(UNSET_ACTION, q_data);
|
|
5675
3934
|
}
|
|
5676
3935
|
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
data: date_encoded_data,
|
|
5680
|
-
endpoint: this._get_config('api_host') + '/engage/',
|
|
5681
|
-
batcher: this._mixpanel.request_batchers.people
|
|
5682
|
-
}, callback);
|
|
5683
|
-
};
|
|
3936
|
+
console.log('MIXPANEL PEOPLE REQUEST (QUEUED, PENDING IDENTIFY):');
|
|
3937
|
+
console.log(data);
|
|
5684
3938
|
|
|
5685
|
-
|
|
5686
|
-
return this._mixpanel.get_config(conf_var);
|
|
3939
|
+
this.save();
|
|
5687
3940
|
};
|
|
5688
3941
|
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
3942
|
+
MixpanelPersistence.prototype._pop_from_people_queue = function(queue, data) {
|
|
3943
|
+
var q = this._get_queue(queue);
|
|
3944
|
+
if (!_.isUndefined(q)) {
|
|
3945
|
+
_.each(data, function(v, k) {
|
|
3946
|
+
if (queue === APPEND_ACTION || queue === REMOVE_ACTION) {
|
|
3947
|
+
// list actions: only remove if both k+v match
|
|
3948
|
+
// e.g. remove should not override append in a case like
|
|
3949
|
+
// append({foo: 'bar'}); remove({foo: 'qux'})
|
|
3950
|
+
_.each(q, function(queued_action) {
|
|
3951
|
+
if (queued_action[k] === v) {
|
|
3952
|
+
delete queued_action[k];
|
|
3953
|
+
}
|
|
3954
|
+
});
|
|
3955
|
+
} else {
|
|
3956
|
+
delete q[k];
|
|
3957
|
+
}
|
|
3958
|
+
}, this);
|
|
5692
3959
|
|
|
5693
|
-
|
|
5694
|
-
MixpanelPeople.prototype._enqueue = function(data) {
|
|
5695
|
-
if (SET_ACTION in data) {
|
|
5696
|
-
this._mixpanel['persistence']._add_to_people_queue(SET_ACTION, data);
|
|
5697
|
-
} else if (SET_ONCE_ACTION in data) {
|
|
5698
|
-
this._mixpanel['persistence']._add_to_people_queue(SET_ONCE_ACTION, data);
|
|
5699
|
-
} else if (UNSET_ACTION in data) {
|
|
5700
|
-
this._mixpanel['persistence']._add_to_people_queue(UNSET_ACTION, data);
|
|
5701
|
-
} else if (ADD_ACTION in data) {
|
|
5702
|
-
this._mixpanel['persistence']._add_to_people_queue(ADD_ACTION, data);
|
|
5703
|
-
} else if (APPEND_ACTION in data) {
|
|
5704
|
-
this._mixpanel['persistence']._add_to_people_queue(APPEND_ACTION, data);
|
|
5705
|
-
} else if (REMOVE_ACTION in data) {
|
|
5706
|
-
this._mixpanel['persistence']._add_to_people_queue(REMOVE_ACTION, data);
|
|
5707
|
-
} else if (UNION_ACTION in data) {
|
|
5708
|
-
this._mixpanel['persistence']._add_to_people_queue(UNION_ACTION, data);
|
|
5709
|
-
} else {
|
|
5710
|
-
console.error('Invalid call to _enqueue():', data);
|
|
3960
|
+
this.save();
|
|
5711
3961
|
}
|
|
5712
3962
|
};
|
|
5713
3963
|
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
}
|
|
5732
|
-
});
|
|
3964
|
+
MixpanelPersistence.prototype._get_queue_key = function(queue) {
|
|
3965
|
+
if (queue === SET_ACTION) {
|
|
3966
|
+
return SET_QUEUE_KEY;
|
|
3967
|
+
} else if (queue === SET_ONCE_ACTION) {
|
|
3968
|
+
return SET_ONCE_QUEUE_KEY;
|
|
3969
|
+
} else if (queue === UNSET_ACTION) {
|
|
3970
|
+
return UNSET_QUEUE_KEY;
|
|
3971
|
+
} else if (queue === ADD_ACTION) {
|
|
3972
|
+
return ADD_QUEUE_KEY;
|
|
3973
|
+
} else if (queue === APPEND_ACTION) {
|
|
3974
|
+
return APPEND_QUEUE_KEY;
|
|
3975
|
+
} else if (queue === REMOVE_ACTION) {
|
|
3976
|
+
return REMOVE_QUEUE_KEY;
|
|
3977
|
+
} else if (queue === UNION_ACTION) {
|
|
3978
|
+
return UNION_QUEUE_KEY;
|
|
3979
|
+
} else {
|
|
3980
|
+
console.error('Invalid queue:', queue);
|
|
5733
3981
|
}
|
|
5734
3982
|
};
|
|
5735
3983
|
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
var $append_queue = this._mixpanel['persistence']._get_queue(APPEND_ACTION);
|
|
5743
|
-
var $remove_queue = this._mixpanel['persistence']._get_queue(REMOVE_ACTION);
|
|
5744
|
-
|
|
5745
|
-
this._flush_one_queue(SET_ACTION, this.set, _set_callback);
|
|
5746
|
-
this._flush_one_queue(SET_ONCE_ACTION, this.set_once, _set_once_callback);
|
|
5747
|
-
this._flush_one_queue(UNSET_ACTION, this.unset, _unset_callback, function(queue) { return _.keys(queue); });
|
|
5748
|
-
this._flush_one_queue(ADD_ACTION, this.increment, _add_callback);
|
|
5749
|
-
this._flush_one_queue(UNION_ACTION, this.union, _union_callback);
|
|
5750
|
-
|
|
5751
|
-
// we have to fire off each $append individually since there is
|
|
5752
|
-
// no concat method server side
|
|
5753
|
-
if (!_.isUndefined($append_queue) && _.isArray($append_queue) && $append_queue.length) {
|
|
5754
|
-
var $append_item;
|
|
5755
|
-
var append_callback = function(response, data) {
|
|
5756
|
-
if (response === 0) {
|
|
5757
|
-
_this._mixpanel['persistence']._add_to_people_queue(APPEND_ACTION, $append_item);
|
|
5758
|
-
}
|
|
5759
|
-
if (!_.isUndefined(_append_callback)) {
|
|
5760
|
-
_append_callback(response, data);
|
|
5761
|
-
}
|
|
5762
|
-
};
|
|
5763
|
-
for (var i = $append_queue.length - 1; i >= 0; i--) {
|
|
5764
|
-
$append_item = $append_queue.pop();
|
|
5765
|
-
if (!_.isEmptyObject($append_item)) {
|
|
5766
|
-
_this.append($append_item, append_callback);
|
|
5767
|
-
}
|
|
5768
|
-
}
|
|
5769
|
-
// Save the shortened append queue
|
|
5770
|
-
_this._mixpanel['persistence'].save();
|
|
5771
|
-
}
|
|
3984
|
+
MixpanelPersistence.prototype._get_queue = function(queue) {
|
|
3985
|
+
return this['props'][this._get_queue_key(queue)];
|
|
3986
|
+
};
|
|
3987
|
+
MixpanelPersistence.prototype._get_or_create_queue = function(queue, default_val) {
|
|
3988
|
+
var key = this._get_queue_key(queue);
|
|
3989
|
+
default_val = _.isUndefined(default_val) ? {} : default_val;
|
|
5772
3990
|
|
|
5773
|
-
|
|
5774
|
-
if (!_.isUndefined($remove_queue) && _.isArray($remove_queue) && $remove_queue.length) {
|
|
5775
|
-
var $remove_item;
|
|
5776
|
-
var remove_callback = function(response, data) {
|
|
5777
|
-
if (response === 0) {
|
|
5778
|
-
_this._mixpanel['persistence']._add_to_people_queue(REMOVE_ACTION, $remove_item);
|
|
5779
|
-
}
|
|
5780
|
-
if (!_.isUndefined(_remove_callback)) {
|
|
5781
|
-
_remove_callback(response, data);
|
|
5782
|
-
}
|
|
5783
|
-
};
|
|
5784
|
-
for (var j = $remove_queue.length - 1; j >= 0; j--) {
|
|
5785
|
-
$remove_item = $remove_queue.pop();
|
|
5786
|
-
if (!_.isEmptyObject($remove_item)) {
|
|
5787
|
-
_this.remove($remove_item, remove_callback);
|
|
5788
|
-
}
|
|
5789
|
-
}
|
|
5790
|
-
_this._mixpanel['persistence'].save();
|
|
5791
|
-
}
|
|
3991
|
+
return this['props'][key] || (this['props'][key] = default_val);
|
|
5792
3992
|
};
|
|
5793
3993
|
|
|
5794
|
-
|
|
5795
|
-
|
|
3994
|
+
MixpanelPersistence.prototype.set_event_timer = function(event_name, timestamp) {
|
|
3995
|
+
var timers = this['props'][EVENT_TIMERS_KEY] || {};
|
|
3996
|
+
timers[event_name] = timestamp;
|
|
3997
|
+
this['props'][EVENT_TIMERS_KEY] = timers;
|
|
3998
|
+
this.save();
|
|
5796
3999
|
};
|
|
5797
4000
|
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5804
|
-
|
|
5805
|
-
|
|
5806
|
-
|
|
5807
|
-
MixpanelPeople.prototype['clear_charges'] = MixpanelPeople.prototype.clear_charges;
|
|
5808
|
-
MixpanelPeople.prototype['delete_user'] = MixpanelPeople.prototype.delete_user;
|
|
5809
|
-
MixpanelPeople.prototype['toString'] = MixpanelPeople.prototype.toString;
|
|
4001
|
+
MixpanelPersistence.prototype.remove_event_timer = function(event_name) {
|
|
4002
|
+
var timers = this['props'][EVENT_TIMERS_KEY] || {};
|
|
4003
|
+
var timestamp = timers[event_name];
|
|
4004
|
+
if (!_.isUndefined(timestamp)) {
|
|
4005
|
+
delete this['props'][EVENT_TIMERS_KEY][event_name];
|
|
4006
|
+
this.save();
|
|
4007
|
+
}
|
|
4008
|
+
return timestamp;
|
|
4009
|
+
};
|
|
5810
4010
|
|
|
5811
4011
|
/*
|
|
5812
4012
|
* Mixpanel JS Library
|
|
@@ -5862,10 +4062,10 @@
|
|
|
5862
4062
|
|
|
5863
4063
|
// save reference to navigator.sendBeacon so it can be minified
|
|
5864
4064
|
var sendBeacon = null;
|
|
5865
|
-
if (navigator
|
|
4065
|
+
if (navigator['sendBeacon']) {
|
|
5866
4066
|
sendBeacon = function() {
|
|
5867
4067
|
// late reference to navigator.sendBeacon to allow patching/spying
|
|
5868
|
-
return navigator
|
|
4068
|
+
return navigator['sendBeacon'].apply(navigator, arguments);
|
|
5869
4069
|
};
|
|
5870
4070
|
}
|
|
5871
4071
|
|
|
@@ -5881,6 +4081,7 @@
|
|
|
5881
4081
|
'cdn': 'https://cdn.mxpnl.com',
|
|
5882
4082
|
'cross_site_cookie': false,
|
|
5883
4083
|
'cross_subdomain_cookie': true,
|
|
4084
|
+
'error_reporter': NOOP_FUNC,
|
|
5884
4085
|
'persistence': 'cookie',
|
|
5885
4086
|
'persistence_name': '',
|
|
5886
4087
|
'cookie_domain': '',
|
|
@@ -5905,8 +4106,6 @@
|
|
|
5905
4106
|
'opt_out_tracking_cookie_prefix': null,
|
|
5906
4107
|
'property_blacklist': [],
|
|
5907
4108
|
'xhr_headers': {}, // { header: value, header2: value }
|
|
5908
|
-
'inapp_protocol': '//',
|
|
5909
|
-
'inapp_link_new_window': false,
|
|
5910
4109
|
'ignore_dnt': false,
|
|
5911
4110
|
'batch_requests': true,
|
|
5912
4111
|
'batch_size': 50,
|
|
@@ -5948,8 +4147,6 @@
|
|
|
5948
4147
|
}
|
|
5949
4148
|
|
|
5950
4149
|
instance._cached_groups = {}; // cache groups in a pool
|
|
5951
|
-
instance._user_decide_check_complete = false;
|
|
5952
|
-
instance._events_tracked_before_user_decide_check_complete = [];
|
|
5953
4150
|
|
|
5954
4151
|
instance._init(token, config, name);
|
|
5955
4152
|
|
|
@@ -5992,11 +4189,11 @@
|
|
|
5992
4189
|
*/
|
|
5993
4190
|
MixpanelLib.prototype.init = function (token, config, name) {
|
|
5994
4191
|
if (_.isUndefined(name)) {
|
|
5995
|
-
|
|
4192
|
+
this.report_error('You must name your new library: init(token, config, name)');
|
|
5996
4193
|
return;
|
|
5997
4194
|
}
|
|
5998
4195
|
if (name === PRIMARY_INSTANCE_NAME) {
|
|
5999
|
-
|
|
4196
|
+
this.report_error('You must initialize the main mixpanel object right after you include the Mixpanel js snippet');
|
|
6000
4197
|
return;
|
|
6001
4198
|
}
|
|
6002
4199
|
|
|
@@ -6019,7 +4216,6 @@
|
|
|
6019
4216
|
|
|
6020
4217
|
this['__loaded'] = true;
|
|
6021
4218
|
this['config'] = {};
|
|
6022
|
-
this['_triggered_notifs'] = [];
|
|
6023
4219
|
|
|
6024
4220
|
var variable_features = {};
|
|
6025
4221
|
|
|
@@ -6138,7 +4334,7 @@
|
|
|
6138
4334
|
|
|
6139
4335
|
MixpanelLib.prototype._track_dom = function(DomClass, args) {
|
|
6140
4336
|
if (this.get_config('img')) {
|
|
6141
|
-
|
|
4337
|
+
this.report_error('You can\'t use DOM tracking functions with img = true.');
|
|
6142
4338
|
return false;
|
|
6143
4339
|
}
|
|
6144
4340
|
|
|
@@ -6240,6 +4436,7 @@
|
|
|
6240
4436
|
|
|
6241
4437
|
url += '?' + _.HTTPBuildQuery(data);
|
|
6242
4438
|
|
|
4439
|
+
var lib = this;
|
|
6243
4440
|
if ('img' in data) {
|
|
6244
4441
|
var img = document$1.createElement('img');
|
|
6245
4442
|
img.src = url;
|
|
@@ -6248,7 +4445,7 @@
|
|
|
6248
4445
|
try {
|
|
6249
4446
|
succeeded = sendBeacon(url, body_data);
|
|
6250
4447
|
} catch (e) {
|
|
6251
|
-
|
|
4448
|
+
lib.report_error(e);
|
|
6252
4449
|
succeeded = false;
|
|
6253
4450
|
}
|
|
6254
4451
|
try {
|
|
@@ -6256,7 +4453,7 @@
|
|
|
6256
4453
|
callback(succeeded ? 1 : 0);
|
|
6257
4454
|
}
|
|
6258
4455
|
} catch (e) {
|
|
6259
|
-
|
|
4456
|
+
lib.report_error(e);
|
|
6260
4457
|
}
|
|
6261
4458
|
} else if (USE_XHR) {
|
|
6262
4459
|
try {
|
|
@@ -6288,7 +4485,7 @@
|
|
|
6288
4485
|
try {
|
|
6289
4486
|
response = _.JSONDecode(req.responseText);
|
|
6290
4487
|
} catch (e) {
|
|
6291
|
-
|
|
4488
|
+
lib.report_error(e);
|
|
6292
4489
|
if (options.ignore_json_errors) {
|
|
6293
4490
|
response = req.responseText;
|
|
6294
4491
|
} else {
|
|
@@ -6311,7 +4508,7 @@
|
|
|
6311
4508
|
} else {
|
|
6312
4509
|
error = 'Bad HTTP status: ' + req.status + ' ' + req.statusText;
|
|
6313
4510
|
}
|
|
6314
|
-
|
|
4511
|
+
lib.report_error(error);
|
|
6315
4512
|
if (callback) {
|
|
6316
4513
|
if (verbose_mode) {
|
|
6317
4514
|
callback({status: 0, error: error, xhr_req: req});
|
|
@@ -6324,7 +4521,7 @@
|
|
|
6324
4521
|
};
|
|
6325
4522
|
req.send(body_data);
|
|
6326
4523
|
} catch (e) {
|
|
6327
|
-
|
|
4524
|
+
lib.report_error(e);
|
|
6328
4525
|
succeeded = false;
|
|
6329
4526
|
}
|
|
6330
4527
|
} else {
|
|
@@ -6414,7 +4611,9 @@
|
|
|
6414
4611
|
}, this),
|
|
6415
4612
|
beforeSendHook: _.bind(function(item) {
|
|
6416
4613
|
return this._run_hook('before_send_' + attrs.type, item);
|
|
6417
|
-
}, this)
|
|
4614
|
+
}, this),
|
|
4615
|
+
errorReporter: this.get_config('error_reporter'),
|
|
4616
|
+
stopAllBatchingFunc: _.bind(this.stop_batch_senders, this)
|
|
6418
4617
|
}
|
|
6419
4618
|
);
|
|
6420
4619
|
}, this);
|
|
@@ -6571,7 +4770,7 @@
|
|
|
6571
4770
|
}
|
|
6572
4771
|
|
|
6573
4772
|
if (_.isUndefined(event_name)) {
|
|
6574
|
-
|
|
4773
|
+
this.report_error('No event name provided to mixpanel.track');
|
|
6575
4774
|
return;
|
|
6576
4775
|
}
|
|
6577
4776
|
|
|
@@ -6612,7 +4811,7 @@
|
|
|
6612
4811
|
delete properties[blacklisted_prop];
|
|
6613
4812
|
});
|
|
6614
4813
|
} else {
|
|
6615
|
-
|
|
4814
|
+
this.report_error('Invalid value for property_blacklist config: ' + property_blacklist);
|
|
6616
4815
|
}
|
|
6617
4816
|
|
|
6618
4817
|
var data = {
|
|
@@ -6628,8 +4827,6 @@
|
|
|
6628
4827
|
send_request_options: options
|
|
6629
4828
|
}, callback);
|
|
6630
4829
|
|
|
6631
|
-
this._check_and_handle_triggered_notifications(data);
|
|
6632
|
-
|
|
6633
4830
|
return ret;
|
|
6634
4831
|
});
|
|
6635
4832
|
|
|
@@ -6857,7 +5054,7 @@
|
|
|
6857
5054
|
*/
|
|
6858
5055
|
MixpanelLib.prototype.time_event = function(event_name) {
|
|
6859
5056
|
if (_.isUndefined(event_name)) {
|
|
6860
|
-
|
|
5057
|
+
this.report_error('No event name provided to mixpanel.time_event');
|
|
6861
5058
|
return;
|
|
6862
5059
|
}
|
|
6863
5060
|
|
|
@@ -7040,7 +5237,6 @@
|
|
|
7040
5237
|
this.unregister(ALIAS_ID_KEY);
|
|
7041
5238
|
this.register({'distinct_id': new_distinct_id});
|
|
7042
5239
|
}
|
|
7043
|
-
this._check_and_handle_notifications(this.get_distinct_id());
|
|
7044
5240
|
this._flags.identify_called = true;
|
|
7045
5241
|
// Flush any queued up people requests
|
|
7046
5242
|
this['people']._flush(_set_callback, _add_callback, _append_callback, _set_once_callback, _union_callback, _unset_callback, _remove_callback);
|
|
@@ -7130,7 +5326,7 @@
|
|
|
7130
5326
|
// mixpanel.people.identify() call made for this user. It is VERY BAD to make an alias with
|
|
7131
5327
|
// this ID, as it will duplicate users.
|
|
7132
5328
|
if (alias === this.get_property(PEOPLE_DISTINCT_ID_KEY)) {
|
|
7133
|
-
|
|
5329
|
+
this.report_error('Attempting to create alias for existing People user - aborting.');
|
|
7134
5330
|
return -2;
|
|
7135
5331
|
}
|
|
7136
5332
|
|
|
@@ -7150,7 +5346,7 @@
|
|
|
7150
5346
|
_this.identify(alias);
|
|
7151
5347
|
});
|
|
7152
5348
|
} else {
|
|
7153
|
-
|
|
5349
|
+
this.report_error('alias matches current distinct_id - skipping api call.');
|
|
7154
5350
|
this.identify(alias);
|
|
7155
5351
|
return -1;
|
|
7156
5352
|
}
|
|
@@ -7277,14 +5473,6 @@
|
|
|
7277
5473
|
* // the format {'Header-Name': value}
|
|
7278
5474
|
* xhr_headers: {}
|
|
7279
5475
|
*
|
|
7280
|
-
* // protocol for fetching in-app message resources, e.g.
|
|
7281
|
-
* // 'https://' or 'http://'; defaults to '//' (which defers to the
|
|
7282
|
-
* // current page's protocol)
|
|
7283
|
-
* inapp_protocol: '//'
|
|
7284
|
-
*
|
|
7285
|
-
* // whether to open in-app message link in new tab/window
|
|
7286
|
-
* inapp_link_new_window: false
|
|
7287
|
-
*
|
|
7288
5476
|
* // whether to ignore or respect the web browser's Do Not Track setting
|
|
7289
5477
|
* ignore_dnt: false
|
|
7290
5478
|
* }
|
|
@@ -7333,7 +5521,7 @@
|
|
|
7333
5521
|
MixpanelLib.prototype._run_hook = function(hook_name) {
|
|
7334
5522
|
var ret = (this['config']['hooks'][hook_name] || IDENTITY_FUNC).apply(this, slice.call(arguments, 1));
|
|
7335
5523
|
if (typeof ret === 'undefined') {
|
|
7336
|
-
|
|
5524
|
+
this.report_error(hook_name + ' hook did not return a value');
|
|
7337
5525
|
ret = null;
|
|
7338
5526
|
}
|
|
7339
5527
|
return ret;
|
|
@@ -7375,75 +5563,6 @@
|
|
|
7375
5563
|
_.include(this.__disabled_events, event_name);
|
|
7376
5564
|
};
|
|
7377
5565
|
|
|
7378
|
-
MixpanelLib.prototype._check_and_handle_triggered_notifications = addOptOutCheckMixpanelLib(function(event_data) {
|
|
7379
|
-
if (!this._user_decide_check_complete) {
|
|
7380
|
-
this._events_tracked_before_user_decide_check_complete.push(event_data);
|
|
7381
|
-
} else {
|
|
7382
|
-
var arr = this['_triggered_notifs'];
|
|
7383
|
-
for (var i = 0; i < arr.length; i++) {
|
|
7384
|
-
var notif = new MixpanelNotification(arr[i], this);
|
|
7385
|
-
if (notif._matches_event_data(event_data)) {
|
|
7386
|
-
this._show_notification(arr[i]);
|
|
7387
|
-
return;
|
|
7388
|
-
}
|
|
7389
|
-
}
|
|
7390
|
-
}
|
|
7391
|
-
});
|
|
7392
|
-
|
|
7393
|
-
MixpanelLib.prototype._check_and_handle_notifications = addOptOutCheckMixpanelLib(function(distinct_id) {
|
|
7394
|
-
if (
|
|
7395
|
-
!distinct_id ||
|
|
7396
|
-
this._flags.identify_called ||
|
|
7397
|
-
this.get_config('disable_notifications')
|
|
7398
|
-
) {
|
|
7399
|
-
return;
|
|
7400
|
-
}
|
|
7401
|
-
|
|
7402
|
-
console.log('MIXPANEL NOTIFICATION CHECK');
|
|
7403
|
-
|
|
7404
|
-
var data = {
|
|
7405
|
-
'verbose': true,
|
|
7406
|
-
'version': '3',
|
|
7407
|
-
'lib': 'web',
|
|
7408
|
-
'token': this.get_config('token'),
|
|
7409
|
-
'distinct_id': distinct_id
|
|
7410
|
-
};
|
|
7411
|
-
this._send_request(
|
|
7412
|
-
this.get_config('api_host') + '/decide/',
|
|
7413
|
-
data,
|
|
7414
|
-
{method: 'GET', transport: 'XHR'},
|
|
7415
|
-
this._prepare_callback(_.bind(function(result) {
|
|
7416
|
-
if (result['notifications'] && result['notifications'].length > 0) {
|
|
7417
|
-
this['_triggered_notifs'] = [];
|
|
7418
|
-
var notifications = [];
|
|
7419
|
-
_.each(result['notifications'], function(notif) {
|
|
7420
|
-
(notif['display_triggers'] && notif['display_triggers'].length > 0 ? this['_triggered_notifs'] : notifications).push(notif);
|
|
7421
|
-
}, this);
|
|
7422
|
-
if (notifications.length > 0) {
|
|
7423
|
-
this._show_notification.call(this, notifications[0]);
|
|
7424
|
-
}
|
|
7425
|
-
}
|
|
7426
|
-
this._handle_user_decide_check_complete();
|
|
7427
|
-
}, this))
|
|
7428
|
-
);
|
|
7429
|
-
});
|
|
7430
|
-
|
|
7431
|
-
MixpanelLib.prototype._handle_user_decide_check_complete = function() {
|
|
7432
|
-
this._user_decide_check_complete = true;
|
|
7433
|
-
|
|
7434
|
-
// check notifications against events that were tracked before decide call completed
|
|
7435
|
-
var events = this._events_tracked_before_user_decide_check_complete;
|
|
7436
|
-
while (events.length > 0) {
|
|
7437
|
-
var data = events.shift(); // replay in the same order they came in
|
|
7438
|
-
this._check_and_handle_triggered_notifications(data);
|
|
7439
|
-
}
|
|
7440
|
-
};
|
|
7441
|
-
|
|
7442
|
-
MixpanelLib.prototype._show_notification = function(notif_data) {
|
|
7443
|
-
var notification = new MixpanelNotification(notif_data, this);
|
|
7444
|
-
notification.show();
|
|
7445
|
-
};
|
|
7446
|
-
|
|
7447
5566
|
// perform some housekeeping around GDPR opt-in/out state
|
|
7448
5567
|
MixpanelLib.prototype._gdpr_init = function() {
|
|
7449
5568
|
var is_localStorage_requested = this.get_config('opt_out_tracking_persistence_type') === 'localStorage';
|
|
@@ -7689,6 +5808,18 @@
|
|
|
7689
5808
|
this._gdpr_update_persistence(options);
|
|
7690
5809
|
};
|
|
7691
5810
|
|
|
5811
|
+
MixpanelLib.prototype.report_error = function(msg, err) {
|
|
5812
|
+
console.error.apply(console.error, arguments);
|
|
5813
|
+
try {
|
|
5814
|
+
if (!err && !(msg instanceof Error)) {
|
|
5815
|
+
msg = new Error(msg);
|
|
5816
|
+
}
|
|
5817
|
+
this.get_config('error_reporter')(msg, err);
|
|
5818
|
+
} catch(err) {
|
|
5819
|
+
console.error(err);
|
|
5820
|
+
}
|
|
5821
|
+
};
|
|
5822
|
+
|
|
7692
5823
|
// EXPORTS (for closure compiler)
|
|
7693
5824
|
|
|
7694
5825
|
// MixpanelLib Exports
|
|
@@ -7711,9 +5842,6 @@
|
|
|
7711
5842
|
MixpanelLib.prototype['get_property'] = MixpanelLib.prototype.get_property;
|
|
7712
5843
|
MixpanelLib.prototype['get_distinct_id'] = MixpanelLib.prototype.get_distinct_id;
|
|
7713
5844
|
MixpanelLib.prototype['toString'] = MixpanelLib.prototype.toString;
|
|
7714
|
-
MixpanelLib.prototype['_check_and_handle_notifications'] = MixpanelLib.prototype._check_and_handle_notifications;
|
|
7715
|
-
MixpanelLib.prototype['_handle_user_decide_check_complete'] = MixpanelLib.prototype._handle_user_decide_check_complete;
|
|
7716
|
-
MixpanelLib.prototype['_show_notification'] = MixpanelLib.prototype._show_notification;
|
|
7717
5845
|
MixpanelLib.prototype['opt_out_tracking'] = MixpanelLib.prototype.opt_out_tracking;
|
|
7718
5846
|
MixpanelLib.prototype['opt_in_tracking'] = MixpanelLib.prototype.opt_in_tracking;
|
|
7719
5847
|
MixpanelLib.prototype['has_opted_out_tracking'] = MixpanelLib.prototype.has_opted_out_tracking;
|
|
@@ -7734,8 +5862,6 @@
|
|
|
7734
5862
|
MixpanelPersistence.prototype['get_cross_subdomain'] = MixpanelPersistence.prototype.get_cross_subdomain;
|
|
7735
5863
|
MixpanelPersistence.prototype['clear'] = MixpanelPersistence.prototype.clear;
|
|
7736
5864
|
|
|
7737
|
-
_.safewrap_class(MixpanelLib, ['identify', '_check_and_handle_notifications', '_show_notification']);
|
|
7738
|
-
|
|
7739
5865
|
|
|
7740
5866
|
var instances = {};
|
|
7741
5867
|
var extend_mp = function() {
|