mixpanel-browser 2.72.0 → 2.73.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 -0
- package/dist/mixpanel-core.cjs.d.ts +37 -3
- package/dist/mixpanel-core.cjs.js +130 -12
- package/dist/mixpanel-recorder.js +4 -2
- package/dist/mixpanel-recorder.min.js +1 -1
- package/dist/mixpanel-recorder.min.js.map +1 -1
- package/dist/mixpanel-with-async-recorder.cjs.d.ts +37 -3
- package/dist/mixpanel-with-async-recorder.cjs.js +130 -12
- package/dist/mixpanel-with-recorder.d.ts +37 -3
- package/dist/mixpanel-with-recorder.js +130 -12
- package/dist/mixpanel-with-recorder.min.d.ts +37 -3
- package/dist/mixpanel-with-recorder.min.js +1 -1
- package/dist/mixpanel.amd.d.ts +37 -3
- package/dist/mixpanel.amd.js +130 -12
- package/dist/mixpanel.cjs.d.ts +37 -3
- package/dist/mixpanel.cjs.js +130 -12
- package/dist/mixpanel.globals.js +130 -12
- package/dist/mixpanel.min.js +171 -169
- package/dist/mixpanel.module.d.ts +37 -3
- package/dist/mixpanel.module.js +130 -12
- package/dist/mixpanel.umd.d.ts +37 -3
- package/dist/mixpanel.umd.js +130 -12
- package/package.json +1 -1
- package/src/config.js +1 -1
- package/src/index.d.ts +37 -3
- package/src/mixpanel-core.js +126 -10
- package/src/window.js +3 -1
- package/.claude/settings.local.json +0 -9
package/dist/mixpanel.umd.js
CHANGED
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
screen: { width: 0, height: 0 },
|
|
22
22
|
location: loc,
|
|
23
23
|
addEventListener: function() {},
|
|
24
|
-
removeEventListener: function() {}
|
|
24
|
+
removeEventListener: function() {},
|
|
25
|
+
dispatchEvent: function() {},
|
|
26
|
+
CustomEvent: function () {}
|
|
25
27
|
};
|
|
26
28
|
} else {
|
|
27
29
|
win = window;
|
|
@@ -14536,7 +14538,7 @@
|
|
|
14536
14538
|
|
|
14537
14539
|
var Config = {
|
|
14538
14540
|
DEBUG: false,
|
|
14539
|
-
LIB_VERSION: '2.
|
|
14541
|
+
LIB_VERSION: '2.73.0'
|
|
14540
14542
|
};
|
|
14541
14543
|
|
|
14542
14544
|
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
@@ -21804,8 +21806,6 @@
|
|
|
21804
21806
|
var INIT_MODULE = 0;
|
|
21805
21807
|
var INIT_SNIPPET = 1;
|
|
21806
21808
|
|
|
21807
|
-
var IDENTITY_FUNC = function(x) {return x;};
|
|
21808
|
-
|
|
21809
21809
|
/** @const */ var PRIMARY_INSTANCE_NAME = 'mixpanel';
|
|
21810
21810
|
/** @const */ var PAYLOAD_TYPE_BASE64 = 'base64';
|
|
21811
21811
|
/** @const */ var PAYLOAD_TYPE_JSON = 'json';
|
|
@@ -21971,6 +21971,17 @@
|
|
|
21971
21971
|
// global debug to be true
|
|
21972
21972
|
Config.DEBUG = Config.DEBUG || instance.get_config('debug');
|
|
21973
21973
|
|
|
21974
|
+
var source = init_type === INIT_MODULE ? 'module' : 'snippet';
|
|
21975
|
+
win.dispatchEvent(new win.CustomEvent('$mp_sdk_to_extension_event', {
|
|
21976
|
+
'detail': {
|
|
21977
|
+
'instance': instance,
|
|
21978
|
+
'source': source,
|
|
21979
|
+
'token': token,
|
|
21980
|
+
'name': name,
|
|
21981
|
+
'info': _.info
|
|
21982
|
+
}
|
|
21983
|
+
}));
|
|
21984
|
+
|
|
21974
21985
|
// if target is not defined, we called init after the lib already
|
|
21975
21986
|
// loaded, so there won't be an array of things to execute
|
|
21976
21987
|
if (!_.isUndefined(target) && _.isArray(target)) {
|
|
@@ -22041,6 +22052,8 @@
|
|
|
22041
22052
|
}
|
|
22042
22053
|
}
|
|
22043
22054
|
|
|
22055
|
+
this.hooks = {};
|
|
22056
|
+
|
|
22044
22057
|
this.set_config(_.extend({}, DEFAULT_CONFIG, variable_features, config, {
|
|
22045
22058
|
'name': name,
|
|
22046
22059
|
'token': token,
|
|
@@ -22641,7 +22654,12 @@
|
|
|
22641
22654
|
);
|
|
22642
22655
|
}, this),
|
|
22643
22656
|
beforeSendHook: _.bind(function(item) {
|
|
22644
|
-
|
|
22657
|
+
var ret = this._run_hook('before_send_' + attrs.type, item);
|
|
22658
|
+
if (ret) {
|
|
22659
|
+
return ret[0];
|
|
22660
|
+
} else {
|
|
22661
|
+
return null;
|
|
22662
|
+
}
|
|
22645
22663
|
}, this),
|
|
22646
22664
|
stopAllBatchingFunc: _.bind(this.stop_batch_senders, this),
|
|
22647
22665
|
usePersistence: true,
|
|
@@ -22734,6 +22752,9 @@
|
|
|
22734
22752
|
var send_request_immediately = _.bind(function() {
|
|
22735
22753
|
if (!send_request_options.skip_hooks) {
|
|
22736
22754
|
truncated_data = this._run_hook('before_send_' + options.type, truncated_data);
|
|
22755
|
+
if (truncated_data) {
|
|
22756
|
+
truncated_data = truncated_data[0];
|
|
22757
|
+
}
|
|
22737
22758
|
}
|
|
22738
22759
|
if (truncated_data) {
|
|
22739
22760
|
console$1.log('MIXPANEL REQUEST:');
|
|
@@ -22788,6 +22809,17 @@
|
|
|
22788
22809
|
* with the tracking payload sent to the API server is returned; otherwise false.
|
|
22789
22810
|
*/
|
|
22790
22811
|
MixpanelLib.prototype.track = addOptOutCheckMixpanelLib(function(event_name, properties, options, callback) {
|
|
22812
|
+
var ret;
|
|
22813
|
+
if (!(options && options.skip_hooks)) {
|
|
22814
|
+
ret = this._run_hook('before_track', event_name, properties);
|
|
22815
|
+
if (ret === null) {
|
|
22816
|
+
return;
|
|
22817
|
+
} else {
|
|
22818
|
+
event_name = ret[0];
|
|
22819
|
+
properties = ret[1];
|
|
22820
|
+
}
|
|
22821
|
+
}
|
|
22822
|
+
|
|
22791
22823
|
if (!callback && typeof options === 'function') {
|
|
22792
22824
|
callback = options;
|
|
22793
22825
|
options = null;
|
|
@@ -22857,7 +22889,7 @@
|
|
|
22857
22889
|
'event': event_name,
|
|
22858
22890
|
'properties': properties
|
|
22859
22891
|
};
|
|
22860
|
-
|
|
22892
|
+
ret = this._track_or_batch({
|
|
22861
22893
|
type: 'events',
|
|
22862
22894
|
data: data,
|
|
22863
22895
|
endpoint: this.get_api_host('events') + '/' + this.get_config('api_routes')['track'],
|
|
@@ -23203,6 +23235,14 @@
|
|
|
23203
23235
|
* @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
|
|
23204
23236
|
*/
|
|
23205
23237
|
MixpanelLib.prototype.register = function(props, days_or_options) {
|
|
23238
|
+
var ret = this._run_hook('before_register', props, days_or_options);
|
|
23239
|
+
if (ret === null) {
|
|
23240
|
+
return;
|
|
23241
|
+
} else {
|
|
23242
|
+
props = ret[0];
|
|
23243
|
+
days_or_options = ret[1];
|
|
23244
|
+
}
|
|
23245
|
+
|
|
23206
23246
|
var options = options_for_register(days_or_options);
|
|
23207
23247
|
if (options['persistent']) {
|
|
23208
23248
|
this['persistence'].register(props, options['days']);
|
|
@@ -23239,6 +23279,15 @@
|
|
|
23239
23279
|
* @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
|
|
23240
23280
|
*/
|
|
23241
23281
|
MixpanelLib.prototype.register_once = function(props, default_value, days_or_options) {
|
|
23282
|
+
var ret = this._run_hook('before_register_once', props, default_value, days_or_options);
|
|
23283
|
+
if (ret === null) {
|
|
23284
|
+
return;
|
|
23285
|
+
} else {
|
|
23286
|
+
props = ret[0];
|
|
23287
|
+
default_value = ret[1];
|
|
23288
|
+
days_or_options = ret[2];
|
|
23289
|
+
}
|
|
23290
|
+
|
|
23242
23291
|
var options = options_for_register(days_or_options);
|
|
23243
23292
|
if (options['persistent']) {
|
|
23244
23293
|
this['persistence'].register_once(props, default_value, options['days']);
|
|
@@ -23262,6 +23311,14 @@
|
|
|
23262
23311
|
* @param {boolean} [options.persistent=true] - whether to look in persistent storage (cookie/localStorage)
|
|
23263
23312
|
*/
|
|
23264
23313
|
MixpanelLib.prototype.unregister = function(property, options) {
|
|
23314
|
+
var ret = this._run_hook('before_unregister', property, options);
|
|
23315
|
+
if (ret === null) {
|
|
23316
|
+
return;
|
|
23317
|
+
} else {
|
|
23318
|
+
property = ret[0];
|
|
23319
|
+
options = ret[1];
|
|
23320
|
+
}
|
|
23321
|
+
|
|
23265
23322
|
options = options_for_register(options);
|
|
23266
23323
|
if (options['persistent']) {
|
|
23267
23324
|
this['persistence'].unregister(property);
|
|
@@ -23310,6 +23367,13 @@
|
|
|
23310
23367
|
// _set_once_callback:function A callback to be run if and when the People set_once queue is flushed
|
|
23311
23368
|
// _union_callback:function A callback to be run if and when the People union queue is flushed
|
|
23312
23369
|
// _unset_callback:function A callback to be run if and when the People unset queue is flushed
|
|
23370
|
+
var ret = this._run_hook('before_identify', new_distinct_id);
|
|
23371
|
+
|
|
23372
|
+
if (ret === null) {
|
|
23373
|
+
return -1;
|
|
23374
|
+
} else {
|
|
23375
|
+
new_distinct_id = ret[0];
|
|
23376
|
+
}
|
|
23313
23377
|
|
|
23314
23378
|
var previous_distinct_id = this.get_distinct_id();
|
|
23315
23379
|
if (new_distinct_id && previous_distinct_id !== new_distinct_id) {
|
|
@@ -23634,6 +23698,25 @@
|
|
|
23634
23698
|
if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
|
|
23635
23699
|
this.autocapture.init();
|
|
23636
23700
|
}
|
|
23701
|
+
|
|
23702
|
+
if (_.isObject(config['hooks'])) {
|
|
23703
|
+
this.hooks = {};
|
|
23704
|
+
_.each(config['hooks'], function(hook_value, hook_name) {
|
|
23705
|
+
if (_.isFunction(hook_value)) {
|
|
23706
|
+
this.hooks[hook_name] = [hook_value];
|
|
23707
|
+
} else if (_.isArray(hook_value)) {
|
|
23708
|
+
this.hooks[hook_name] = [];
|
|
23709
|
+
for (var i = 0; i < hook_value.length; i++) {
|
|
23710
|
+
if (!_.isFunction(hook_value[i])) {
|
|
23711
|
+
console$1.critical('Invalid hook added. Hook is not a function');
|
|
23712
|
+
}
|
|
23713
|
+
this.hooks[hook_name].push(hook_value[i]);
|
|
23714
|
+
}
|
|
23715
|
+
} else {
|
|
23716
|
+
console$1.critical('Invalid hooks added. Ensure that the hook values passed into config.hooks are functions or arrays of functions.');
|
|
23717
|
+
}
|
|
23718
|
+
}, this);
|
|
23719
|
+
}
|
|
23637
23720
|
}
|
|
23638
23721
|
};
|
|
23639
23722
|
|
|
@@ -23651,12 +23734,26 @@
|
|
|
23651
23734
|
* @returns {any|null} return value of user-provided hook, or null if nothing was returned
|
|
23652
23735
|
*/
|
|
23653
23736
|
MixpanelLib.prototype._run_hook = function(hook_name) {
|
|
23654
|
-
var
|
|
23655
|
-
|
|
23656
|
-
|
|
23657
|
-
|
|
23658
|
-
|
|
23659
|
-
|
|
23737
|
+
var hook_data = slice.call(arguments, 1);
|
|
23738
|
+
_.each(this.hooks[hook_name], function(hook) {
|
|
23739
|
+
if (hook_data === null) {
|
|
23740
|
+
return null;
|
|
23741
|
+
}
|
|
23742
|
+
|
|
23743
|
+
var ret = hook.apply(this, hook_data);
|
|
23744
|
+
|
|
23745
|
+
if (typeof ret === 'undefined') {
|
|
23746
|
+
this.report_error(hook_name + ' hook did not return a valid value');
|
|
23747
|
+
hook_data = null;
|
|
23748
|
+
} else {
|
|
23749
|
+
if (!_.isArray(ret)) {
|
|
23750
|
+
ret = [ret];
|
|
23751
|
+
}
|
|
23752
|
+
hook_data.splice.apply(hook_data, [0, ret.length].concat(ret));
|
|
23753
|
+
}
|
|
23754
|
+
}, this);
|
|
23755
|
+
|
|
23756
|
+
return hook_data;
|
|
23660
23757
|
};
|
|
23661
23758
|
|
|
23662
23759
|
/**
|
|
@@ -23967,6 +24064,25 @@
|
|
|
23967
24064
|
}
|
|
23968
24065
|
};
|
|
23969
24066
|
|
|
24067
|
+
MixpanelLib.prototype.add_hook = function(hook_name, hook_fn) {
|
|
24068
|
+
if (!this.hooks[hook_name]) {
|
|
24069
|
+
this.hooks[hook_name] = [];
|
|
24070
|
+
}
|
|
24071
|
+
this.hooks[hook_name].push(hook_fn);
|
|
24072
|
+
};
|
|
24073
|
+
|
|
24074
|
+
MixpanelLib.prototype.remove_hook = function(hook_name, hook_fn) {
|
|
24075
|
+
var fn_index;
|
|
24076
|
+
if (this.hooks[hook_name]) {
|
|
24077
|
+
fn_index = this.hooks[hook_name].indexOf(hook_fn);
|
|
24078
|
+
if (fn_index !== -1) {
|
|
24079
|
+
this.hooks[hook_name].splice(fn_index, 1);
|
|
24080
|
+
} else {
|
|
24081
|
+
console$1.log('remove_hook failed. Matching hook was not found');
|
|
24082
|
+
}
|
|
24083
|
+
}
|
|
24084
|
+
};
|
|
24085
|
+
|
|
23970
24086
|
// EXPORTS (for closure compiler)
|
|
23971
24087
|
|
|
23972
24088
|
// MixpanelLib Exports
|
|
@@ -23999,6 +24115,8 @@
|
|
|
23999
24115
|
MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
|
|
24000
24116
|
MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
|
|
24001
24117
|
MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
|
|
24118
|
+
MixpanelLib.prototype['add_hook'] = MixpanelLib.prototype.add_hook;
|
|
24119
|
+
MixpanelLib.prototype['remove_hook'] = MixpanelLib.prototype.remove_hook;
|
|
24002
24120
|
MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
|
|
24003
24121
|
MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
|
|
24004
24122
|
MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
|
package/package.json
CHANGED
package/src/config.js
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export type Persistence = "cookie" | "localStorage";
|
|
|
2
2
|
|
|
3
3
|
export type ApiPayloadFormat = "base64" | "json";
|
|
4
4
|
|
|
5
|
-
export type PushItem = Array<string | Dict>;
|
|
5
|
+
export type PushItem = Array<string | Dict | ((this: Mixpanel) => void)>;
|
|
6
6
|
|
|
7
7
|
export type Query = string | Element | Element[];
|
|
8
8
|
|
|
@@ -155,6 +155,11 @@ export interface FlagsConfig {
|
|
|
155
155
|
context: Dict;
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
export interface BeforeSendHookPayload {
|
|
159
|
+
event: string;
|
|
160
|
+
properties: Record<string, any>;
|
|
161
|
+
}
|
|
162
|
+
|
|
158
163
|
export interface Config {
|
|
159
164
|
api_host: string;
|
|
160
165
|
api_routes: {
|
|
@@ -167,10 +172,13 @@ export interface Config {
|
|
|
167
172
|
app_host: string;
|
|
168
173
|
api_payload_format: ApiPayloadFormat;
|
|
169
174
|
autotrack: boolean;
|
|
175
|
+
batch_autostart: boolean;
|
|
176
|
+
batch_requests: boolean;
|
|
170
177
|
cdn: string;
|
|
171
178
|
cookie_domain: string;
|
|
172
179
|
cross_site_cookie: boolean;
|
|
173
180
|
cross_subdomain_cookie: boolean;
|
|
181
|
+
error_reporter: (msg: string, err?: Error) => void;
|
|
174
182
|
flags: boolean | FlagsConfig;
|
|
175
183
|
persistence: Persistence;
|
|
176
184
|
persistence_name: string;
|
|
@@ -207,10 +215,10 @@ export interface Config {
|
|
|
207
215
|
inapp_protocol: string;
|
|
208
216
|
inapp_link_new_window: boolean;
|
|
209
217
|
ignore_dnt: boolean;
|
|
210
|
-
batch_requests: boolean;
|
|
211
218
|
batch_size: number;
|
|
212
219
|
batch_flush_interval_ms: number;
|
|
213
220
|
batch_request_timeout_ms: number;
|
|
221
|
+
recorder_src: string;
|
|
214
222
|
record_block_class: string | RegExp;
|
|
215
223
|
record_block_selector: string;
|
|
216
224
|
record_collect_fonts: boolean;
|
|
@@ -223,6 +231,29 @@ export interface Config {
|
|
|
223
231
|
record_sessions_percent: number;
|
|
224
232
|
record_canvas: boolean;
|
|
225
233
|
record_heatmap_data: boolean;
|
|
234
|
+
hooks: {
|
|
235
|
+
before_identify?: (new_distinct_id: string) => string | null;
|
|
236
|
+
before_register?: (
|
|
237
|
+
props: Dict,
|
|
238
|
+
days_or_options?: number | Partial<RegisterOptions>
|
|
239
|
+
) => Dict | Array<Dict | number | Partial<RegisterOptions>> | null;
|
|
240
|
+
before_register_once?: (
|
|
241
|
+
props: Dict,
|
|
242
|
+
default_value?: any,
|
|
243
|
+
days_or_options?: number | Partial<RegisterOptions>
|
|
244
|
+
) => Dict | Array<any | Dict | number | Partial<RegisterOptions>> | null;
|
|
245
|
+
before_send_events?: (
|
|
246
|
+
event: BeforeSendHookPayload
|
|
247
|
+
) => BeforeSendHookPayload | null;
|
|
248
|
+
before_track?: (
|
|
249
|
+
event_name: string,
|
|
250
|
+
properties: Dict
|
|
251
|
+
) => string | Array<string | Dict> | null;
|
|
252
|
+
before_unregister?: (
|
|
253
|
+
property: string,
|
|
254
|
+
options?: Partial<RegisterOptions>
|
|
255
|
+
) => string | Partial<RegisterOptions> | null;
|
|
256
|
+
};
|
|
226
257
|
}
|
|
227
258
|
|
|
228
259
|
export type VerboseResponse =
|
|
@@ -323,10 +354,11 @@ export interface Mixpanel {
|
|
|
323
354
|
get_distinct_id(): any;
|
|
324
355
|
get_group(group_key: string, group_id: string): Group;
|
|
325
356
|
get_property(property_name: string): any;
|
|
357
|
+
get_session_replay_url(): string;
|
|
326
358
|
has_opted_in_tracking(options?: Partial<HasOptedInOutOptions>): boolean;
|
|
327
359
|
has_opted_out_tracking(options?: Partial<HasOptedInOutOptions>): boolean;
|
|
328
360
|
identify(unique_id?: string): any;
|
|
329
|
-
init(token: string, config: Partial<Config>, name
|
|
361
|
+
init(token: string, config: Partial<Config>, name?: string): Mixpanel;
|
|
330
362
|
opt_in_tracking(options?: Partial<InTrackingOptions>): void;
|
|
331
363
|
opt_out_tracking(options?: Partial<OutTrackingOptions>): void;
|
|
332
364
|
push(item: PushItem): void;
|
|
@@ -351,6 +383,7 @@ export interface Mixpanel {
|
|
|
351
383
|
group_ids: string | string[] | number | number[],
|
|
352
384
|
callback?: Callback
|
|
353
385
|
): void;
|
|
386
|
+
start_batch_senders(): void;
|
|
354
387
|
time_event(event_name: string): void;
|
|
355
388
|
track(
|
|
356
389
|
event_name: string,
|
|
@@ -380,6 +413,7 @@ export interface Mixpanel {
|
|
|
380
413
|
): void;
|
|
381
414
|
unregister(property: string, options?: Partial<RegisterOptions>): void;
|
|
382
415
|
people: People;
|
|
416
|
+
start_batch_senders(): void;
|
|
383
417
|
start_session_recording(): void;
|
|
384
418
|
stop_session_recording(): void;
|
|
385
419
|
get_session_recording_properties(): { $mp_replay_id?: string } | {};
|
package/src/mixpanel-core.js
CHANGED
|
@@ -57,8 +57,6 @@ var mixpanel_master; // main mixpanel instance / object
|
|
|
57
57
|
var INIT_MODULE = 0;
|
|
58
58
|
var INIT_SNIPPET = 1;
|
|
59
59
|
|
|
60
|
-
var IDENTITY_FUNC = function(x) {return x;};
|
|
61
|
-
|
|
62
60
|
/** @const */ var PRIMARY_INSTANCE_NAME = 'mixpanel';
|
|
63
61
|
/** @const */ var PAYLOAD_TYPE_BASE64 = 'base64';
|
|
64
62
|
/** @const */ var PAYLOAD_TYPE_JSON = 'json';
|
|
@@ -224,6 +222,17 @@ var create_mplib = function(token, config, name) {
|
|
|
224
222
|
// global debug to be true
|
|
225
223
|
Config.DEBUG = Config.DEBUG || instance.get_config('debug');
|
|
226
224
|
|
|
225
|
+
var source = init_type === INIT_MODULE ? 'module' : 'snippet';
|
|
226
|
+
window.dispatchEvent(new window.CustomEvent('$mp_sdk_to_extension_event', {
|
|
227
|
+
'detail': {
|
|
228
|
+
'instance': instance,
|
|
229
|
+
'source': source,
|
|
230
|
+
'token': token,
|
|
231
|
+
'name': name,
|
|
232
|
+
'info': _.info
|
|
233
|
+
}
|
|
234
|
+
}));
|
|
235
|
+
|
|
227
236
|
// if target is not defined, we called init after the lib already
|
|
228
237
|
// loaded, so there won't be an array of things to execute
|
|
229
238
|
if (!_.isUndefined(target) && _.isArray(target)) {
|
|
@@ -294,6 +303,8 @@ MixpanelLib.prototype._init = function(token, config, name) {
|
|
|
294
303
|
}
|
|
295
304
|
}
|
|
296
305
|
|
|
306
|
+
this.hooks = {};
|
|
307
|
+
|
|
297
308
|
this.set_config(_.extend({}, DEFAULT_CONFIG, variable_features, config, {
|
|
298
309
|
'name': name,
|
|
299
310
|
'token': token,
|
|
@@ -894,7 +905,12 @@ MixpanelLib.prototype.init_batchers = function() {
|
|
|
894
905
|
);
|
|
895
906
|
}, this),
|
|
896
907
|
beforeSendHook: _.bind(function(item) {
|
|
897
|
-
|
|
908
|
+
var ret = this._run_hook('before_send_' + attrs.type, item);
|
|
909
|
+
if (ret) {
|
|
910
|
+
return ret[0];
|
|
911
|
+
} else {
|
|
912
|
+
return null;
|
|
913
|
+
}
|
|
898
914
|
}, this),
|
|
899
915
|
stopAllBatchingFunc: _.bind(this.stop_batch_senders, this),
|
|
900
916
|
usePersistence: true,
|
|
@@ -987,6 +1003,9 @@ MixpanelLib.prototype._track_or_batch = function(options, callback) {
|
|
|
987
1003
|
var send_request_immediately = _.bind(function() {
|
|
988
1004
|
if (!send_request_options.skip_hooks) {
|
|
989
1005
|
truncated_data = this._run_hook('before_send_' + options.type, truncated_data);
|
|
1006
|
+
if (truncated_data) {
|
|
1007
|
+
truncated_data = truncated_data[0];
|
|
1008
|
+
}
|
|
990
1009
|
}
|
|
991
1010
|
if (truncated_data) {
|
|
992
1011
|
console.log('MIXPANEL REQUEST:');
|
|
@@ -1041,6 +1060,17 @@ MixpanelLib.prototype._track_or_batch = function(options, callback) {
|
|
|
1041
1060
|
* with the tracking payload sent to the API server is returned; otherwise false.
|
|
1042
1061
|
*/
|
|
1043
1062
|
MixpanelLib.prototype.track = addOptOutCheckMixpanelLib(function(event_name, properties, options, callback) {
|
|
1063
|
+
var ret;
|
|
1064
|
+
if (!(options && options.skip_hooks)) {
|
|
1065
|
+
ret = this._run_hook('before_track', event_name, properties);
|
|
1066
|
+
if (ret === null) {
|
|
1067
|
+
return;
|
|
1068
|
+
} else {
|
|
1069
|
+
event_name = ret[0];
|
|
1070
|
+
properties = ret[1];
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1044
1074
|
if (!callback && typeof options === 'function') {
|
|
1045
1075
|
callback = options;
|
|
1046
1076
|
options = null;
|
|
@@ -1110,7 +1140,7 @@ MixpanelLib.prototype.track = addOptOutCheckMixpanelLib(function(event_name, pro
|
|
|
1110
1140
|
'event': event_name,
|
|
1111
1141
|
'properties': properties
|
|
1112
1142
|
};
|
|
1113
|
-
|
|
1143
|
+
ret = this._track_or_batch({
|
|
1114
1144
|
type: 'events',
|
|
1115
1145
|
data: data,
|
|
1116
1146
|
endpoint: this.get_api_host('events') + '/' + this.get_config('api_routes')['track'],
|
|
@@ -1456,6 +1486,14 @@ var options_for_register = function(days_or_options) {
|
|
|
1456
1486
|
* @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
|
|
1457
1487
|
*/
|
|
1458
1488
|
MixpanelLib.prototype.register = function(props, days_or_options) {
|
|
1489
|
+
var ret = this._run_hook('before_register', props, days_or_options);
|
|
1490
|
+
if (ret === null) {
|
|
1491
|
+
return;
|
|
1492
|
+
} else {
|
|
1493
|
+
props = ret[0];
|
|
1494
|
+
days_or_options = ret[1];
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1459
1497
|
var options = options_for_register(days_or_options);
|
|
1460
1498
|
if (options['persistent']) {
|
|
1461
1499
|
this['persistence'].register(props, options['days']);
|
|
@@ -1492,6 +1530,15 @@ MixpanelLib.prototype.register = function(props, days_or_options) {
|
|
|
1492
1530
|
* @param {boolean} [days_or_options.persistent=true] - whether to put in persistent storage (cookie/localStorage)
|
|
1493
1531
|
*/
|
|
1494
1532
|
MixpanelLib.prototype.register_once = function(props, default_value, days_or_options) {
|
|
1533
|
+
var ret = this._run_hook('before_register_once', props, default_value, days_or_options);
|
|
1534
|
+
if (ret === null) {
|
|
1535
|
+
return;
|
|
1536
|
+
} else {
|
|
1537
|
+
props = ret[0];
|
|
1538
|
+
default_value = ret[1];
|
|
1539
|
+
days_or_options = ret[2];
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1495
1542
|
var options = options_for_register(days_or_options);
|
|
1496
1543
|
if (options['persistent']) {
|
|
1497
1544
|
this['persistence'].register_once(props, default_value, options['days']);
|
|
@@ -1515,6 +1562,14 @@ MixpanelLib.prototype.register_once = function(props, default_value, days_or_opt
|
|
|
1515
1562
|
* @param {boolean} [options.persistent=true] - whether to look in persistent storage (cookie/localStorage)
|
|
1516
1563
|
*/
|
|
1517
1564
|
MixpanelLib.prototype.unregister = function(property, options) {
|
|
1565
|
+
var ret = this._run_hook('before_unregister', property, options);
|
|
1566
|
+
if (ret === null) {
|
|
1567
|
+
return;
|
|
1568
|
+
} else {
|
|
1569
|
+
property = ret[0];
|
|
1570
|
+
options = ret[1];
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1518
1573
|
options = options_for_register(options);
|
|
1519
1574
|
if (options['persistent']) {
|
|
1520
1575
|
this['persistence'].unregister(property);
|
|
@@ -1563,6 +1618,13 @@ MixpanelLib.prototype.identify = function(
|
|
|
1563
1618
|
// _set_once_callback:function A callback to be run if and when the People set_once queue is flushed
|
|
1564
1619
|
// _union_callback:function A callback to be run if and when the People union queue is flushed
|
|
1565
1620
|
// _unset_callback:function A callback to be run if and when the People unset queue is flushed
|
|
1621
|
+
var ret = this._run_hook('before_identify', new_distinct_id);
|
|
1622
|
+
|
|
1623
|
+
if (ret === null) {
|
|
1624
|
+
return -1;
|
|
1625
|
+
} else {
|
|
1626
|
+
new_distinct_id = ret[0];
|
|
1627
|
+
}
|
|
1566
1628
|
|
|
1567
1629
|
var previous_distinct_id = this.get_distinct_id();
|
|
1568
1630
|
if (new_distinct_id && previous_distinct_id !== new_distinct_id) {
|
|
@@ -1887,6 +1949,25 @@ MixpanelLib.prototype.set_config = function(config) {
|
|
|
1887
1949
|
if (('autocapture' in config || 'record_heatmap_data' in config) && this.autocapture) {
|
|
1888
1950
|
this.autocapture.init();
|
|
1889
1951
|
}
|
|
1952
|
+
|
|
1953
|
+
if (_.isObject(config['hooks'])) {
|
|
1954
|
+
this.hooks = {};
|
|
1955
|
+
_.each(config['hooks'], function(hook_value, hook_name) {
|
|
1956
|
+
if (_.isFunction(hook_value)) {
|
|
1957
|
+
this.hooks[hook_name] = [hook_value];
|
|
1958
|
+
} else if (_.isArray(hook_value)) {
|
|
1959
|
+
this.hooks[hook_name] = [];
|
|
1960
|
+
for (var i = 0; i < hook_value.length; i++) {
|
|
1961
|
+
if (!_.isFunction(hook_value[i])) {
|
|
1962
|
+
console.critical('Invalid hook added. Hook is not a function');
|
|
1963
|
+
}
|
|
1964
|
+
this.hooks[hook_name].push(hook_value[i]);
|
|
1965
|
+
}
|
|
1966
|
+
} else {
|
|
1967
|
+
console.critical('Invalid hooks added. Ensure that the hook values passed into config.hooks are functions or arrays of functions.');
|
|
1968
|
+
}
|
|
1969
|
+
}, this);
|
|
1970
|
+
}
|
|
1890
1971
|
}
|
|
1891
1972
|
};
|
|
1892
1973
|
|
|
@@ -1904,12 +1985,26 @@ MixpanelLib.prototype.get_config = function(prop_name) {
|
|
|
1904
1985
|
* @returns {any|null} return value of user-provided hook, or null if nothing was returned
|
|
1905
1986
|
*/
|
|
1906
1987
|
MixpanelLib.prototype._run_hook = function(hook_name) {
|
|
1907
|
-
var
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1988
|
+
var hook_data = slice.call(arguments, 1);
|
|
1989
|
+
_.each(this.hooks[hook_name], function(hook) {
|
|
1990
|
+
if (hook_data === null) {
|
|
1991
|
+
return null;
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
var ret = hook.apply(this, hook_data);
|
|
1995
|
+
|
|
1996
|
+
if (typeof ret === 'undefined') {
|
|
1997
|
+
this.report_error(hook_name + ' hook did not return a valid value');
|
|
1998
|
+
hook_data = null;
|
|
1999
|
+
} else {
|
|
2000
|
+
if (!_.isArray(ret)) {
|
|
2001
|
+
ret = [ret];
|
|
2002
|
+
}
|
|
2003
|
+
hook_data.splice.apply(hook_data, [0, ret.length].concat(ret));
|
|
2004
|
+
}
|
|
2005
|
+
}, this);
|
|
2006
|
+
|
|
2007
|
+
return hook_data;
|
|
1913
2008
|
};
|
|
1914
2009
|
|
|
1915
2010
|
/**
|
|
@@ -2220,6 +2315,25 @@ MixpanelLib.prototype.report_error = function(msg, err) {
|
|
|
2220
2315
|
}
|
|
2221
2316
|
};
|
|
2222
2317
|
|
|
2318
|
+
MixpanelLib.prototype.add_hook = function(hook_name, hook_fn) {
|
|
2319
|
+
if (!this.hooks[hook_name]) {
|
|
2320
|
+
this.hooks[hook_name] = [];
|
|
2321
|
+
}
|
|
2322
|
+
this.hooks[hook_name].push(hook_fn);
|
|
2323
|
+
};
|
|
2324
|
+
|
|
2325
|
+
MixpanelLib.prototype.remove_hook = function(hook_name, hook_fn) {
|
|
2326
|
+
var fn_index;
|
|
2327
|
+
if (this.hooks[hook_name]) {
|
|
2328
|
+
fn_index = this.hooks[hook_name].indexOf(hook_fn);
|
|
2329
|
+
if (fn_index !== -1) {
|
|
2330
|
+
this.hooks[hook_name].splice(fn_index, 1);
|
|
2331
|
+
} else {
|
|
2332
|
+
console.log('remove_hook failed. Matching hook was not found');
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
};
|
|
2336
|
+
|
|
2223
2337
|
// EXPORTS (for closure compiler)
|
|
2224
2338
|
|
|
2225
2339
|
// MixpanelLib Exports
|
|
@@ -2252,6 +2366,8 @@ MixpanelLib.prototype['get_group'] = MixpanelLib.protot
|
|
|
2252
2366
|
MixpanelLib.prototype['set_group'] = MixpanelLib.prototype.set_group;
|
|
2253
2367
|
MixpanelLib.prototype['add_group'] = MixpanelLib.prototype.add_group;
|
|
2254
2368
|
MixpanelLib.prototype['remove_group'] = MixpanelLib.prototype.remove_group;
|
|
2369
|
+
MixpanelLib.prototype['add_hook'] = MixpanelLib.prototype.add_hook;
|
|
2370
|
+
MixpanelLib.prototype['remove_hook'] = MixpanelLib.prototype.remove_hook;
|
|
2255
2371
|
MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
|
|
2256
2372
|
MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
|
|
2257
2373
|
MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
|
package/src/window.js
CHANGED
|
@@ -15,7 +15,9 @@ if (typeof(window) === 'undefined') {
|
|
|
15
15
|
screen: { width: 0, height: 0 },
|
|
16
16
|
location: loc,
|
|
17
17
|
addEventListener: function() {},
|
|
18
|
-
removeEventListener: function() {}
|
|
18
|
+
removeEventListener: function() {},
|
|
19
|
+
dispatchEvent: function() {},
|
|
20
|
+
CustomEvent: function () {}
|
|
19
21
|
};
|
|
20
22
|
} else {
|
|
21
23
|
win = window;
|