mixpanel-browser 2.48.0 → 2.49.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/.eslintignore +2 -0
- package/CHANGELOG.md +10 -0
- package/README.md +1 -1
- package/bower.json +1 -1
- package/build.sh +12 -8
- package/dist/mixpanel-js-wrapper.js +247 -0
- package/dist/mixpanel-js-wrapper.min.js +5 -0
- package/dist/mixpanel.amd.js +106 -18
- package/dist/mixpanel.cjs.js +106 -18
- package/dist/mixpanel.globals.js +106 -18
- package/dist/mixpanel.min.js +105 -102
- package/dist/mixpanel.umd.js +106 -18
- package/doc/readme.io/javascript-full-api-reference.md +107 -1
- package/package.json +1 -1
- package/src/config.js +1 -1
- package/src/loaders/loader-globals.js +4 -0
- package/src/{loader-module.js → loaders/loader-module.js} +1 -1
- package/src/loaders/mixpanel-js-wrapper.js +143 -0
- package/src/loaders/mixpanel-js-wrapper.md +114 -0
- package/src/mixpanel-core.js +94 -13
- package/src/mixpanel-people.js +0 -1
- package/src/utils.js +11 -3
- package/src/loader-globals.js +0 -4
- /package/{mixpanel-jslib-snippet.js → src/loaders/mixpanel-jslib-snippet.js} +0 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Mixpanel JavaScript SDK wrapper for Google Tag Manager
|
|
2
|
+
The purpose of this wrapper is to provide a JavaScript interface for interacting with the `window.mixpanel` interface.
|
|
3
|
+
|
|
4
|
+
The wrapper has been designed with [Google Tag Manager](https://tagmanager.google.com) in mind. GTM's [custom templates](https://developers.google.com/tag-manager/templates) offer a way to deploy custom JavaScript without having to resort to Custom HTML tags and with the ability to craft a user interface for the scripts within Google Tag Manager.
|
|
5
|
+
|
|
6
|
+
However, one of the defining features of custom templates is their [sandboxed JavaScript API](https://developers.google.com/tag-manager/templates/sandboxed-javascript) inventory, which severely restricts what type of browser JavaScript can be executed in the template code.
|
|
7
|
+
|
|
8
|
+
Mixpanel's [JavaScript SDK](https://developer.mixpanel.com/docs/javascript-full-api-reference) makes use of JavaScript features which are not permitted by the sandbox of GTM's custom templates (e.g. object instances initiated with the `new` keyword, `this` and `prototype`, etc.).
|
|
9
|
+
|
|
10
|
+
Thus, in order to interact with Mixpanel's JavaScript SDK via Google Tag Manager's custom templates (or any other context where the aforementioned JavaScript features cannot be used), this wrapper is required. [The template loads this wrapper](https://github.com/mixpanel/mixpanel-gtm-template/blob/2f577d826acc7d96d138367db339035b8f9df359/src/template.tpl#L1383) in the sandboxed template code.
|
|
11
|
+
|
|
12
|
+
# Deployment
|
|
13
|
+
The wrapper is served by the Mixpanel CDN at https://cdn.mxpnl.com/libs/mixpanel-js-wrapper.js
|
|
14
|
+
|
|
15
|
+
# How it works
|
|
16
|
+
When the wrapper JavaScript is loaded in the browser, the global method `window._mixpanel()` is created for interacting with the wrapper.
|
|
17
|
+
|
|
18
|
+
This namespace includes all the methods supported by the [JavaScript SDK](https://developer.mixpanel.com/docs/javascript-full-api-reference) with some exceptions (see below). Each method can be invoked by passing the command name as the first argument of the call to `window._mixpanel()`.
|
|
19
|
+
|
|
20
|
+
If this command name is prefixed with `<string>.`, then `<string>` will be used as the [library name](https://developer.mixpanel.com/docs/javascript-full-api-reference#mixpanelinit). After the command, all additional arguments are processed as arguments to the command method itself.
|
|
21
|
+
|
|
22
|
+
For example, to dispatch an event named `Add To Cart` using a custom library name, you could use this command:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
window._mixpanel(
|
|
26
|
+
'myTracker.track', // Run the track command and utilize the library name "myTracker"
|
|
27
|
+
'Add To Cart', // Event name is the first argument to the track command
|
|
28
|
+
{product_id: 'shirt123'} // (optional) Event parameters are the second argument to the track command
|
|
29
|
+
);
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## `group`
|
|
33
|
+
[Link to specification](https://developer.mixpanel.com/docs/javascript-full-api-reference#mixpanelgroup)
|
|
34
|
+
|
|
35
|
+
Use this command to interact with group properties.
|
|
36
|
+
|
|
37
|
+
Syntax:
|
|
38
|
+
|
|
39
|
+
`window._mixpanel('<library_name.>group.<group_command>', ['<group_key>', '<group_id>'], <parameters>)`
|
|
40
|
+
|
|
41
|
+
Example:
|
|
42
|
+
```
|
|
43
|
+
// Union a property for a group
|
|
44
|
+
window._mixpanel(
|
|
45
|
+
'group.union',
|
|
46
|
+
['my_group_key', 'my_group_id'],
|
|
47
|
+
'location',
|
|
48
|
+
['San Francisco', 'London']
|
|
49
|
+
);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
| Parameter name | Description |
|
|
53
|
+
|----------------|-------------|
|
|
54
|
+
| `library_name` | (Optional) target a specific library/instance name with this command |
|
|
55
|
+
| `group_command` | (Required) one of `set`, `set_once`, `remove`, `union`, `unset` |
|
|
56
|
+
| `parameters` | All the parameters you want to submit to the `group` command. |
|
|
57
|
+
|
|
58
|
+
## `people`
|
|
59
|
+
[Link to specification](https://developer.mixpanel.com/docs/javascript-full-api-reference#mixpanelpeople)
|
|
60
|
+
|
|
61
|
+
Interact with the people analytics property.
|
|
62
|
+
|
|
63
|
+
Syntax:
|
|
64
|
+
|
|
65
|
+
`window._mixpanel('<library_name.>people.<people_command>', <parameters>)`
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
```
|
|
69
|
+
// Set the "gender" property "n/a"
|
|
70
|
+
window._mixpanel(
|
|
71
|
+
'people.set',
|
|
72
|
+
'gender',
|
|
73
|
+
'n/a'
|
|
74
|
+
);
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
| Parameter name | Description |
|
|
78
|
+
|----------------|-------------|
|
|
79
|
+
| `library_name` | (Optional) target a specific library/instance name with this command |
|
|
80
|
+
| `people_command` | (Required) one of `append`, `clear_charge`, `delete_user`, `increment`, `remove`, `set`, `set_once`, `track_charge`, `union`, `unset` |
|
|
81
|
+
| `parameters` | All the parameters you want to submit to the `people` command. |
|
|
82
|
+
|
|
83
|
+
## Other commands
|
|
84
|
+
|
|
85
|
+
All other commands can be sent to the `_mixpanel` interface like this:
|
|
86
|
+
|
|
87
|
+
`window._mixpanel('<library_name.><command_name>', <parameters>)`
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
window._mixpanel(
|
|
93
|
+
'my_mixpanel.register',
|
|
94
|
+
{'Account Type': 'Free'}
|
|
95
|
+
);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Exceptions
|
|
99
|
+
|
|
100
|
+
Because the wrapper only pipes commands to the actual `window.mixpanel` interface, the wrapper cannot be used for get-methods. So the following commands **are not** supported by the wrapper:
|
|
101
|
+
|
|
102
|
+
`get_config`
|
|
103
|
+
`get_distinct_id`
|
|
104
|
+
`get_group`
|
|
105
|
+
`get_property`
|
|
106
|
+
`has_opted_in_tracking`
|
|
107
|
+
`has_opted_out_tracking`
|
|
108
|
+
|
|
109
|
+
The following commands are also disabled due to not being relevant with the wrapper:
|
|
110
|
+
|
|
111
|
+
`push`
|
|
112
|
+
`init`
|
|
113
|
+
|
|
114
|
+
Initialization is done with the `window.mixpanel` interface directly, and `push` is already used by the wrapper to forward calls to the main interface.
|
package/src/mixpanel-core.js
CHANGED
|
@@ -106,10 +106,12 @@ var DEFAULT_CONFIG = {
|
|
|
106
106
|
'cookie_domain': '',
|
|
107
107
|
'cookie_name': '',
|
|
108
108
|
'loaded': NOOP_FUNC,
|
|
109
|
+
'mp_loader': null,
|
|
109
110
|
'track_marketing': true,
|
|
110
111
|
'track_pageview': false,
|
|
111
112
|
'skip_first_touch_marketing': false,
|
|
112
113
|
'store_google': true,
|
|
114
|
+
'stop_utm_persistence': false,
|
|
113
115
|
'save_referrer': true,
|
|
114
116
|
'test': false,
|
|
115
117
|
'verbose': false,
|
|
@@ -343,8 +345,9 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
343
345
|
}, '');
|
|
344
346
|
}
|
|
345
347
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
+
var track_pageview_option = this.get_config('track_pageview');
|
|
349
|
+
if (track_pageview_option) {
|
|
350
|
+
this._init_url_change_tracking(track_pageview_option);
|
|
348
351
|
}
|
|
349
352
|
};
|
|
350
353
|
|
|
@@ -353,13 +356,26 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
353
356
|
MixpanelLib.prototype._loaded = function() {
|
|
354
357
|
this.get_config('loaded')(this);
|
|
355
358
|
this._set_default_superprops();
|
|
359
|
+
this['people'].set_once(this['persistence'].get_referrer_info());
|
|
360
|
+
|
|
361
|
+
// The original 'store_google' functionality will be deprecated and the config will be
|
|
362
|
+
// used to clear previously managed UTM parameters from persistence.
|
|
363
|
+
// stop_utm_persistence is `false` by default now but will be default `true` in the future.
|
|
364
|
+
if (this.get_config('store_google') && this.get_config('stop_utm_persistence')) {
|
|
365
|
+
var utm_params = _.info.campaignParams(null);
|
|
366
|
+
_.each(utm_params, function(_utm_value, utm_key) {
|
|
367
|
+
// We need to unregister persisted UTM parameters so old values
|
|
368
|
+
// are not mixed with the new UTM parameters
|
|
369
|
+
this.unregister(utm_key);
|
|
370
|
+
}.bind(this));
|
|
371
|
+
}
|
|
356
372
|
};
|
|
357
373
|
|
|
358
374
|
// update persistence with info on referrer, UTM params, etc
|
|
359
375
|
MixpanelLib.prototype._set_default_superprops = function() {
|
|
360
376
|
this['persistence'].update_search_keyword(document.referrer);
|
|
361
|
-
if (this.get_config('store_google')) {
|
|
362
|
-
this.register(_.info.campaignParams()
|
|
377
|
+
if (this.get_config('store_google') && !this.get_config('stop_utm_persistence')) {
|
|
378
|
+
this.register(_.info.campaignParams());
|
|
363
379
|
}
|
|
364
380
|
if (this.get_config('save_referrer')) {
|
|
365
381
|
this['persistence'].update_referrer_info(document.referrer);
|
|
@@ -396,6 +412,55 @@ MixpanelLib.prototype._track_dom = function(DomClass, args) {
|
|
|
396
412
|
return dt.track.apply(dt, args);
|
|
397
413
|
};
|
|
398
414
|
|
|
415
|
+
MixpanelLib.prototype._init_url_change_tracking = function(track_pageview_option) {
|
|
416
|
+
var previous_tracked_url = '';
|
|
417
|
+
var tracked = this.track_pageview();
|
|
418
|
+
if (tracked) {
|
|
419
|
+
previous_tracked_url = _.info.currentUrl();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (_.include(['full-url', 'url-with-path-and-query-string', 'url-with-path'], track_pageview_option)) {
|
|
423
|
+
window.addEventListener('popstate', function() {
|
|
424
|
+
window.dispatchEvent(new Event('mp_locationchange'));
|
|
425
|
+
});
|
|
426
|
+
window.addEventListener('hashchange', function() {
|
|
427
|
+
window.dispatchEvent(new Event('mp_locationchange'));
|
|
428
|
+
});
|
|
429
|
+
var nativePushState = window.history.pushState;
|
|
430
|
+
if (typeof nativePushState === 'function') {
|
|
431
|
+
window.history.pushState = function(state, unused, url) {
|
|
432
|
+
nativePushState.call(window.history, state, unused, url);
|
|
433
|
+
window.dispatchEvent(new Event('mp_locationchange'));
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
var nativeReplaceState = window.history.replaceState;
|
|
437
|
+
if (typeof nativeReplaceState === 'function') {
|
|
438
|
+
window.history.replaceState = function(state, unused, url) {
|
|
439
|
+
nativeReplaceState.call(window.history, state, unused, url);
|
|
440
|
+
window.dispatchEvent(new Event('mp_locationchange'));
|
|
441
|
+
};
|
|
442
|
+
}
|
|
443
|
+
window.addEventListener('mp_locationchange', function() {
|
|
444
|
+
var current_url = _.info.currentUrl();
|
|
445
|
+
var should_track = false;
|
|
446
|
+
if (track_pageview_option === 'full-url') {
|
|
447
|
+
should_track = current_url !== previous_tracked_url;
|
|
448
|
+
} else if (track_pageview_option === 'url-with-path-and-query-string') {
|
|
449
|
+
should_track = current_url.split('#')[0] !== previous_tracked_url.split('#')[0];
|
|
450
|
+
} else if (track_pageview_option === 'url-with-path') {
|
|
451
|
+
should_track = current_url.split('#')[0].split('?')[0] !== previous_tracked_url.split('#')[0].split('?')[0];
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (should_track) {
|
|
455
|
+
var tracked = this.track_pageview();
|
|
456
|
+
if (tracked) {
|
|
457
|
+
previous_tracked_url = current_url;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}.bind(this));
|
|
461
|
+
}
|
|
462
|
+
};
|
|
463
|
+
|
|
399
464
|
/**
|
|
400
465
|
* _prepare_callback() should be called by callers of _send_request for use
|
|
401
466
|
* as the callback argument.
|
|
@@ -864,7 +929,7 @@ MixpanelLib.prototype.track = addOptOutCheckMixpanelLib(function(event_name, pro
|
|
|
864
929
|
// update properties with pageview info and super-properties
|
|
865
930
|
properties = _.extend(
|
|
866
931
|
{},
|
|
867
|
-
_.info.properties(),
|
|
932
|
+
_.info.properties({'mp_loader': this.get_config('mp_loader')}),
|
|
868
933
|
marketing_properties,
|
|
869
934
|
this['persistence'].properties(),
|
|
870
935
|
this.unpersisted_superprops,
|
|
@@ -1028,10 +1093,9 @@ MixpanelLib.prototype.get_group = function (group_key, group_id) {
|
|
|
1028
1093
|
|
|
1029
1094
|
/**
|
|
1030
1095
|
* Track a default Mixpanel page view event, which includes extra default event properties to
|
|
1031
|
-
* improve page view data.
|
|
1032
|
-
* may be turned on for tracking page loads automatically.
|
|
1096
|
+
* improve page view data.
|
|
1033
1097
|
*
|
|
1034
|
-
* ### Usage
|
|
1098
|
+
* ### Usage:
|
|
1035
1099
|
*
|
|
1036
1100
|
* // track a default $mp_web_page_view event
|
|
1037
1101
|
* mixpanel.track_pageview();
|
|
@@ -1048,6 +1112,23 @@ MixpanelLib.prototype.get_group = function (group_key, group_id) {
|
|
|
1048
1112
|
* // views on different products or internal applications that are considered completely separate
|
|
1049
1113
|
* mixpanel.track_pageview({'page': 'customer-search'}, {'event_name': '[internal] Admin Page View'});
|
|
1050
1114
|
*
|
|
1115
|
+
* ### Notes:
|
|
1116
|
+
*
|
|
1117
|
+
* The `config.track_pageview` option for <a href="#mixpanelinit">mixpanel.init()</a>
|
|
1118
|
+
* may be turned on for tracking page loads automatically.
|
|
1119
|
+
*
|
|
1120
|
+
* // track only page loads
|
|
1121
|
+
* mixpanel.init(PROJECT_TOKEN, {track_pageview: true});
|
|
1122
|
+
*
|
|
1123
|
+
* // track when the URL changes in any manner
|
|
1124
|
+
* mixpanel.init(PROJECT_TOKEN, {track_pageview: 'full-url'});
|
|
1125
|
+
*
|
|
1126
|
+
* // track when the URL changes, ignoring any changes in the hash part
|
|
1127
|
+
* mixpanel.init(PROJECT_TOKEN, {track_pageview: 'url-with-path-and-query-string'});
|
|
1128
|
+
*
|
|
1129
|
+
* // track when the path changes, ignoring any query parameter or hash changes
|
|
1130
|
+
* mixpanel.init(PROJECT_TOKEN, {track_pageview: 'url-with-path'});
|
|
1131
|
+
*
|
|
1051
1132
|
* @param {Object} [properties] An optional set of additional properties to send with the page view event
|
|
1052
1133
|
* @param {Object} [options] Page view tracking options
|
|
1053
1134
|
* @param {String} [options.event_name] - Alternate name for the tracking event
|
|
@@ -1798,7 +1879,7 @@ MixpanelLib.prototype._gdpr_call_func = function(func, options) {
|
|
|
1798
1879
|
/**
|
|
1799
1880
|
* Opt the user in to data tracking and cookies/localstorage for this Mixpanel instance
|
|
1800
1881
|
*
|
|
1801
|
-
* ### Usage
|
|
1882
|
+
* ### Usage:
|
|
1802
1883
|
*
|
|
1803
1884
|
* // opt user in
|
|
1804
1885
|
* mixpanel.opt_in_tracking();
|
|
@@ -1838,7 +1919,7 @@ MixpanelLib.prototype.opt_in_tracking = function(options) {
|
|
|
1838
1919
|
/**
|
|
1839
1920
|
* Opt the user out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
1840
1921
|
*
|
|
1841
|
-
* ### Usage
|
|
1922
|
+
* ### Usage:
|
|
1842
1923
|
*
|
|
1843
1924
|
* // opt user out
|
|
1844
1925
|
* mixpanel.opt_out_tracking();
|
|
@@ -1879,7 +1960,7 @@ MixpanelLib.prototype.opt_out_tracking = function(options) {
|
|
|
1879
1960
|
/**
|
|
1880
1961
|
* Check whether the user has opted in to data tracking and cookies/localstorage for this Mixpanel instance
|
|
1881
1962
|
*
|
|
1882
|
-
* ### Usage
|
|
1963
|
+
* ### Usage:
|
|
1883
1964
|
*
|
|
1884
1965
|
* var has_opted_in = mixpanel.has_opted_in_tracking();
|
|
1885
1966
|
* // use has_opted_in value
|
|
@@ -1896,7 +1977,7 @@ MixpanelLib.prototype.has_opted_in_tracking = function(options) {
|
|
|
1896
1977
|
/**
|
|
1897
1978
|
* Check whether the user has opted out of data tracking and cookies/localstorage for this Mixpanel instance
|
|
1898
1979
|
*
|
|
1899
|
-
* ### Usage
|
|
1980
|
+
* ### Usage:
|
|
1900
1981
|
*
|
|
1901
1982
|
* var has_opted_out = mixpanel.has_opted_out_tracking();
|
|
1902
1983
|
* // use has_opted_out value
|
|
@@ -1913,7 +1994,7 @@ MixpanelLib.prototype.has_opted_out_tracking = function(options) {
|
|
|
1913
1994
|
/**
|
|
1914
1995
|
* Clear the user's opt in/out status of data tracking and cookies/localstorage for this Mixpanel instance
|
|
1915
1996
|
*
|
|
1916
|
-
* ### Usage
|
|
1997
|
+
* ### Usage:
|
|
1917
1998
|
*
|
|
1918
1999
|
* // clear user's opt-in/out status
|
|
1919
2000
|
* mixpanel.clear_opt_in_out_tracking();
|
package/src/mixpanel-people.js
CHANGED
|
@@ -57,7 +57,6 @@ MixpanelPeople.prototype.set = addOptOutCheckMixpanelPeople(function(prop, to, c
|
|
|
57
57
|
data[SET_ACTION] = _.extend(
|
|
58
58
|
{},
|
|
59
59
|
_.info.people_properties(),
|
|
60
|
-
this._mixpanel['persistence'].get_referrer_info(),
|
|
61
60
|
data[SET_ACTION]
|
|
62
61
|
);
|
|
63
62
|
return this._send_request(data, callback);
|
package/src/utils.js
CHANGED
|
@@ -899,6 +899,7 @@ _.UUID = (function() {
|
|
|
899
899
|
// sending false tracking data
|
|
900
900
|
var BLOCKED_UA_STRS = [
|
|
901
901
|
'ahrefsbot',
|
|
902
|
+
'ahrefssiteaudit',
|
|
902
903
|
'baiduspider',
|
|
903
904
|
'bingbot',
|
|
904
905
|
'bingpreview',
|
|
@@ -1619,7 +1620,14 @@ _.info = {
|
|
|
1619
1620
|
return '';
|
|
1620
1621
|
},
|
|
1621
1622
|
|
|
1622
|
-
|
|
1623
|
+
currentUrl: function() {
|
|
1624
|
+
return win.location.href;
|
|
1625
|
+
},
|
|
1626
|
+
|
|
1627
|
+
properties: function(extra_props) {
|
|
1628
|
+
if (typeof extra_props !== 'object') {
|
|
1629
|
+
extra_props = {};
|
|
1630
|
+
}
|
|
1623
1631
|
return _.extend(_.strip_empty_properties({
|
|
1624
1632
|
'$os': _.info.os(),
|
|
1625
1633
|
'$browser': _.info.browser(userAgent, navigator.vendor, windowOpera),
|
|
@@ -1627,7 +1635,7 @@ _.info = {
|
|
|
1627
1635
|
'$referring_domain': _.info.referringDomain(document.referrer),
|
|
1628
1636
|
'$device': _.info.device(userAgent)
|
|
1629
1637
|
}), {
|
|
1630
|
-
'$current_url':
|
|
1638
|
+
'$current_url': _.info.currentUrl(),
|
|
1631
1639
|
'$browser_version': _.info.browserVersion(userAgent, navigator.vendor, windowOpera),
|
|
1632
1640
|
'$screen_height': screen.height,
|
|
1633
1641
|
'$screen_width': screen.width,
|
|
@@ -1635,7 +1643,7 @@ _.info = {
|
|
|
1635
1643
|
'$lib_version': Config.LIB_VERSION,
|
|
1636
1644
|
'$insert_id': cheap_guid(),
|
|
1637
1645
|
'time': _.timestamp() / 1000 // epoch time in seconds
|
|
1638
|
-
});
|
|
1646
|
+
}, _.strip_empty_properties(extra_props));
|
|
1639
1647
|
},
|
|
1640
1648
|
|
|
1641
1649
|
people_properties: function() {
|
package/src/loader-globals.js
DELETED
|
File without changes
|