mixpanel-browser 2.45.0 → 2.46.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 +5 -1
- package/README.md +1 -1
- package/build.sh +2 -0
- package/dist/mixpanel.amd.js +93 -34
- package/dist/mixpanel.cjs.js +93 -34
- package/dist/mixpanel.globals.js +93 -34
- package/dist/mixpanel.min.js +100 -99
- package/dist/mixpanel.umd.js +93 -34
- package/doc/readme.io/javascript-full-api-reference.md +3 -55
- package/doc/template.md +1 -1
- package/package.json +5 -5
- package/src/config.js +1 -1
- package/src/mixpanel-core.js +14 -5
- package/src/mixpanel-people.js +29 -27
- package/src/request-batcher.js +50 -1
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.46.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
|
|
@@ -2299,6 +2299,9 @@
|
|
|
2299
2299
|
|
|
2300
2300
|
this.stopped = !this.libConfig['batch_autostart'];
|
|
2301
2301
|
this.consecutiveRemovalFailures = 0;
|
|
2302
|
+
|
|
2303
|
+
// extra client-side dedupe
|
|
2304
|
+
this.itemIdsSentSuccessfully = {};
|
|
2302
2305
|
};
|
|
2303
2306
|
|
|
2304
2307
|
/**
|
|
@@ -2391,7 +2394,34 @@
|
|
|
2391
2394
|
payload = this.beforeSendHook(payload);
|
|
2392
2395
|
}
|
|
2393
2396
|
if (payload) {
|
|
2394
|
-
|
|
2397
|
+
// mp_sent_by_lib_version prop captures which lib version actually
|
|
2398
|
+
// sends each event (regardless of which version originally queued
|
|
2399
|
+
// it for sending)
|
|
2400
|
+
if (payload['event'] && payload['properties']) {
|
|
2401
|
+
payload['properties'] = _.extend(
|
|
2402
|
+
{},
|
|
2403
|
+
payload['properties'],
|
|
2404
|
+
{'mp_sent_by_lib_version': Config.LIB_VERSION}
|
|
2405
|
+
);
|
|
2406
|
+
}
|
|
2407
|
+
var addPayload = true;
|
|
2408
|
+
var itemId = item['id'];
|
|
2409
|
+
if (itemId) {
|
|
2410
|
+
if ((this.itemIdsSentSuccessfully[itemId] || 0) > 5) {
|
|
2411
|
+
this.reportError('[dupe] item ID sent too many times, not sending', {
|
|
2412
|
+
item: item,
|
|
2413
|
+
batchSize: batch.length,
|
|
2414
|
+
timesSent: this.itemIdsSentSuccessfully[itemId]
|
|
2415
|
+
});
|
|
2416
|
+
addPayload = false;
|
|
2417
|
+
}
|
|
2418
|
+
} else {
|
|
2419
|
+
this.reportError('[dupe] found item with no ID', {item: item});
|
|
2420
|
+
}
|
|
2421
|
+
|
|
2422
|
+
if (addPayload) {
|
|
2423
|
+
dataForRequest.push(payload);
|
|
2424
|
+
}
|
|
2395
2425
|
}
|
|
2396
2426
|
transformedItems[item['id']] = payload;
|
|
2397
2427
|
}, this);
|
|
@@ -2474,6 +2504,24 @@
|
|
|
2474
2504
|
}
|
|
2475
2505
|
}, this)
|
|
2476
2506
|
);
|
|
2507
|
+
|
|
2508
|
+
// client-side dedupe
|
|
2509
|
+
_.each(batch, _.bind(function(item) {
|
|
2510
|
+
var itemId = item['id'];
|
|
2511
|
+
if (itemId) {
|
|
2512
|
+
this.itemIdsSentSuccessfully[itemId] = this.itemIdsSentSuccessfully[itemId] || 0;
|
|
2513
|
+
this.itemIdsSentSuccessfully[itemId]++;
|
|
2514
|
+
if (this.itemIdsSentSuccessfully[itemId] > 5) {
|
|
2515
|
+
this.reportError('[dupe] item ID sent too many times', {
|
|
2516
|
+
item: item,
|
|
2517
|
+
batchSize: batch.length,
|
|
2518
|
+
timesSent: this.itemIdsSentSuccessfully[itemId]
|
|
2519
|
+
});
|
|
2520
|
+
}
|
|
2521
|
+
} else {
|
|
2522
|
+
this.reportError('[dupe] found item with no ID while removing', {item: item});
|
|
2523
|
+
}
|
|
2524
|
+
}, this));
|
|
2477
2525
|
}
|
|
2478
2526
|
|
|
2479
2527
|
} catch(err) {
|
|
@@ -3319,24 +3367,25 @@
|
|
|
3319
3367
|
});
|
|
3320
3368
|
|
|
3321
3369
|
/*
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3370
|
+
* Record that you have charged the current user a certain amount
|
|
3371
|
+
* of money. Charges recorded with track_charge() will appear in the
|
|
3372
|
+
* Mixpanel revenue report.
|
|
3373
|
+
*
|
|
3374
|
+
* ### Usage:
|
|
3375
|
+
*
|
|
3376
|
+
* // charge a user $50
|
|
3377
|
+
* mixpanel.people.track_charge(50);
|
|
3378
|
+
*
|
|
3379
|
+
* // charge a user $30.50 on the 2nd of january
|
|
3380
|
+
* mixpanel.people.track_charge(30.50, {
|
|
3381
|
+
* '$time': new Date('jan 1 2012')
|
|
3382
|
+
* });
|
|
3383
|
+
*
|
|
3384
|
+
* @param {Number} amount The amount of money charged to the current user
|
|
3385
|
+
* @param {Object} [properties] An associative array of properties associated with the charge
|
|
3386
|
+
* @param {Function} [callback] If provided, the callback will be called when the server responds
|
|
3387
|
+
* @deprecated
|
|
3388
|
+
*/
|
|
3340
3389
|
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function(amount, properties, callback) {
|
|
3341
3390
|
if (!_.isNumber(amount)) {
|
|
3342
3391
|
amount = parseFloat(amount);
|
|
@@ -3352,15 +3401,16 @@
|
|
|
3352
3401
|
});
|
|
3353
3402
|
|
|
3354
3403
|
/*
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3404
|
+
* Permanently clear all revenue report transactions from the
|
|
3405
|
+
* current user's people analytics profile.
|
|
3406
|
+
*
|
|
3407
|
+
* ### Usage:
|
|
3408
|
+
*
|
|
3409
|
+
* mixpanel.people.clear_charges();
|
|
3410
|
+
*
|
|
3411
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
3412
|
+
* @deprecated
|
|
3413
|
+
*/
|
|
3364
3414
|
MixpanelPeople.prototype.clear_charges = function(callback) {
|
|
3365
3415
|
return this.set('$transactions', [], callback);
|
|
3366
3416
|
};
|
|
@@ -4049,6 +4099,7 @@
|
|
|
4049
4099
|
/** @const */ var PRIMARY_INSTANCE_NAME = 'mixpanel';
|
|
4050
4100
|
/** @const */ var PAYLOAD_TYPE_BASE64 = 'base64';
|
|
4051
4101
|
/** @const */ var PAYLOAD_TYPE_JSON = 'json';
|
|
4102
|
+
/** @const */ var DEVICE_ID_PREFIX = '$device:';
|
|
4052
4103
|
|
|
4053
4104
|
|
|
4054
4105
|
/*
|
|
@@ -4296,7 +4347,7 @@
|
|
|
4296
4347
|
// or the device id if something was already stored
|
|
4297
4348
|
// in the persitence
|
|
4298
4349
|
this.register_once({
|
|
4299
|
-
'distinct_id': uuid,
|
|
4350
|
+
'distinct_id': DEVICE_ID_PREFIX + uuid,
|
|
4300
4351
|
'$device_id': uuid
|
|
4301
4352
|
}, '');
|
|
4302
4353
|
}
|
|
@@ -5222,7 +5273,15 @@
|
|
|
5222
5273
|
// _unset_callback:function A callback to be run if and when the People unset queue is flushed
|
|
5223
5274
|
|
|
5224
5275
|
var previous_distinct_id = this.get_distinct_id();
|
|
5225
|
-
|
|
5276
|
+
if (new_distinct_id && previous_distinct_id !== new_distinct_id) {
|
|
5277
|
+
// we allow the following condition if previous distinct_id is same as new_distinct_id
|
|
5278
|
+
// so that you can force flush people updates for anonymous profiles.
|
|
5279
|
+
if (typeof new_distinct_id === 'string' && new_distinct_id.indexOf(DEVICE_ID_PREFIX) === 0) {
|
|
5280
|
+
this.report_error('distinct_id cannot have $device: prefix');
|
|
5281
|
+
return -1;
|
|
5282
|
+
}
|
|
5283
|
+
this.register({'$user_id': new_distinct_id});
|
|
5284
|
+
}
|
|
5226
5285
|
|
|
5227
5286
|
if (!this.get_property('$device_id')) {
|
|
5228
5287
|
// The persisted distinct id might not actually be a device id at all
|
|
@@ -5263,7 +5322,7 @@
|
|
|
5263
5322
|
this._flags.identify_called = false;
|
|
5264
5323
|
var uuid = _.UUID();
|
|
5265
5324
|
this.register_once({
|
|
5266
|
-
'distinct_id': uuid,
|
|
5325
|
+
'distinct_id': DEVICE_ID_PREFIX + uuid,
|
|
5267
5326
|
'$device_id': uuid
|
|
5268
5327
|
}, '');
|
|
5269
5328
|
};
|
|
@@ -5388,8 +5447,8 @@
|
|
|
5388
5447
|
* // batching or retry mechanisms.
|
|
5389
5448
|
* api_transport: 'XHR'
|
|
5390
5449
|
*
|
|
5391
|
-
* //
|
|
5392
|
-
* batch_requests:
|
|
5450
|
+
* // request-batching/queueing/retry
|
|
5451
|
+
* batch_requests: true,
|
|
5393
5452
|
*
|
|
5394
5453
|
* // maximum number of events/updates to send in a single
|
|
5395
5454
|
* // network request
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
category:
|
|
2
|
+
category: 62ec0192a94ae90a45602b13
|
|
3
3
|
title: JavaScript Full API Reference
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -450,8 +450,8 @@ The default config is:
|
|
|
450
450
|
// batching or retry mechanisms.
|
|
451
451
|
api_transport: 'XHR'
|
|
452
452
|
|
|
453
|
-
//
|
|
454
|
-
batch_requests:
|
|
453
|
+
// request-batching/queueing/retry
|
|
454
|
+
batch_requests: true,
|
|
455
455
|
|
|
456
456
|
// maximum number of events/updates to send in a single
|
|
457
457
|
// network request
|
|
@@ -538,14 +538,6 @@ The default config is:
|
|
|
538
538
|
// the format {'Header-Name': value}
|
|
539
539
|
xhr_headers: {}
|
|
540
540
|
|
|
541
|
-
// protocol for fetching in-app message resources, e.g.
|
|
542
|
-
// 'https://' or 'http://'; defaults to '//' (which defers to the
|
|
543
|
-
// current page's protocol)
|
|
544
|
-
inapp_protocol: '//'
|
|
545
|
-
|
|
546
|
-
// whether to open in-app message link in new tab/window
|
|
547
|
-
inapp_link_new_window: false
|
|
548
|
-
|
|
549
541
|
// whether to ignore or respect the web browser's Do Not Track setting
|
|
550
542
|
ignore_dnt: false
|
|
551
543
|
}
|
|
@@ -761,24 +753,6 @@ mixpanel.people.append({
|
|
|
761
753
|
| **callback** | <span class="mp-arg-type">Function</span></br></span><span class="mp-arg-optional">optional</span> | If provided, the callback will be called after tracking the event. |
|
|
762
754
|
|
|
763
755
|
|
|
764
|
-
___
|
|
765
|
-
## mixpanel.people.clear_charges
|
|
766
|
-
Permanently clear all revenue report transactions from the current user's people analytics profile.
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
### Usage:
|
|
770
|
-
|
|
771
|
-
```javascript
|
|
772
|
-
mixpanel.people.clear_charges();
|
|
773
|
-
```
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
| Argument | Type | Description |
|
|
778
|
-
| ------------- | ------------- | ----- |
|
|
779
|
-
| **callback** | <span class="mp-arg-type">Function</span></br></span><span class="mp-arg-optional">optional</span> | If provided, the callback will be called after tracking the event. |
|
|
780
|
-
|
|
781
|
-
|
|
782
756
|
___
|
|
783
757
|
## mixpanel.people.delete_user
|
|
784
758
|
Permanently deletes the current people analytics profile from Mixpanel (using the current distinct_id).
|
|
@@ -904,32 +878,6 @@ mixpanel.people.set_once({
|
|
|
904
878
|
| **callback** | <span class="mp-arg-type">Function</span></br></span><span class="mp-arg-optional">optional</span> | If provided, the callback will be called after tracking the event. |
|
|
905
879
|
|
|
906
880
|
|
|
907
|
-
___
|
|
908
|
-
## mixpanel.people.track_charge
|
|
909
|
-
Record that you have charged the current user a certain amount of money. Charges recorded with track_charge() will appear in the Mixpanel revenue report.
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
### Usage:
|
|
913
|
-
|
|
914
|
-
```javascript
|
|
915
|
-
// charge a user $50
|
|
916
|
-
mixpanel.people.track_charge(50);
|
|
917
|
-
|
|
918
|
-
// charge a user $30.50 on the 2nd of january
|
|
919
|
-
mixpanel.people.track_charge(30.50, {
|
|
920
|
-
'$time': new Date('jan 1 2012')
|
|
921
|
-
});
|
|
922
|
-
```
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
| Argument | Type | Description |
|
|
927
|
-
| ------------- | ------------- | ----- |
|
|
928
|
-
| **amount** | <span class="mp-arg-type">Number</span></br></span><span class="mp-arg-required">required</span> | The amount of money charged to the current user |
|
|
929
|
-
| **properties** | <span class="mp-arg-type">Object</span></br></span><span class="mp-arg-optional">optional</span> | An associative array of properties associated with the charge |
|
|
930
|
-
| **callback** | <span class="mp-arg-type">Function</span></br></span><span class="mp-arg-optional">optional</span> | If provided, the callback will be called when the server responds |
|
|
931
|
-
|
|
932
|
-
|
|
933
881
|
___
|
|
934
882
|
## mixpanel.people.union
|
|
935
883
|
Merge a given list with a list-valued people analytics property, excluding duplicate values.
|
package/doc/template.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mixpanel-browser",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.46.0",
|
|
4
4
|
"description": "The official Mixpanel JavaScript browser client library",
|
|
5
5
|
"main": "dist/mixpanel.cjs.js",
|
|
6
6
|
"directories": {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"build-full": "FULL=1 ./build.sh",
|
|
13
13
|
"build-test-polyfill": "webpack tests/vendor/core-js-polyfills.src.js tests/vendor/core-js-polyfills.js",
|
|
14
14
|
"dox": "node doc/build-docs.js",
|
|
15
|
-
"dox-publish": "rdme docs doc/readme.io --key=$RDME_API_KEY --version
|
|
15
|
+
"dox-publish": "rdme docs:single doc/readme.io/javascript-full-api-reference.md --key=$RDME_API_KEY --version=$RDME_DOC_VERSION",
|
|
16
16
|
"integration_test": "echo 'Browse to localhost:3000/tests' && node testServer.js",
|
|
17
17
|
"lint": "eslint ./src",
|
|
18
18
|
"prepublishOnly": "npm run build-dist",
|
|
@@ -37,19 +37,19 @@
|
|
|
37
37
|
"babel-preset-es2015": "6.6.0",
|
|
38
38
|
"babelify": "6.1.2",
|
|
39
39
|
"browserify": "10.2.4",
|
|
40
|
-
"chai": "
|
|
40
|
+
"chai": "4.0.0",
|
|
41
41
|
"cookie-parser": "1.3.4",
|
|
42
42
|
"core-js": "3.6.5",
|
|
43
43
|
"dox": "0.9.0",
|
|
44
44
|
"eslint": "4.18.2",
|
|
45
45
|
"express": "4.12.2",
|
|
46
|
-
"jsdom": "
|
|
46
|
+
"jsdom": "16.5.0",
|
|
47
47
|
"jsdom-global": "3.0.2",
|
|
48
48
|
"localStorage": "1.0.4",
|
|
49
49
|
"lodash": "4.17.21",
|
|
50
50
|
"mocha": "7.1.1",
|
|
51
51
|
"morgan": "1.9.1",
|
|
52
|
-
"rdme": "
|
|
52
|
+
"rdme": "7.5.0",
|
|
53
53
|
"request": "2.88.0",
|
|
54
54
|
"rollup": "0.25.8",
|
|
55
55
|
"rollup-plugin-npm": "1.4.0",
|
package/src/config.js
CHANGED
package/src/mixpanel-core.js
CHANGED
|
@@ -57,6 +57,7 @@ var NOOP_FUNC = function() {};
|
|
|
57
57
|
/** @const */ var PRIMARY_INSTANCE_NAME = 'mixpanel';
|
|
58
58
|
/** @const */ var PAYLOAD_TYPE_BASE64 = 'base64';
|
|
59
59
|
/** @const */ var PAYLOAD_TYPE_JSON = 'json';
|
|
60
|
+
/** @const */ var DEVICE_ID_PREFIX = '$device:';
|
|
60
61
|
|
|
61
62
|
|
|
62
63
|
/*
|
|
@@ -304,7 +305,7 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
304
305
|
// or the device id if something was already stored
|
|
305
306
|
// in the persitence
|
|
306
307
|
this.register_once({
|
|
307
|
-
'distinct_id': uuid,
|
|
308
|
+
'distinct_id': DEVICE_ID_PREFIX + uuid,
|
|
308
309
|
'$device_id': uuid
|
|
309
310
|
}, '');
|
|
310
311
|
}
|
|
@@ -1230,7 +1231,15 @@ MixpanelLib.prototype.identify = function(
|
|
|
1230
1231
|
// _unset_callback:function A callback to be run if and when the People unset queue is flushed
|
|
1231
1232
|
|
|
1232
1233
|
var previous_distinct_id = this.get_distinct_id();
|
|
1233
|
-
|
|
1234
|
+
if (new_distinct_id && previous_distinct_id !== new_distinct_id) {
|
|
1235
|
+
// we allow the following condition if previous distinct_id is same as new_distinct_id
|
|
1236
|
+
// so that you can force flush people updates for anonymous profiles.
|
|
1237
|
+
if (typeof new_distinct_id === 'string' && new_distinct_id.indexOf(DEVICE_ID_PREFIX) === 0) {
|
|
1238
|
+
this.report_error('distinct_id cannot have $device: prefix');
|
|
1239
|
+
return -1;
|
|
1240
|
+
}
|
|
1241
|
+
this.register({'$user_id': new_distinct_id});
|
|
1242
|
+
}
|
|
1234
1243
|
|
|
1235
1244
|
if (!this.get_property('$device_id')) {
|
|
1236
1245
|
// The persisted distinct id might not actually be a device id at all
|
|
@@ -1271,7 +1280,7 @@ MixpanelLib.prototype.reset = function() {
|
|
|
1271
1280
|
this._flags.identify_called = false;
|
|
1272
1281
|
var uuid = _.UUID();
|
|
1273
1282
|
this.register_once({
|
|
1274
|
-
'distinct_id': uuid,
|
|
1283
|
+
'distinct_id': DEVICE_ID_PREFIX + uuid,
|
|
1275
1284
|
'$device_id': uuid
|
|
1276
1285
|
}, '');
|
|
1277
1286
|
};
|
|
@@ -1396,8 +1405,8 @@ MixpanelLib.prototype.name_tag = function(name_tag) {
|
|
|
1396
1405
|
* // batching or retry mechanisms.
|
|
1397
1406
|
* api_transport: 'XHR'
|
|
1398
1407
|
*
|
|
1399
|
-
* //
|
|
1400
|
-
* batch_requests:
|
|
1408
|
+
* // request-batching/queueing/retry
|
|
1409
|
+
* batch_requests: true,
|
|
1401
1410
|
*
|
|
1402
1411
|
* // maximum number of events/updates to send in a single
|
|
1403
1412
|
* // network request
|
package/src/mixpanel-people.js
CHANGED
|
@@ -244,24 +244,25 @@ MixpanelPeople.prototype.union = addOptOutCheckMixpanelPeople(function(list_name
|
|
|
244
244
|
});
|
|
245
245
|
|
|
246
246
|
/*
|
|
247
|
-
* Record that you have charged the current user a certain amount
|
|
248
|
-
* of money. Charges recorded with track_charge() will appear in the
|
|
249
|
-
* Mixpanel revenue report.
|
|
250
|
-
*
|
|
251
|
-
* ### Usage:
|
|
252
|
-
*
|
|
253
|
-
* // charge a user $50
|
|
254
|
-
* mixpanel.people.track_charge(50);
|
|
255
|
-
*
|
|
256
|
-
* // charge a user $30.50 on the 2nd of january
|
|
257
|
-
* mixpanel.people.track_charge(30.50, {
|
|
258
|
-
* '$time': new Date('jan 1 2012')
|
|
259
|
-
* });
|
|
260
|
-
*
|
|
261
|
-
* @param {Number} amount The amount of money charged to the current user
|
|
262
|
-
* @param {Object} [properties] An associative array of properties associated with the charge
|
|
263
|
-
* @param {Function} [callback] If provided, the callback will be called when the server responds
|
|
264
|
-
|
|
247
|
+
* Record that you have charged the current user a certain amount
|
|
248
|
+
* of money. Charges recorded with track_charge() will appear in the
|
|
249
|
+
* Mixpanel revenue report.
|
|
250
|
+
*
|
|
251
|
+
* ### Usage:
|
|
252
|
+
*
|
|
253
|
+
* // charge a user $50
|
|
254
|
+
* mixpanel.people.track_charge(50);
|
|
255
|
+
*
|
|
256
|
+
* // charge a user $30.50 on the 2nd of january
|
|
257
|
+
* mixpanel.people.track_charge(30.50, {
|
|
258
|
+
* '$time': new Date('jan 1 2012')
|
|
259
|
+
* });
|
|
260
|
+
*
|
|
261
|
+
* @param {Number} amount The amount of money charged to the current user
|
|
262
|
+
* @param {Object} [properties] An associative array of properties associated with the charge
|
|
263
|
+
* @param {Function} [callback] If provided, the callback will be called when the server responds
|
|
264
|
+
* @deprecated
|
|
265
|
+
*/
|
|
265
266
|
MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function(amount, properties, callback) {
|
|
266
267
|
if (!_.isNumber(amount)) {
|
|
267
268
|
amount = parseFloat(amount);
|
|
@@ -277,15 +278,16 @@ MixpanelPeople.prototype.track_charge = addOptOutCheckMixpanelPeople(function(am
|
|
|
277
278
|
});
|
|
278
279
|
|
|
279
280
|
/*
|
|
280
|
-
* Permanently clear all revenue report transactions from the
|
|
281
|
-
* current user's people analytics profile.
|
|
282
|
-
*
|
|
283
|
-
* ### Usage:
|
|
284
|
-
*
|
|
285
|
-
* mixpanel.people.clear_charges();
|
|
286
|
-
*
|
|
287
|
-
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
288
|
-
|
|
281
|
+
* Permanently clear all revenue report transactions from the
|
|
282
|
+
* current user's people analytics profile.
|
|
283
|
+
*
|
|
284
|
+
* ### Usage:
|
|
285
|
+
*
|
|
286
|
+
* mixpanel.people.clear_charges();
|
|
287
|
+
*
|
|
288
|
+
* @param {Function} [callback] If provided, the callback will be called after tracking the event.
|
|
289
|
+
* @deprecated
|
|
290
|
+
*/
|
|
289
291
|
MixpanelPeople.prototype.clear_charges = function(callback) {
|
|
290
292
|
return this.set('$transactions', [], callback);
|
|
291
293
|
};
|
package/src/request-batcher.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Config from './config';
|
|
1
2
|
import { RequestQueue } from './request-queue';
|
|
2
3
|
import { console_with_prefix, _ } from './utils'; // eslint-disable-line camelcase
|
|
3
4
|
|
|
@@ -30,6 +31,9 @@ var RequestBatcher = function(storageKey, options) {
|
|
|
30
31
|
|
|
31
32
|
this.stopped = !this.libConfig['batch_autostart'];
|
|
32
33
|
this.consecutiveRemovalFailures = 0;
|
|
34
|
+
|
|
35
|
+
// extra client-side dedupe
|
|
36
|
+
this.itemIdsSentSuccessfully = {};
|
|
33
37
|
};
|
|
34
38
|
|
|
35
39
|
/**
|
|
@@ -122,7 +126,34 @@ RequestBatcher.prototype.flush = function(options) {
|
|
|
122
126
|
payload = this.beforeSendHook(payload);
|
|
123
127
|
}
|
|
124
128
|
if (payload) {
|
|
125
|
-
|
|
129
|
+
// mp_sent_by_lib_version prop captures which lib version actually
|
|
130
|
+
// sends each event (regardless of which version originally queued
|
|
131
|
+
// it for sending)
|
|
132
|
+
if (payload['event'] && payload['properties']) {
|
|
133
|
+
payload['properties'] = _.extend(
|
|
134
|
+
{},
|
|
135
|
+
payload['properties'],
|
|
136
|
+
{'mp_sent_by_lib_version': Config.LIB_VERSION}
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
var addPayload = true;
|
|
140
|
+
var itemId = item['id'];
|
|
141
|
+
if (itemId) {
|
|
142
|
+
if ((this.itemIdsSentSuccessfully[itemId] || 0) > 5) {
|
|
143
|
+
this.reportError('[dupe] item ID sent too many times, not sending', {
|
|
144
|
+
item: item,
|
|
145
|
+
batchSize: batch.length,
|
|
146
|
+
timesSent: this.itemIdsSentSuccessfully[itemId]
|
|
147
|
+
});
|
|
148
|
+
addPayload = false;
|
|
149
|
+
}
|
|
150
|
+
} else {
|
|
151
|
+
this.reportError('[dupe] found item with no ID', {item: item});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (addPayload) {
|
|
155
|
+
dataForRequest.push(payload);
|
|
156
|
+
}
|
|
126
157
|
}
|
|
127
158
|
transformedItems[item['id']] = payload;
|
|
128
159
|
}, this);
|
|
@@ -205,6 +236,24 @@ RequestBatcher.prototype.flush = function(options) {
|
|
|
205
236
|
}
|
|
206
237
|
}, this)
|
|
207
238
|
);
|
|
239
|
+
|
|
240
|
+
// client-side dedupe
|
|
241
|
+
_.each(batch, _.bind(function(item) {
|
|
242
|
+
var itemId = item['id'];
|
|
243
|
+
if (itemId) {
|
|
244
|
+
this.itemIdsSentSuccessfully[itemId] = this.itemIdsSentSuccessfully[itemId] || 0;
|
|
245
|
+
this.itemIdsSentSuccessfully[itemId]++;
|
|
246
|
+
if (this.itemIdsSentSuccessfully[itemId] > 5) {
|
|
247
|
+
this.reportError('[dupe] item ID sent too many times', {
|
|
248
|
+
item: item,
|
|
249
|
+
batchSize: batch.length,
|
|
250
|
+
timesSent: this.itemIdsSentSuccessfully[itemId]
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
this.reportError('[dupe] found item with no ID while removing', {item: item});
|
|
255
|
+
}
|
|
256
|
+
}, this));
|
|
208
257
|
}
|
|
209
258
|
|
|
210
259
|
} catch(err) {
|