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