@metamask-previews/analytics-controller 1.1.1-preview-1ec310ea7 → 1.1.1-preview-8f1765558
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 +0 -4
- package/dist/AnalyticsController-method-action-types.cjs.map +1 -1
- package/dist/AnalyticsController-method-action-types.d.cts +1 -19
- package/dist/AnalyticsController-method-action-types.d.cts.map +1 -1
- package/dist/AnalyticsController-method-action-types.d.mts +1 -19
- package/dist/AnalyticsController-method-action-types.d.mts.map +1 -1
- package/dist/AnalyticsController-method-action-types.mjs.map +1 -1
- package/dist/AnalyticsController.cjs +6 -120
- package/dist/AnalyticsController.cjs.map +1 -1
- package/dist/AnalyticsController.d.cts +1 -46
- package/dist/AnalyticsController.d.cts.map +1 -1
- package/dist/AnalyticsController.d.mts +1 -46
- package/dist/AnalyticsController.d.mts.map +1 -1
- package/dist/AnalyticsController.mjs +6 -120
- package/dist/AnalyticsController.mjs.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/selectors.cjs +0 -10
- package/dist/selectors.cjs.map +1 -1
- package/dist/selectors.d.cts +0 -1
- package/dist/selectors.d.cts.map +1 -1
- package/dist/selectors.d.mts +0 -1
- package/dist/selectors.d.mts.map +1 -1
- package/dist/selectors.mjs +0 -10
- package/dist/selectors.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,10 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
-
### Added
|
|
11
|
-
|
|
12
|
-
- Add optional pre-consent event queue to `AnalyticsController` (disabled by default via `isPreConsentQueueEnabled`), with a `consentDecisionMade` state field, `selectConsentDecisionMade` selector, and `resetConsentDecision` action ([#9252](https://github.com/MetaMask/core/pull/9252))
|
|
13
|
-
|
|
14
10
|
### Changed
|
|
15
11
|
|
|
16
12
|
- Bump `@metamask/utils` from `^11.9.0` to `^11.11.0` ([#9074](https://github.com/MetaMask/core/pull/9074))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsController-method-action-types.cjs","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { AnalyticsController } from './AnalyticsController';\n\n/**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param event - Analytics event with properties and sensitive properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerTrackEventAction = {\n type: `AnalyticsController:trackEvent`;\n handler: AnalyticsController['trackEvent'];\n};\n\n/**\n * Identify a user for analytics.\n *\n * @param traits - User traits/properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerIdentifyAction = {\n type: `AnalyticsController:identify`;\n handler: AnalyticsController['identify'];\n};\n\n/**\n * Track a page or screen view.\n *\n * @param name - The identifier/name of the page or screen being viewed (e.g., \"home\", \"settings\", \"wallet\")\n * @param properties - Optional properties associated with the view\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerTrackViewAction = {\n type: `AnalyticsController:trackView`;\n handler: AnalyticsController['trackView'];\n};\n\n/**\n * Opt in to analytics.\n
|
|
1
|
+
{"version":3,"file":"AnalyticsController-method-action-types.cjs","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":";AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { AnalyticsController } from './AnalyticsController';\n\n/**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param event - Analytics event with properties and sensitive properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerTrackEventAction = {\n type: `AnalyticsController:trackEvent`;\n handler: AnalyticsController['trackEvent'];\n};\n\n/**\n * Identify a user for analytics.\n *\n * @param traits - User traits/properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerIdentifyAction = {\n type: `AnalyticsController:identify`;\n handler: AnalyticsController['identify'];\n};\n\n/**\n * Track a page or screen view.\n *\n * @param name - The identifier/name of the page or screen being viewed (e.g., \"home\", \"settings\", \"wallet\")\n * @param properties - Optional properties associated with the view\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerTrackViewAction = {\n type: `AnalyticsController:trackView`;\n handler: AnalyticsController['trackView'];\n};\n\n/**\n * Opt in to analytics.\n */\nexport type AnalyticsControllerOptInAction = {\n type: `AnalyticsController:optIn`;\n handler: AnalyticsController['optIn'];\n};\n\n/**\n * Opt out of analytics.\n */\nexport type AnalyticsControllerOptOutAction = {\n type: `AnalyticsController:optOut`;\n handler: AnalyticsController['optOut'];\n};\n\n/**\n * Union of all AnalyticsController action types.\n */\nexport type AnalyticsControllerMethodActions =\n | AnalyticsControllerTrackEventAction\n | AnalyticsControllerIdentifyAction\n | AnalyticsControllerTrackViewAction\n | AnalyticsControllerOptInAction\n | AnalyticsControllerOptOutAction;\n"]}
|
|
@@ -38,9 +38,6 @@ export type AnalyticsControllerTrackViewAction = {
|
|
|
38
38
|
};
|
|
39
39
|
/**
|
|
40
40
|
* Opt in to analytics.
|
|
41
|
-
*
|
|
42
|
-
* Records that a consent decision has been made and replays any events that
|
|
43
|
-
* were queued while the user was undecided.
|
|
44
41
|
*/
|
|
45
42
|
export type AnalyticsControllerOptInAction = {
|
|
46
43
|
type: `AnalyticsController:optIn`;
|
|
@@ -48,28 +45,13 @@ export type AnalyticsControllerOptInAction = {
|
|
|
48
45
|
};
|
|
49
46
|
/**
|
|
50
47
|
* Opt out of analytics.
|
|
51
|
-
*
|
|
52
|
-
* Records that a consent decision has been made and discards any persisted
|
|
53
|
-
* events so nothing captured before the decision is ever delivered.
|
|
54
48
|
*/
|
|
55
49
|
export type AnalyticsControllerOptOutAction = {
|
|
56
50
|
type: `AnalyticsController:optOut`;
|
|
57
51
|
handler: AnalyticsController['optOut'];
|
|
58
52
|
};
|
|
59
|
-
/**
|
|
60
|
-
* Reset the consent decision back to undecided.
|
|
61
|
-
*
|
|
62
|
-
* Intended for client flows that restart onboarding. Clears the opt-in
|
|
63
|
-
* preference and discards both the delivery queue and any pre-consent events,
|
|
64
|
-
* so nothing captured before the reset is delivered and the user is treated
|
|
65
|
-
* as undecided again.
|
|
66
|
-
*/
|
|
67
|
-
export type AnalyticsControllerResetConsentDecisionAction = {
|
|
68
|
-
type: `AnalyticsController:resetConsentDecision`;
|
|
69
|
-
handler: AnalyticsController['resetConsentDecision'];
|
|
70
|
-
};
|
|
71
53
|
/**
|
|
72
54
|
* Union of all AnalyticsController action types.
|
|
73
55
|
*/
|
|
74
|
-
export type AnalyticsControllerMethodActions = AnalyticsControllerTrackEventAction | AnalyticsControllerIdentifyAction | AnalyticsControllerTrackViewAction | AnalyticsControllerOptInAction | AnalyticsControllerOptOutAction
|
|
56
|
+
export type AnalyticsControllerMethodActions = AnalyticsControllerTrackEventAction | AnalyticsControllerIdentifyAction | AnalyticsControllerTrackViewAction | AnalyticsControllerOptInAction | AnalyticsControllerOptOutAction;
|
|
75
57
|
//# sourceMappingURL=AnalyticsController-method-action-types.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsController-method-action-types.d.cts","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,kCAA8B;AAEjE;;;;;;;GAOG;AACH,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,gCAAgC,CAAC;IACvC,OAAO,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAC;CAC5C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,kCAAkC,GAAG;IAC/C,IAAI,EAAE,+BAA+B,CAAC;IACtC,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;CAC3C,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"AnalyticsController-method-action-types.d.cts","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,kCAA8B;AAEjE;;;;;;;GAOG;AACH,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,gCAAgC,CAAC;IACvC,OAAO,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAC;CAC5C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,kCAAkC,GAAG;IAC/C,IAAI,EAAE,+BAA+B,CAAC;IACtC,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;CAC3C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,2BAA2B,CAAC;IAClC,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,IAAI,EAAE,4BAA4B,CAAC;IACnC,OAAO,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gCAAgC,GACxC,mCAAmC,GACnC,iCAAiC,GACjC,kCAAkC,GAClC,8BAA8B,GAC9B,+BAA+B,CAAC"}
|
|
@@ -38,9 +38,6 @@ export type AnalyticsControllerTrackViewAction = {
|
|
|
38
38
|
};
|
|
39
39
|
/**
|
|
40
40
|
* Opt in to analytics.
|
|
41
|
-
*
|
|
42
|
-
* Records that a consent decision has been made and replays any events that
|
|
43
|
-
* were queued while the user was undecided.
|
|
44
41
|
*/
|
|
45
42
|
export type AnalyticsControllerOptInAction = {
|
|
46
43
|
type: `AnalyticsController:optIn`;
|
|
@@ -48,28 +45,13 @@ export type AnalyticsControllerOptInAction = {
|
|
|
48
45
|
};
|
|
49
46
|
/**
|
|
50
47
|
* Opt out of analytics.
|
|
51
|
-
*
|
|
52
|
-
* Records that a consent decision has been made and discards any persisted
|
|
53
|
-
* events so nothing captured before the decision is ever delivered.
|
|
54
48
|
*/
|
|
55
49
|
export type AnalyticsControllerOptOutAction = {
|
|
56
50
|
type: `AnalyticsController:optOut`;
|
|
57
51
|
handler: AnalyticsController['optOut'];
|
|
58
52
|
};
|
|
59
|
-
/**
|
|
60
|
-
* Reset the consent decision back to undecided.
|
|
61
|
-
*
|
|
62
|
-
* Intended for client flows that restart onboarding. Clears the opt-in
|
|
63
|
-
* preference and discards both the delivery queue and any pre-consent events,
|
|
64
|
-
* so nothing captured before the reset is delivered and the user is treated
|
|
65
|
-
* as undecided again.
|
|
66
|
-
*/
|
|
67
|
-
export type AnalyticsControllerResetConsentDecisionAction = {
|
|
68
|
-
type: `AnalyticsController:resetConsentDecision`;
|
|
69
|
-
handler: AnalyticsController['resetConsentDecision'];
|
|
70
|
-
};
|
|
71
53
|
/**
|
|
72
54
|
* Union of all AnalyticsController action types.
|
|
73
55
|
*/
|
|
74
|
-
export type AnalyticsControllerMethodActions = AnalyticsControllerTrackEventAction | AnalyticsControllerIdentifyAction | AnalyticsControllerTrackViewAction | AnalyticsControllerOptInAction | AnalyticsControllerOptOutAction
|
|
56
|
+
export type AnalyticsControllerMethodActions = AnalyticsControllerTrackEventAction | AnalyticsControllerIdentifyAction | AnalyticsControllerTrackViewAction | AnalyticsControllerOptInAction | AnalyticsControllerOptOutAction;
|
|
75
57
|
//# sourceMappingURL=AnalyticsController-method-action-types.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsController-method-action-types.d.mts","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,kCAA8B;AAEjE;;;;;;;GAOG;AACH,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,gCAAgC,CAAC;IACvC,OAAO,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAC;CAC5C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,kCAAkC,GAAG;IAC/C,IAAI,EAAE,+BAA+B,CAAC;IACtC,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;CAC3C,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"AnalyticsController-method-action-types.d.mts","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,kCAA8B;AAEjE;;;;;;;GAOG;AACH,MAAM,MAAM,mCAAmC,GAAG;IAChD,IAAI,EAAE,gCAAgC,CAAC;IACvC,OAAO,EAAE,mBAAmB,CAAC,YAAY,CAAC,CAAC;CAC5C,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC9C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,mBAAmB,CAAC,UAAU,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,kCAAkC,GAAG;IAC/C,IAAI,EAAE,+BAA+B,CAAC;IACtC,OAAO,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC;CAC3C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,IAAI,EAAE,2BAA2B,CAAC;IAClC,OAAO,EAAE,mBAAmB,CAAC,OAAO,CAAC,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,+BAA+B,GAAG;IAC5C,IAAI,EAAE,4BAA4B,CAAC;IACnC,OAAO,EAAE,mBAAmB,CAAC,QAAQ,CAAC,CAAC;CACxC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gCAAgC,GACxC,mCAAmC,GACnC,iCAAiC,GACjC,kCAAkC,GAClC,8BAA8B,GAC9B,+BAA+B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsController-method-action-types.mjs","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { AnalyticsController } from './AnalyticsController';\n\n/**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param event - Analytics event with properties and sensitive properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerTrackEventAction = {\n type: `AnalyticsController:trackEvent`;\n handler: AnalyticsController['trackEvent'];\n};\n\n/**\n * Identify a user for analytics.\n *\n * @param traits - User traits/properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerIdentifyAction = {\n type: `AnalyticsController:identify`;\n handler: AnalyticsController['identify'];\n};\n\n/**\n * Track a page or screen view.\n *\n * @param name - The identifier/name of the page or screen being viewed (e.g., \"home\", \"settings\", \"wallet\")\n * @param properties - Optional properties associated with the view\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerTrackViewAction = {\n type: `AnalyticsController:trackView`;\n handler: AnalyticsController['trackView'];\n};\n\n/**\n * Opt in to analytics.\n
|
|
1
|
+
{"version":3,"file":"AnalyticsController-method-action-types.mjs","sourceRoot":"","sources":["../src/AnalyticsController-method-action-types.ts"],"names":[],"mappings":"AAAA;;;GAGG","sourcesContent":["/**\n * This file is auto generated.\n * Do not edit manually.\n */\n\nimport type { AnalyticsController } from './AnalyticsController';\n\n/**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param event - Analytics event with properties and sensitive properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerTrackEventAction = {\n type: `AnalyticsController:trackEvent`;\n handler: AnalyticsController['trackEvent'];\n};\n\n/**\n * Identify a user for analytics.\n *\n * @param traits - User traits/properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerIdentifyAction = {\n type: `AnalyticsController:identify`;\n handler: AnalyticsController['identify'];\n};\n\n/**\n * Track a page or screen view.\n *\n * @param name - The identifier/name of the page or screen being viewed (e.g., \"home\", \"settings\", \"wallet\")\n * @param properties - Optional properties associated with the view\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\nexport type AnalyticsControllerTrackViewAction = {\n type: `AnalyticsController:trackView`;\n handler: AnalyticsController['trackView'];\n};\n\n/**\n * Opt in to analytics.\n */\nexport type AnalyticsControllerOptInAction = {\n type: `AnalyticsController:optIn`;\n handler: AnalyticsController['optIn'];\n};\n\n/**\n * Opt out of analytics.\n */\nexport type AnalyticsControllerOptOutAction = {\n type: `AnalyticsController:optOut`;\n handler: AnalyticsController['optOut'];\n};\n\n/**\n * Union of all AnalyticsController action types.\n */\nexport type AnalyticsControllerMethodActions =\n | AnalyticsControllerTrackEventAction\n | AnalyticsControllerIdentifyAction\n | AnalyticsControllerTrackViewAction\n | AnalyticsControllerOptInAction\n | AnalyticsControllerOptOutAction;\n"]}
|
|
@@ -10,7 +10,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
12
12
|
};
|
|
13
|
-
var _AnalyticsController_instances, _AnalyticsController_platformAdapter, _AnalyticsController_isAnonymousEventsFeatureEnabled, _AnalyticsController_isEventQueuePersistenceEnabled,
|
|
13
|
+
var _AnalyticsController_instances, _AnalyticsController_platformAdapter, _AnalyticsController_isAnonymousEventsFeatureEnabled, _AnalyticsController_isEventQueuePersistenceEnabled, _AnalyticsController_initialized, _AnalyticsController_sendOrQueueTrackEvent, _AnalyticsController_sendOrQueueIdentifyEvent, _AnalyticsController_sendOrQueueViewEvent, _AnalyticsController_enqueueEvent, _AnalyticsController_sendQueuedEvent, _AnalyticsController_replayQueuedEvents, _AnalyticsController_removeQueuedEvent, _AnalyticsController_clearQueuedEvents;
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.AnalyticsController = exports.getDefaultAnalyticsControllerState = exports.controllerName = void 0;
|
|
16
16
|
const base_controller_1 = require("@metamask/base-controller");
|
|
@@ -37,7 +37,6 @@ exports.controllerName = 'AnalyticsController';
|
|
|
37
37
|
function getDefaultAnalyticsControllerState() {
|
|
38
38
|
return {
|
|
39
39
|
optedIn: false,
|
|
40
|
-
consentDecisionMade: false,
|
|
41
40
|
};
|
|
42
41
|
}
|
|
43
42
|
exports.getDefaultAnalyticsControllerState = getDefaultAnalyticsControllerState;
|
|
@@ -66,18 +65,6 @@ const analyticsControllerMetadata = {
|
|
|
66
65
|
includeInDebugSnapshot: false,
|
|
67
66
|
usedInUi: false,
|
|
68
67
|
},
|
|
69
|
-
consentDecisionMade: {
|
|
70
|
-
includeInStateLogs: true,
|
|
71
|
-
persist: true,
|
|
72
|
-
includeInDebugSnapshot: true,
|
|
73
|
-
usedInUi: true,
|
|
74
|
-
},
|
|
75
|
-
preConsentEventQueue: {
|
|
76
|
-
includeInStateLogs: false,
|
|
77
|
-
persist: true,
|
|
78
|
-
includeInDebugSnapshot: false,
|
|
79
|
-
usedInUi: false,
|
|
80
|
-
},
|
|
81
68
|
};
|
|
82
69
|
// === MESSENGER ===
|
|
83
70
|
const MESSENGER_EXPOSED_METHODS = [
|
|
@@ -86,7 +73,6 @@ const MESSENGER_EXPOSED_METHODS = [
|
|
|
86
73
|
'trackView',
|
|
87
74
|
'optIn',
|
|
88
75
|
'optOut',
|
|
89
|
-
'resetConsentDecision',
|
|
90
76
|
];
|
|
91
77
|
/**
|
|
92
78
|
* Returns whether a value is a non-array object.
|
|
@@ -152,11 +138,10 @@ class AnalyticsController extends base_controller_1.BaseController {
|
|
|
152
138
|
* @param options.platformAdapter - Platform adapter implementation for tracking
|
|
153
139
|
* @param options.isAnonymousEventsFeatureEnabled - Whether the anonymous events feature is enabled
|
|
154
140
|
* @param options.isEventQueuePersistenceEnabled - Whether analytics event queue persistence is enabled
|
|
155
|
-
* @param options.isPreConsentQueueEnabled - Whether the pre-consent event queue is enabled
|
|
156
141
|
* @throws Error if state.analyticsId is missing or not a valid UUIDv4
|
|
157
142
|
* @remarks After construction, call {@link AnalyticsController.init} to complete initialization.
|
|
158
143
|
*/
|
|
159
|
-
constructor({ state, messenger, platformAdapter, isAnonymousEventsFeatureEnabled = false, isEventQueuePersistenceEnabled = false,
|
|
144
|
+
constructor({ state, messenger, platformAdapter, isAnonymousEventsFeatureEnabled = false, isEventQueuePersistenceEnabled = false, }) {
|
|
160
145
|
const initialState = {
|
|
161
146
|
...getDefaultAnalyticsControllerState(),
|
|
162
147
|
...state,
|
|
@@ -172,21 +157,17 @@ class AnalyticsController extends base_controller_1.BaseController {
|
|
|
172
157
|
_AnalyticsController_platformAdapter.set(this, void 0);
|
|
173
158
|
_AnalyticsController_isAnonymousEventsFeatureEnabled.set(this, void 0);
|
|
174
159
|
_AnalyticsController_isEventQueuePersistenceEnabled.set(this, void 0);
|
|
175
|
-
_AnalyticsController_isPreConsentQueueEnabled.set(this, void 0);
|
|
176
160
|
_AnalyticsController_initialized.set(this, void 0);
|
|
177
161
|
__classPrivateFieldSet(this, _AnalyticsController_isAnonymousEventsFeatureEnabled, isAnonymousEventsFeatureEnabled, "f");
|
|
178
162
|
__classPrivateFieldSet(this, _AnalyticsController_isEventQueuePersistenceEnabled, isEventQueuePersistenceEnabled, "f");
|
|
179
|
-
__classPrivateFieldSet(this, _AnalyticsController_isPreConsentQueueEnabled, isPreConsentQueueEnabled, "f");
|
|
180
163
|
__classPrivateFieldSet(this, _AnalyticsController_platformAdapter, platformAdapter, "f");
|
|
181
164
|
__classPrivateFieldSet(this, _AnalyticsController_initialized, false, "f");
|
|
182
165
|
this.messenger.registerMethodActionHandlers(this, MESSENGER_EXPOSED_METHODS);
|
|
183
166
|
(0, AnalyticsLogger_1.projectLogger)('AnalyticsController initialized and ready', {
|
|
184
167
|
enabled: selectors_1.analyticsControllerSelectors.selectEnabled(this.state),
|
|
185
168
|
optedIn: this.state.optedIn,
|
|
186
|
-
consentDecisionMade: this.state.consentDecisionMade,
|
|
187
169
|
analyticsId: this.state.analyticsId,
|
|
188
170
|
eventQueuePersistenceEnabled: __classPrivateFieldGet(this, _AnalyticsController_isEventQueuePersistenceEnabled, "f"),
|
|
189
|
-
preConsentQueueEnabled: __classPrivateFieldGet(this, _AnalyticsController_isPreConsentQueueEnabled, "f"),
|
|
190
171
|
});
|
|
191
172
|
}
|
|
192
173
|
/**
|
|
@@ -209,7 +190,6 @@ class AnalyticsController extends base_controller_1.BaseController {
|
|
|
209
190
|
(0, AnalyticsLogger_1.projectLogger)('Error calling platformAdapter.onSetupCompleted', error);
|
|
210
191
|
}
|
|
211
192
|
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_replayQueuedEvents).call(this);
|
|
212
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_reconcilePreConsentEvents).call(this);
|
|
213
193
|
}
|
|
214
194
|
/**
|
|
215
195
|
* Track an analytics event.
|
|
@@ -220,15 +200,9 @@ class AnalyticsController extends base_controller_1.BaseController {
|
|
|
220
200
|
* @param context - Optional platform-specific context forwarded to the platform adapter.
|
|
221
201
|
*/
|
|
222
202
|
trackEvent(event, context) {
|
|
203
|
+
// Don't track if analytics is disabled
|
|
223
204
|
if (!selectors_1.analyticsControllerSelectors.selectEnabled(this.state)) {
|
|
224
|
-
|
|
225
|
-
// captured in the pre-consent queue (see #sendOrQueueTrackEvent) to be
|
|
226
|
-
// replayed if they later opt in. Otherwise (opted out, or pre-consent
|
|
227
|
-
// queue disabled) drop it.
|
|
228
|
-
const shouldQueuePreConsent = __classPrivateFieldGet(this, _AnalyticsController_isPreConsentQueueEnabled, "f") && !this.state.consentDecisionMade;
|
|
229
|
-
if (!shouldQueuePreConsent) {
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
205
|
+
return;
|
|
232
206
|
}
|
|
233
207
|
// if event does not have properties, send event without properties
|
|
234
208
|
// and return to prevent any additional processing
|
|
@@ -282,53 +256,25 @@ class AnalyticsController extends base_controller_1.BaseController {
|
|
|
282
256
|
}
|
|
283
257
|
/**
|
|
284
258
|
* Opt in to analytics.
|
|
285
|
-
*
|
|
286
|
-
* Records that a consent decision has been made and replays any events that
|
|
287
|
-
* were queued while the user was undecided.
|
|
288
259
|
*/
|
|
289
260
|
optIn() {
|
|
290
261
|
this.update((state) => {
|
|
291
262
|
state.optedIn = true;
|
|
292
|
-
state.consentDecisionMade = true;
|
|
293
263
|
});
|
|
294
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_replayPreConsentEvents).call(this);
|
|
295
264
|
}
|
|
296
265
|
/**
|
|
297
266
|
* Opt out of analytics.
|
|
298
|
-
*
|
|
299
|
-
* Records that a consent decision has been made and discards any persisted
|
|
300
|
-
* events so nothing captured before the decision is ever delivered.
|
|
301
267
|
*/
|
|
302
268
|
optOut() {
|
|
303
269
|
this.update((state) => {
|
|
304
270
|
state.optedIn = false;
|
|
305
|
-
state.consentDecisionMade = true;
|
|
306
271
|
});
|
|
307
272
|
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_clearQueuedEvents).call(this);
|
|
308
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_clearPreConsentEvents).call(this);
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Reset the consent decision back to undecided.
|
|
312
|
-
*
|
|
313
|
-
* Intended for client flows that restart onboarding. Clears the opt-in
|
|
314
|
-
* preference and discards both the delivery queue and any pre-consent events,
|
|
315
|
-
* so nothing captured before the reset is delivered and the user is treated
|
|
316
|
-
* as undecided again.
|
|
317
|
-
*/
|
|
318
|
-
resetConsentDecision() {
|
|
319
|
-
this.update((state) => {
|
|
320
|
-
state.optedIn = false;
|
|
321
|
-
state.consentDecisionMade = false;
|
|
322
|
-
});
|
|
323
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_clearQueuedEvents).call(this);
|
|
324
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_clearPreConsentEvents).call(this);
|
|
325
273
|
}
|
|
326
274
|
}
|
|
327
275
|
exports.AnalyticsController = AnalyticsController;
|
|
328
|
-
_AnalyticsController_platformAdapter = new WeakMap(), _AnalyticsController_isAnonymousEventsFeatureEnabled = new WeakMap(), _AnalyticsController_isEventQueuePersistenceEnabled = new WeakMap(),
|
|
329
|
-
|
|
330
|
-
if (selectors_1.analyticsControllerSelectors.selectEnabled(this.state) &&
|
|
331
|
-
!__classPrivateFieldGet(this, _AnalyticsController_isEventQueuePersistenceEnabled, "f")) {
|
|
276
|
+
_AnalyticsController_platformAdapter = new WeakMap(), _AnalyticsController_isAnonymousEventsFeatureEnabled = new WeakMap(), _AnalyticsController_isEventQueuePersistenceEnabled = new WeakMap(), _AnalyticsController_initialized = new WeakMap(), _AnalyticsController_instances = new WeakSet(), _AnalyticsController_sendOrQueueTrackEvent = function _AnalyticsController_sendOrQueueTrackEvent(eventName, properties, context) {
|
|
277
|
+
if (!__classPrivateFieldGet(this, _AnalyticsController_isEventQueuePersistenceEnabled, "f")) {
|
|
332
278
|
__classPrivateFieldGet(this, _AnalyticsController_platformAdapter, "f").track(eventName, properties, context);
|
|
333
279
|
return;
|
|
334
280
|
}
|
|
@@ -340,12 +286,6 @@ _AnalyticsController_platformAdapter = new WeakMap(), _AnalyticsController_isAno
|
|
|
340
286
|
...(properties === undefined ? {} : { properties }),
|
|
341
287
|
...(context === undefined ? {} : { context }),
|
|
342
288
|
};
|
|
343
|
-
// Not yet enabled (reached only while undecided with the pre-consent queue
|
|
344
|
-
// enabled): hold the event until the user opts in.
|
|
345
|
-
if (!selectors_1.analyticsControllerSelectors.selectEnabled(this.state)) {
|
|
346
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_enqueuePreConsentEvent).call(this, queuedEvent);
|
|
347
|
-
return;
|
|
348
|
-
}
|
|
349
289
|
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_enqueueEvent).call(this, queuedEvent);
|
|
350
290
|
}, _AnalyticsController_sendOrQueueIdentifyEvent = function _AnalyticsController_sendOrQueueIdentifyEvent(userId, traits, context) {
|
|
351
291
|
if (!__classPrivateFieldGet(this, _AnalyticsController_isEventQueuePersistenceEnabled, "f")) {
|
|
@@ -458,59 +398,5 @@ _AnalyticsController_platformAdapter = new WeakMap(), _AnalyticsController_isAno
|
|
|
458
398
|
this.update((state) => {
|
|
459
399
|
state.eventQueue = {};
|
|
460
400
|
});
|
|
461
|
-
}, _AnalyticsController_enqueuePreConsentEvent = function _AnalyticsController_enqueuePreConsentEvent(queuedEvent) {
|
|
462
|
-
const preConsentEventQueue = {
|
|
463
|
-
...(this.state.preConsentEventQueue ?? {}),
|
|
464
|
-
[queuedEvent.messageId]: queuedEvent,
|
|
465
|
-
};
|
|
466
|
-
this.update((state) => {
|
|
467
|
-
state.preConsentEventQueue = preConsentEventQueue;
|
|
468
|
-
});
|
|
469
|
-
}, _AnalyticsController_replayPreConsentEvents = function _AnalyticsController_replayPreConsentEvents() {
|
|
470
|
-
if (!__classPrivateFieldGet(this, _AnalyticsController_isPreConsentQueueEnabled, "f")) {
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
const queue = this.state.preConsentEventQueue;
|
|
474
|
-
if (!queue) {
|
|
475
|
-
return;
|
|
476
|
-
}
|
|
477
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_clearPreConsentEvents).call(this);
|
|
478
|
-
for (const [messageId, queuedEvent] of Object.entries(queue)) {
|
|
479
|
-
if (!isAnalyticsQueuedEvent(queuedEvent) ||
|
|
480
|
-
queuedEvent.messageId !== messageId) {
|
|
481
|
-
(0, AnalyticsLogger_1.projectLogger)('Dropping invalid queued pre-consent analytics event', {
|
|
482
|
-
messageId,
|
|
483
|
-
});
|
|
484
|
-
continue;
|
|
485
|
-
}
|
|
486
|
-
if (__classPrivateFieldGet(this, _AnalyticsController_isEventQueuePersistenceEnabled, "f")) {
|
|
487
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_enqueueEvent).call(this, queuedEvent);
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_sendQueuedEvent).call(this, queuedEvent);
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
}, _AnalyticsController_clearPreConsentEvents = function _AnalyticsController_clearPreConsentEvents() {
|
|
494
|
-
if (!this.state.preConsentEventQueue) {
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
this.update((state) => {
|
|
498
|
-
state.preConsentEventQueue = {};
|
|
499
|
-
});
|
|
500
|
-
}, _AnalyticsController_reconcilePreConsentEvents = function _AnalyticsController_reconcilePreConsentEvents() {
|
|
501
|
-
const queue = this.state.preConsentEventQueue;
|
|
502
|
-
if (!queue) {
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
if (!__classPrivateFieldGet(this, _AnalyticsController_isPreConsentQueueEnabled, "f")) {
|
|
506
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_clearPreConsentEvents).call(this);
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
if (this.state.optedIn) {
|
|
510
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_replayPreConsentEvents).call(this);
|
|
511
|
-
}
|
|
512
|
-
else if (this.state.consentDecisionMade) {
|
|
513
|
-
__classPrivateFieldGet(this, _AnalyticsController_instances, "m", _AnalyticsController_clearPreConsentEvents).call(this);
|
|
514
|
-
}
|
|
515
401
|
};
|
|
516
402
|
//# sourceMappingURL=AnalyticsController.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnalyticsController.cjs","sourceRoot":"","sources":["../src/AnalyticsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport type { Json } from '@metamask/utils';\nimport { cloneDeep } from 'lodash';\nimport { v4 as uuid } from 'uuid';\n\nimport type { AnalyticsControllerMethodActions } from './AnalyticsController-method-action-types';\nimport { validateAnalyticsControllerState } from './analyticsControllerStateValidator';\nimport { projectLogger as log } from './AnalyticsLogger';\nimport type {\n AnalyticsPlatformAdapter,\n AnalyticsDeliveryOptions,\n AnalyticsContext,\n AnalyticsEventProperties,\n AnalyticsUserTraits,\n AnalyticsTrackingEvent,\n} from './AnalyticsPlatformAdapter.types';\nimport { analyticsControllerSelectors } from './selectors';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link AnalyticsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'AnalyticsController';\n\n// === STATE ===\n\n/**\n * Describes the shape of the state object for {@link AnalyticsController}.\n */\nexport type AnalyticsControllerState = {\n /**\n * Whether the user has opted in to analytics.\n */\n optedIn: boolean;\n\n /**\n * User's UUIDv4 analytics identifier.\n * This is an identity (unique per user), not a preference.\n * Must be provided by the platform - the controller does not generate it.\n */\n analyticsId: string;\n\n /**\n * Persisted queue of analytics events waiting for delivery acknowledgement.\n * This is only used when event queue persistence is enabled.\n */\n eventQueue?: Record<string, Json>;\n\n /**\n * Whether the user has made a consent decision (opted in or opted out).\n *\n * This distinguishes the \"undecided\" state (e.g. during onboarding, before\n * the user has answered the analytics prompt) from an explicit opt-out.\n * Defaults to `false` and is set to `true` by {@link AnalyticsController.optIn}\n * or {@link AnalyticsController.optOut}, and back to `false` by\n * {@link AnalyticsController.resetConsentDecision}. Optional for backward\n * compatibility with persisted state that predates this field.\n */\n consentDecisionMade?: boolean;\n\n /**\n * Persisted queue of track events ({@link AnalyticsQueuedTrackEvent}) captured\n * while the user is undecided (no consent decision made yet). Replayed on\n * opt-in and cleared on opt-out. This is only used when the pre-consent queue\n * is enabled.\n */\n preConsentEventQueue?: Record<string, Json>;\n};\n\n/**\n * Event types supported by the persisted analytics event queue.\n */\nexport type AnalyticsQueuedEventType = 'track' | 'identify' | 'view';\n\n/**\n * Base persisted event queue entry.\n */\nexport type AnalyticsQueuedEventBase = {\n /**\n * Event type used to replay the payload with the platform adapter.\n */\n type: AnalyticsQueuedEventType;\n\n /**\n * Stable identifier for the analytics payload.\n */\n messageId: string;\n\n /**\n * Original payload timestamp serialized for persistence.\n */\n timestamp: string;\n};\n\n/**\n * Persisted track event queue entry.\n */\nexport type AnalyticsQueuedTrackEvent = AnalyticsQueuedEventBase & {\n type: 'track';\n eventName: string;\n properties?: AnalyticsEventProperties;\n context?: AnalyticsContext;\n};\n\n/**\n * Persisted identify event queue entry.\n */\nexport type AnalyticsQueuedIdentifyEvent = AnalyticsQueuedEventBase & {\n type: 'identify';\n userId: string;\n traits?: AnalyticsUserTraits;\n context?: AnalyticsContext;\n};\n\n/**\n * Persisted view event queue entry.\n */\nexport type AnalyticsQueuedViewEvent = AnalyticsQueuedEventBase & {\n type: 'view';\n name: string;\n properties?: AnalyticsEventProperties;\n context?: AnalyticsContext;\n};\n\n/**\n * Persisted analytics event queue entry.\n */\nexport type AnalyticsQueuedEvent =\n | AnalyticsQueuedTrackEvent\n | AnalyticsQueuedIdentifyEvent\n | AnalyticsQueuedViewEvent;\n\n/**\n * Persisted analytics event queue keyed by message ID.\n */\nexport type AnalyticsEventQueue = Record<string, AnalyticsQueuedEvent>;\n\n/**\n * Returns default values for AnalyticsController state.\n *\n * Note: analyticsId is NOT included - it's an identity that must be\n * provided by the platform (generated once on first run, then persisted).\n *\n * @returns Default state without analyticsId\n */\nexport function getDefaultAnalyticsControllerState(): Omit<\n AnalyticsControllerState,\n 'analyticsId'\n> {\n return {\n optedIn: false,\n consentDecisionMade: false,\n };\n}\n\n/**\n * The metadata for each property in {@link AnalyticsControllerState}.\n *\n * Both `optedIn` and `analyticsId` are persisted (`persist: true`).\n * The platform must supply a valid UUIDv4 `analyticsId` on first run.\n */\nconst analyticsControllerMetadata = {\n optedIn: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n analyticsId: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n eventQueue: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n consentDecisionMade: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n preConsentEventQueue: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n} satisfies StateMetadata<AnalyticsControllerState>;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'trackEvent',\n 'identify',\n 'trackView',\n 'optIn',\n 'optOut',\n 'resetConsentDecision',\n] as const;\n\n/**\n * Returns the state of the {@link AnalyticsController}.\n */\nexport type AnalyticsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AnalyticsControllerState\n>;\n\n/**\n * Actions that {@link AnalyticsControllerMessenger} exposes to other consumers.\n */\nexport type AnalyticsControllerActions =\n | AnalyticsControllerGetStateAction\n | AnalyticsControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link AnalyticsControllerMessenger} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Event emitted when the state of the {@link AnalyticsController} changes.\n */\nexport type AnalyticsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AnalyticsControllerState\n>;\n\n/**\n * Events that {@link AnalyticsControllerMessenger} exposes to other consumers.\n */\nexport type AnalyticsControllerEvents = AnalyticsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link AnalyticsControllerMessenger} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link AnalyticsController}.\n */\nexport type AnalyticsControllerMessenger = Messenger<\n typeof controllerName,\n AnalyticsControllerActions | AllowedActions,\n AnalyticsControllerEvents | AllowedEvents\n>;\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * The options that AnalyticsController takes.\n */\nexport type AnalyticsControllerOptions = {\n /**\n * Initial controller state. Must include a valid UUIDv4 `analyticsId`.\n * The platform is responsible for generating the ID on first run.\n * It is then persisted with controller state when using a persisted store.\n */\n state: AnalyticsControllerState;\n /**\n * Messenger used to communicate with BaseController and other controllers.\n */\n messenger: AnalyticsControllerMessenger;\n /**\n * Platform adapter implementation for tracking events.\n */\n platformAdapter: AnalyticsPlatformAdapter;\n\n /**\n * Whether the anonymous events feature is enabled.\n *\n * @default false\n */\n isAnonymousEventsFeatureEnabled?: boolean;\n\n /**\n * Whether analytics event queue persistence is enabled.\n *\n * When enabled, AnalyticsController persists each platform adapter payload\n * until the adapter reports successful delivery.\n *\n * @default false\n */\n isEventQueuePersistenceEnabled?: boolean;\n\n /**\n * Whether the pre-consent event queue is enabled.\n *\n * When enabled, track events received while the user is undecided\n * (no consent decision made yet) are persisted and replayed on opt-in,\n * or dropped on opt-out. When disabled, such events are dropped immediately,\n * preserving the legacy behavior.\n *\n * @default false\n */\n isPreConsentQueueEnabled?: boolean;\n};\n\n/**\n * Returns whether a value is a non-array object.\n *\n * @param value - The value to check.\n * @returns True if the value is a record.\n */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/**\n * Returns whether a value is a valid persisted analytics event.\n *\n * @param value - The value to check.\n * @returns True if the value is a queued analytics event.\n */\nfunction isAnalyticsQueuedEvent(value: unknown): value is AnalyticsQueuedEvent {\n if (!isRecord(value)) {\n return false;\n }\n\n if (\n typeof value.messageId !== 'string' ||\n typeof value.timestamp !== 'string'\n ) {\n return false;\n }\n\n if (value.type === 'track') {\n return (\n typeof value.eventName === 'string' &&\n (value.properties === undefined || isRecord(value.properties)) &&\n (value.context === undefined || isRecord(value.context))\n );\n }\n\n if (value.type === 'identify') {\n return (\n typeof value.userId === 'string' &&\n (value.traits === undefined || isRecord(value.traits)) &&\n (value.context === undefined || isRecord(value.context))\n );\n }\n\n if (value.type === 'view') {\n return (\n typeof value.name === 'string' &&\n (value.properties === undefined || isRecord(value.properties)) &&\n (value.context === undefined || isRecord(value.context))\n );\n }\n\n return false;\n}\n\n/**\n * The AnalyticsController manages analytics tracking across platforms (Mobile/Extension).\n * It provides a unified interface for tracking events, identifying users, and managing\n * analytics preferences while delegating platform-specific implementation to an\n * {@link AnalyticsPlatformAdapter}.\n *\n * This controller follows the MetaMask controller pattern and integrates with the\n * messenger system to allow other controllers and components to track analytics events.\n * It delegates platform-specific implementation to an {@link AnalyticsPlatformAdapter}.\n *\n * The controller persists `optedIn` and `analyticsId` when composed with a persisted\n * store. The platform must supply a valid `analyticsId` on first launch.\n */\nexport class AnalyticsController extends BaseController<\n 'AnalyticsController',\n AnalyticsControllerState,\n AnalyticsControllerMessenger\n> {\n readonly #platformAdapter: AnalyticsPlatformAdapter;\n\n readonly #isAnonymousEventsFeatureEnabled: boolean;\n\n readonly #isEventQueuePersistenceEnabled: boolean;\n\n readonly #isPreConsentQueueEnabled: boolean;\n\n #initialized: boolean;\n\n /**\n * Constructs an AnalyticsController instance.\n *\n * @param options - Controller options\n * @param options.state - Initial controller state. Must include a valid UUIDv4 `analyticsId`.\n * Use `getDefaultAnalyticsControllerState()` for default opt-in preferences.\n * @param options.messenger - Messenger used to communicate with BaseController\n * @param options.platformAdapter - Platform adapter implementation for tracking\n * @param options.isAnonymousEventsFeatureEnabled - Whether the anonymous events feature is enabled\n * @param options.isEventQueuePersistenceEnabled - Whether analytics event queue persistence is enabled\n * @param options.isPreConsentQueueEnabled - Whether the pre-consent event queue is enabled\n * @throws Error if state.analyticsId is missing or not a valid UUIDv4\n * @remarks After construction, call {@link AnalyticsController.init} to complete initialization.\n */\n constructor({\n state,\n messenger,\n platformAdapter,\n isAnonymousEventsFeatureEnabled = false,\n isEventQueuePersistenceEnabled = false,\n isPreConsentQueueEnabled = false,\n }: AnalyticsControllerOptions) {\n const initialState: AnalyticsControllerState = {\n ...getDefaultAnalyticsControllerState(),\n ...state,\n };\n\n validateAnalyticsControllerState(\n initialState,\n platformAdapter.skipUUIDv4Check === true,\n );\n\n super({\n name: controllerName,\n metadata: analyticsControllerMetadata,\n state: initialState,\n messenger,\n });\n\n this.#isAnonymousEventsFeatureEnabled = isAnonymousEventsFeatureEnabled;\n this.#isEventQueuePersistenceEnabled = isEventQueuePersistenceEnabled;\n this.#isPreConsentQueueEnabled = isPreConsentQueueEnabled;\n this.#platformAdapter = platformAdapter;\n this.#initialized = false;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n log('AnalyticsController initialized and ready', {\n enabled: analyticsControllerSelectors.selectEnabled(this.state),\n optedIn: this.state.optedIn,\n consentDecisionMade: this.state.consentDecisionMade,\n analyticsId: this.state.analyticsId,\n eventQueuePersistenceEnabled: this.#isEventQueuePersistenceEnabled,\n preConsentQueueEnabled: this.#isPreConsentQueueEnabled,\n });\n }\n\n /**\n * Initialize the controller by calling the platform adapter's onSetupCompleted lifecycle hook.\n * This method must be called after construction to complete the setup process.\n */\n init(): void {\n if (this.#initialized) {\n log('AnalyticsController already initialized.');\n return;\n }\n\n this.#initialized = true;\n\n // Call onSetupCompleted lifecycle hook after initialization\n // State is already validated, so analyticsId is guaranteed to be a valid UUIDv4\n try {\n this.#platformAdapter.onSetupCompleted(this.state.analyticsId);\n } catch (error) {\n // Log error but don't throw - adapter setup failure shouldn't break controller\n log('Error calling platformAdapter.onSetupCompleted', error);\n }\n\n this.#replayQueuedEvents();\n this.#reconcilePreConsentEvents();\n }\n\n /**\n * Send final track payload through the platform adapter or queue it if persistence is enabled.\n *\n * @param eventName - The name of the event.\n * @param properties - Optional event properties.\n * @param context - Optional platform-specific context.\n */\n #sendOrQueueTrackEvent(\n eventName: string,\n properties?: AnalyticsEventProperties,\n context?: AnalyticsContext,\n ): void {\n // Direct delivery: enabled and not persisting.\n if (\n analyticsControllerSelectors.selectEnabled(this.state) &&\n !this.#isEventQueuePersistenceEnabled\n ) {\n this.#platformAdapter.track(eventName, properties, context);\n return;\n }\n\n const queuedEvent: AnalyticsQueuedTrackEvent = {\n type: 'track',\n eventName,\n messageId: uuid(),\n timestamp: new Date().toISOString(),\n ...(properties === undefined ? {} : { properties }),\n ...(context === undefined ? {} : { context }),\n };\n\n // Not yet enabled (reached only while undecided with the pre-consent queue\n // enabled): hold the event until the user opts in.\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n this.#enqueuePreConsentEvent(queuedEvent);\n return;\n }\n\n this.#enqueueEvent(queuedEvent);\n }\n\n /**\n * Send final identify payload through the platform adapter or queue it if persistence is enabled.\n *\n * @param userId - The user ID.\n * @param traits - Optional user traits.\n * @param context - Optional platform-specific context.\n */\n #sendOrQueueIdentifyEvent(\n userId: string,\n traits?: AnalyticsUserTraits,\n context?: AnalyticsContext,\n ): void {\n if (!this.#isEventQueuePersistenceEnabled) {\n this.#platformAdapter.identify(userId, traits, context);\n return;\n }\n\n const queuedEvent: AnalyticsQueuedIdentifyEvent = {\n type: 'identify',\n userId,\n messageId: uuid(),\n timestamp: new Date().toISOString(),\n ...(traits === undefined ? {} : { traits }),\n ...(context === undefined ? {} : { context }),\n };\n\n this.#enqueueEvent(queuedEvent);\n }\n\n /**\n * Send final view payload through the platform adapter or queue it if persistence is enabled.\n *\n * @param name - The view name.\n * @param properties - Optional view properties.\n * @param context - Optional platform-specific context.\n */\n #sendOrQueueViewEvent(\n name: string,\n properties?: AnalyticsEventProperties,\n context?: AnalyticsContext,\n ): void {\n if (!this.#isEventQueuePersistenceEnabled) {\n this.#platformAdapter.view(name, properties, context);\n return;\n }\n\n const queuedEvent: AnalyticsQueuedViewEvent = {\n type: 'view',\n name,\n messageId: uuid(),\n timestamp: new Date().toISOString(),\n ...(properties === undefined ? {} : { properties }),\n ...(context === undefined ? {} : { context }),\n };\n\n this.#enqueueEvent(queuedEvent);\n }\n\n /**\n * Add an analytics event to the queue and send it.\n *\n * @param queuedEvent - The event to enqueue and deliver.\n */\n #enqueueEvent(queuedEvent: AnalyticsQueuedEvent): void {\n const eventQueue: Record<string, Json> = {\n ...(this.state.eventQueue ?? {}),\n [queuedEvent.messageId]: queuedEvent as unknown as Json,\n };\n\n this.update((state) => {\n state.eventQueue = eventQueue as never;\n });\n\n this.#sendQueuedEvent(queuedEvent);\n }\n\n /**\n * Send a queued event through the platform adapter.\n *\n * @param queuedEvent - The queued event to deliver.\n */\n #sendQueuedEvent(queuedEvent: AnalyticsQueuedEvent): void {\n const timestamp = new Date(queuedEvent.timestamp);\n\n if (Number.isNaN(timestamp.getTime())) {\n log('Dropping queued analytics event with invalid timestamp', {\n messageId: queuedEvent.messageId,\n });\n this.#removeQueuedEvent(queuedEvent.messageId);\n return;\n }\n\n const options: AnalyticsDeliveryOptions = {\n messageId: queuedEvent.messageId,\n timestamp,\n callback: (error?: unknown) => {\n if (error) {\n log('Queued analytics event delivery failed', {\n messageId: queuedEvent.messageId,\n error,\n });\n }\n\n this.#removeQueuedEvent(queuedEvent.messageId);\n },\n };\n\n try {\n if (queuedEvent.type === 'track') {\n this.#platformAdapter.track(\n queuedEvent.eventName,\n cloneDeep(queuedEvent.properties),\n cloneDeep(queuedEvent.context),\n options,\n );\n } else if (queuedEvent.type === 'identify') {\n this.#platformAdapter.identify(\n queuedEvent.userId,\n cloneDeep(queuedEvent.traits),\n cloneDeep(queuedEvent.context),\n options,\n );\n } else {\n this.#platformAdapter.view(\n queuedEvent.name,\n cloneDeep(queuedEvent.properties),\n cloneDeep(queuedEvent.context),\n options,\n );\n }\n } catch (error) {\n log('Error sending queued analytics event', {\n messageId: queuedEvent.messageId,\n error,\n });\n }\n }\n\n /**\n * Replay persisted analytics events.\n */\n #replayQueuedEvents(): void {\n if (!this.#isEventQueuePersistenceEnabled || !this.state.eventQueue) {\n return;\n }\n\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n this.#clearQueuedEvents();\n return;\n }\n\n for (const [messageId, queuedEvent] of Object.entries(\n this.state.eventQueue,\n )) {\n if (\n !isAnalyticsQueuedEvent(queuedEvent) ||\n queuedEvent.messageId !== messageId\n ) {\n log('Dropping invalid queued analytics event', { messageId });\n this.#removeQueuedEvent(messageId);\n continue;\n }\n\n this.#sendQueuedEvent(queuedEvent);\n }\n }\n\n /**\n * Remove a queued analytics event.\n *\n * @param messageId - The queued event message ID.\n */\n #removeQueuedEvent(messageId: string): void {\n const currentEventQueue = this.state.eventQueue;\n\n if (\n !currentEventQueue ||\n !Object.prototype.hasOwnProperty.call(currentEventQueue, messageId)\n ) {\n return;\n }\n\n const { [messageId]: _deletedEvent, ...eventQueue } = currentEventQueue;\n\n this.update((state) => {\n state.eventQueue = eventQueue as never;\n });\n }\n\n /**\n * Clear all queued analytics events.\n */\n #clearQueuedEvents(): void {\n if (\n !this.state.eventQueue ||\n Object.keys(this.state.eventQueue).length === 0\n ) {\n return;\n }\n\n this.update((state) => {\n state.eventQueue = {} as never;\n });\n }\n\n /**\n * Add an event to the pre-consent queue without delivering it.\n *\n * @param queuedEvent - The event to hold until the user opts in.\n */\n #enqueuePreConsentEvent(queuedEvent: AnalyticsQueuedEvent): void {\n const preConsentEventQueue: Record<string, Json> = {\n ...(this.state.preConsentEventQueue ?? {}),\n [queuedEvent.messageId]: queuedEvent as unknown as Json,\n };\n\n this.update((state) => {\n state.preConsentEventQueue = preConsentEventQueue as never;\n });\n }\n\n /**\n * Replay queued pre-consent events through the delivery path.\n *\n * Called on opt-in, once analytics is enabled. The queue is cleared before\n * replaying so events cannot be re-queued or replayed twice.\n */\n #replayPreConsentEvents(): void {\n if (!this.#isPreConsentQueueEnabled) {\n return;\n }\n\n const queue = this.state.preConsentEventQueue;\n\n if (!queue) {\n return;\n }\n\n this.#clearPreConsentEvents();\n\n for (const [messageId, queuedEvent] of Object.entries(queue)) {\n if (\n !isAnalyticsQueuedEvent(queuedEvent) ||\n queuedEvent.messageId !== messageId\n ) {\n log('Dropping invalid queued pre-consent analytics event', {\n messageId,\n });\n continue;\n }\n\n if (this.#isEventQueuePersistenceEnabled) {\n this.#enqueueEvent(queuedEvent);\n } else {\n this.#sendQueuedEvent(queuedEvent);\n }\n }\n }\n\n /**\n * Clear all queued pre-consent events.\n */\n #clearPreConsentEvents(): void {\n if (!this.state.preConsentEventQueue) {\n return;\n }\n\n this.update((state) => {\n state.preConsentEventQueue = {} as never;\n });\n }\n\n /**\n * Reconcile the pre-consent queue on initialization.\n *\n * The queue should normally be empty unless the user is still undecided. This\n * handles the rare cases where a consent decision was persisted but the queue\n * was not flushed/cleared (e.g. an interrupted shutdown): replay it if the\n * user is opted in, or clear it if they opted out.\n *\n * If the pre-consent queue is disabled, any stale persisted entries (e.g. from\n * a previous session where it was enabled) are dropped so they can never be\n * replayed.\n */\n #reconcilePreConsentEvents(): void {\n const queue = this.state.preConsentEventQueue;\n\n if (!queue) {\n return;\n }\n\n if (!this.#isPreConsentQueueEnabled) {\n this.#clearPreConsentEvents();\n return;\n }\n\n if (this.state.optedIn) {\n this.#replayPreConsentEvents();\n } else if (this.state.consentDecisionMade) {\n this.#clearPreConsentEvents();\n }\n }\n\n /**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param event - Analytics event with properties and sensitive properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\n trackEvent(event: AnalyticsTrackingEvent, context?: AnalyticsContext): void {\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n // While the user is undecided, fall through so the event is processed and\n // captured in the pre-consent queue (see #sendOrQueueTrackEvent) to be\n // replayed if they later opt in. Otherwise (opted out, or pre-consent\n // queue disabled) drop it.\n const shouldQueuePreConsent =\n this.#isPreConsentQueueEnabled && !this.state.consentDecisionMade;\n if (!shouldQueuePreConsent) {\n return;\n }\n }\n\n // if event does not have properties, send event without properties\n // and return to prevent any additional processing\n if (!event.hasProperties) {\n this.#sendOrQueueTrackEvent(event.name, undefined, context);\n return;\n }\n\n // Track regular properties first if anonymous events feature is enabled\n if (this.#isAnonymousEventsFeatureEnabled) {\n // Note: Even if regular properties object is empty, we still send it to ensure\n // an event with user ID is tracked.\n this.#sendOrQueueTrackEvent(\n event.name,\n {\n ...event.properties,\n },\n context,\n );\n }\n\n const hasSensitiveProperties =\n Object.keys(event.sensitiveProperties).length > 0;\n\n if (!this.#isAnonymousEventsFeatureEnabled || hasSensitiveProperties) {\n this.#sendOrQueueTrackEvent(\n event.name,\n {\n ...event.properties,\n ...event.sensitiveProperties,\n ...(hasSensitiveProperties && { anonymous: true }),\n },\n context,\n );\n }\n }\n\n /**\n * Identify a user for analytics.\n *\n * @param traits - User traits/properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\n identify(traits?: AnalyticsUserTraits, context?: AnalyticsContext): void {\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n return;\n }\n\n // Delegate to platform adapter using the current analytics ID\n this.#sendOrQueueIdentifyEvent(this.state.analyticsId, traits, context);\n }\n\n /**\n * Track a page or screen view.\n *\n * @param name - The identifier/name of the page or screen being viewed (e.g., \"home\", \"settings\", \"wallet\")\n * @param properties - Optional properties associated with the view\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\n trackView(\n name: string,\n properties?: AnalyticsEventProperties,\n context?: AnalyticsContext,\n ): void {\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n return;\n }\n\n // Delegate to platform adapter\n this.#sendOrQueueViewEvent(name, properties, context);\n }\n\n /**\n * Opt in to analytics.\n *\n * Records that a consent decision has been made and replays any events that\n * were queued while the user was undecided.\n */\n optIn(): void {\n this.update((state) => {\n state.optedIn = true;\n state.consentDecisionMade = true;\n });\n\n this.#replayPreConsentEvents();\n }\n\n /**\n * Opt out of analytics.\n *\n * Records that a consent decision has been made and discards any persisted\n * events so nothing captured before the decision is ever delivered.\n */\n optOut(): void {\n this.update((state) => {\n state.optedIn = false;\n state.consentDecisionMade = true;\n });\n\n this.#clearQueuedEvents();\n this.#clearPreConsentEvents();\n }\n\n /**\n * Reset the consent decision back to undecided.\n *\n * Intended for client flows that restart onboarding. Clears the opt-in\n * preference and discards both the delivery queue and any pre-consent events,\n * so nothing captured before the reset is delivered and the user is treated\n * as undecided again.\n */\n resetConsentDecision(): void {\n this.update((state) => {\n state.optedIn = false;\n state.consentDecisionMade = false;\n });\n\n this.#clearQueuedEvents();\n this.#clearPreConsentEvents();\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AnalyticsController.cjs","sourceRoot":"","sources":["../src/AnalyticsController.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ControllerGetStateAction,\n ControllerStateChangeEvent,\n StateMetadata,\n} from '@metamask/base-controller';\nimport { BaseController } from '@metamask/base-controller';\nimport type { Messenger } from '@metamask/messenger';\nimport type { Json } from '@metamask/utils';\nimport { cloneDeep } from 'lodash';\nimport { v4 as uuid } from 'uuid';\n\nimport type { AnalyticsControllerMethodActions } from './AnalyticsController-method-action-types';\nimport { validateAnalyticsControllerState } from './analyticsControllerStateValidator';\nimport { projectLogger as log } from './AnalyticsLogger';\nimport type {\n AnalyticsPlatformAdapter,\n AnalyticsDeliveryOptions,\n AnalyticsContext,\n AnalyticsEventProperties,\n AnalyticsUserTraits,\n AnalyticsTrackingEvent,\n} from './AnalyticsPlatformAdapter.types';\nimport { analyticsControllerSelectors } from './selectors';\n\n// === GENERAL ===\n\n/**\n * The name of the {@link AnalyticsController}, used to namespace the\n * controller's actions and events and to namespace the controller's state data\n * when composed with other controllers.\n */\nexport const controllerName = 'AnalyticsController';\n\n// === STATE ===\n\n/**\n * Describes the shape of the state object for {@link AnalyticsController}.\n */\nexport type AnalyticsControllerState = {\n /**\n * Whether the user has opted in to analytics.\n */\n optedIn: boolean;\n\n /**\n * User's UUIDv4 analytics identifier.\n * This is an identity (unique per user), not a preference.\n * Must be provided by the platform - the controller does not generate it.\n */\n analyticsId: string;\n\n /**\n * Persisted queue of analytics events waiting for delivery acknowledgement.\n * This is only used when event queue persistence is enabled.\n */\n eventQueue?: Record<string, Json>;\n};\n\n/**\n * Event types supported by the persisted analytics event queue.\n */\nexport type AnalyticsQueuedEventType = 'track' | 'identify' | 'view';\n\n/**\n * Base persisted event queue entry.\n */\nexport type AnalyticsQueuedEventBase = {\n /**\n * Event type used to replay the payload with the platform adapter.\n */\n type: AnalyticsQueuedEventType;\n\n /**\n * Stable identifier for the analytics payload.\n */\n messageId: string;\n\n /**\n * Original payload timestamp serialized for persistence.\n */\n timestamp: string;\n};\n\n/**\n * Persisted track event queue entry.\n */\nexport type AnalyticsQueuedTrackEvent = AnalyticsQueuedEventBase & {\n type: 'track';\n eventName: string;\n properties?: AnalyticsEventProperties;\n context?: AnalyticsContext;\n};\n\n/**\n * Persisted identify event queue entry.\n */\nexport type AnalyticsQueuedIdentifyEvent = AnalyticsQueuedEventBase & {\n type: 'identify';\n userId: string;\n traits?: AnalyticsUserTraits;\n context?: AnalyticsContext;\n};\n\n/**\n * Persisted view event queue entry.\n */\nexport type AnalyticsQueuedViewEvent = AnalyticsQueuedEventBase & {\n type: 'view';\n name: string;\n properties?: AnalyticsEventProperties;\n context?: AnalyticsContext;\n};\n\n/**\n * Persisted analytics event queue entry.\n */\nexport type AnalyticsQueuedEvent =\n | AnalyticsQueuedTrackEvent\n | AnalyticsQueuedIdentifyEvent\n | AnalyticsQueuedViewEvent;\n\n/**\n * Persisted analytics event queue keyed by message ID.\n */\nexport type AnalyticsEventQueue = Record<string, AnalyticsQueuedEvent>;\n\n/**\n * Returns default values for AnalyticsController state.\n *\n * Note: analyticsId is NOT included - it's an identity that must be\n * provided by the platform (generated once on first run, then persisted).\n *\n * @returns Default state without analyticsId\n */\nexport function getDefaultAnalyticsControllerState(): Omit<\n AnalyticsControllerState,\n 'analyticsId'\n> {\n return {\n optedIn: false,\n };\n}\n\n/**\n * The metadata for each property in {@link AnalyticsControllerState}.\n *\n * Both `optedIn` and `analyticsId` are persisted (`persist: true`).\n * The platform must supply a valid UUIDv4 `analyticsId` on first run.\n */\nconst analyticsControllerMetadata = {\n optedIn: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: true,\n },\n analyticsId: {\n includeInStateLogs: true,\n persist: true,\n includeInDebugSnapshot: true,\n usedInUi: false,\n },\n eventQueue: {\n includeInStateLogs: false,\n persist: true,\n includeInDebugSnapshot: false,\n usedInUi: false,\n },\n} satisfies StateMetadata<AnalyticsControllerState>;\n\n// === MESSENGER ===\n\nconst MESSENGER_EXPOSED_METHODS = [\n 'trackEvent',\n 'identify',\n 'trackView',\n 'optIn',\n 'optOut',\n] as const;\n\n/**\n * Returns the state of the {@link AnalyticsController}.\n */\nexport type AnalyticsControllerGetStateAction = ControllerGetStateAction<\n typeof controllerName,\n AnalyticsControllerState\n>;\n\n/**\n * Actions that {@link AnalyticsControllerMessenger} exposes to other consumers.\n */\nexport type AnalyticsControllerActions =\n | AnalyticsControllerGetStateAction\n | AnalyticsControllerMethodActions;\n\n/**\n * Actions from other messengers that {@link AnalyticsControllerMessenger} calls.\n */\ntype AllowedActions = never;\n\n/**\n * Event emitted when the state of the {@link AnalyticsController} changes.\n */\nexport type AnalyticsControllerStateChangeEvent = ControllerStateChangeEvent<\n typeof controllerName,\n AnalyticsControllerState\n>;\n\n/**\n * Events that {@link AnalyticsControllerMessenger} exposes to other consumers.\n */\nexport type AnalyticsControllerEvents = AnalyticsControllerStateChangeEvent;\n\n/**\n * Events from other messengers that {@link AnalyticsControllerMessenger} subscribes to.\n */\ntype AllowedEvents = never;\n\n/**\n * The messenger restricted to actions and events accessed by\n * {@link AnalyticsController}.\n */\nexport type AnalyticsControllerMessenger = Messenger<\n typeof controllerName,\n AnalyticsControllerActions | AllowedActions,\n AnalyticsControllerEvents | AllowedEvents\n>;\n\n// === CONTROLLER DEFINITION ===\n\n/**\n * The options that AnalyticsController takes.\n */\nexport type AnalyticsControllerOptions = {\n /**\n * Initial controller state. Must include a valid UUIDv4 `analyticsId`.\n * The platform is responsible for generating the ID on first run.\n * It is then persisted with controller state when using a persisted store.\n */\n state: AnalyticsControllerState;\n /**\n * Messenger used to communicate with BaseController and other controllers.\n */\n messenger: AnalyticsControllerMessenger;\n /**\n * Platform adapter implementation for tracking events.\n */\n platformAdapter: AnalyticsPlatformAdapter;\n\n /**\n * Whether the anonymous events feature is enabled.\n *\n * @default false\n */\n isAnonymousEventsFeatureEnabled?: boolean;\n\n /**\n * Whether analytics event queue persistence is enabled.\n *\n * When enabled, AnalyticsController persists each platform adapter payload\n * until the adapter reports successful delivery.\n *\n * @default false\n */\n isEventQueuePersistenceEnabled?: boolean;\n};\n\n/**\n * Returns whether a value is a non-array object.\n *\n * @param value - The value to check.\n * @returns True if the value is a record.\n */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value);\n}\n\n/**\n * Returns whether a value is a valid persisted analytics event.\n *\n * @param value - The value to check.\n * @returns True if the value is a queued analytics event.\n */\nfunction isAnalyticsQueuedEvent(value: unknown): value is AnalyticsQueuedEvent {\n if (!isRecord(value)) {\n return false;\n }\n\n if (\n typeof value.messageId !== 'string' ||\n typeof value.timestamp !== 'string'\n ) {\n return false;\n }\n\n if (value.type === 'track') {\n return (\n typeof value.eventName === 'string' &&\n (value.properties === undefined || isRecord(value.properties)) &&\n (value.context === undefined || isRecord(value.context))\n );\n }\n\n if (value.type === 'identify') {\n return (\n typeof value.userId === 'string' &&\n (value.traits === undefined || isRecord(value.traits)) &&\n (value.context === undefined || isRecord(value.context))\n );\n }\n\n if (value.type === 'view') {\n return (\n typeof value.name === 'string' &&\n (value.properties === undefined || isRecord(value.properties)) &&\n (value.context === undefined || isRecord(value.context))\n );\n }\n\n return false;\n}\n\n/**\n * The AnalyticsController manages analytics tracking across platforms (Mobile/Extension).\n * It provides a unified interface for tracking events, identifying users, and managing\n * analytics preferences while delegating platform-specific implementation to an\n * {@link AnalyticsPlatformAdapter}.\n *\n * This controller follows the MetaMask controller pattern and integrates with the\n * messenger system to allow other controllers and components to track analytics events.\n * It delegates platform-specific implementation to an {@link AnalyticsPlatformAdapter}.\n *\n * The controller persists `optedIn` and `analyticsId` when composed with a persisted\n * store. The platform must supply a valid `analyticsId` on first launch.\n */\nexport class AnalyticsController extends BaseController<\n 'AnalyticsController',\n AnalyticsControllerState,\n AnalyticsControllerMessenger\n> {\n readonly #platformAdapter: AnalyticsPlatformAdapter;\n\n readonly #isAnonymousEventsFeatureEnabled: boolean;\n\n readonly #isEventQueuePersistenceEnabled: boolean;\n\n #initialized: boolean;\n\n /**\n * Constructs an AnalyticsController instance.\n *\n * @param options - Controller options\n * @param options.state - Initial controller state. Must include a valid UUIDv4 `analyticsId`.\n * Use `getDefaultAnalyticsControllerState()` for default opt-in preferences.\n * @param options.messenger - Messenger used to communicate with BaseController\n * @param options.platformAdapter - Platform adapter implementation for tracking\n * @param options.isAnonymousEventsFeatureEnabled - Whether the anonymous events feature is enabled\n * @param options.isEventQueuePersistenceEnabled - Whether analytics event queue persistence is enabled\n * @throws Error if state.analyticsId is missing or not a valid UUIDv4\n * @remarks After construction, call {@link AnalyticsController.init} to complete initialization.\n */\n constructor({\n state,\n messenger,\n platformAdapter,\n isAnonymousEventsFeatureEnabled = false,\n isEventQueuePersistenceEnabled = false,\n }: AnalyticsControllerOptions) {\n const initialState: AnalyticsControllerState = {\n ...getDefaultAnalyticsControllerState(),\n ...state,\n };\n\n validateAnalyticsControllerState(\n initialState,\n platformAdapter.skipUUIDv4Check === true,\n );\n\n super({\n name: controllerName,\n metadata: analyticsControllerMetadata,\n state: initialState,\n messenger,\n });\n\n this.#isAnonymousEventsFeatureEnabled = isAnonymousEventsFeatureEnabled;\n this.#isEventQueuePersistenceEnabled = isEventQueuePersistenceEnabled;\n this.#platformAdapter = platformAdapter;\n this.#initialized = false;\n\n this.messenger.registerMethodActionHandlers(\n this,\n MESSENGER_EXPOSED_METHODS,\n );\n\n log('AnalyticsController initialized and ready', {\n enabled: analyticsControllerSelectors.selectEnabled(this.state),\n optedIn: this.state.optedIn,\n analyticsId: this.state.analyticsId,\n eventQueuePersistenceEnabled: this.#isEventQueuePersistenceEnabled,\n });\n }\n\n /**\n * Initialize the controller by calling the platform adapter's onSetupCompleted lifecycle hook.\n * This method must be called after construction to complete the setup process.\n */\n init(): void {\n if (this.#initialized) {\n log('AnalyticsController already initialized.');\n return;\n }\n\n this.#initialized = true;\n\n // Call onSetupCompleted lifecycle hook after initialization\n // State is already validated, so analyticsId is guaranteed to be a valid UUIDv4\n try {\n this.#platformAdapter.onSetupCompleted(this.state.analyticsId);\n } catch (error) {\n // Log error but don't throw - adapter setup failure shouldn't break controller\n log('Error calling platformAdapter.onSetupCompleted', error);\n }\n\n this.#replayQueuedEvents();\n }\n\n /**\n * Send final track payload through the platform adapter or queue it if persistence is enabled.\n *\n * @param eventName - The name of the event.\n * @param properties - Optional event properties.\n * @param context - Optional platform-specific context.\n */\n #sendOrQueueTrackEvent(\n eventName: string,\n properties?: AnalyticsEventProperties,\n context?: AnalyticsContext,\n ): void {\n if (!this.#isEventQueuePersistenceEnabled) {\n this.#platformAdapter.track(eventName, properties, context);\n return;\n }\n\n const queuedEvent: AnalyticsQueuedTrackEvent = {\n type: 'track',\n eventName,\n messageId: uuid(),\n timestamp: new Date().toISOString(),\n ...(properties === undefined ? {} : { properties }),\n ...(context === undefined ? {} : { context }),\n };\n\n this.#enqueueEvent(queuedEvent);\n }\n\n /**\n * Send final identify payload through the platform adapter or queue it if persistence is enabled.\n *\n * @param userId - The user ID.\n * @param traits - Optional user traits.\n * @param context - Optional platform-specific context.\n */\n #sendOrQueueIdentifyEvent(\n userId: string,\n traits?: AnalyticsUserTraits,\n context?: AnalyticsContext,\n ): void {\n if (!this.#isEventQueuePersistenceEnabled) {\n this.#platformAdapter.identify(userId, traits, context);\n return;\n }\n\n const queuedEvent: AnalyticsQueuedIdentifyEvent = {\n type: 'identify',\n userId,\n messageId: uuid(),\n timestamp: new Date().toISOString(),\n ...(traits === undefined ? {} : { traits }),\n ...(context === undefined ? {} : { context }),\n };\n\n this.#enqueueEvent(queuedEvent);\n }\n\n /**\n * Send final view payload through the platform adapter or queue it if persistence is enabled.\n *\n * @param name - The view name.\n * @param properties - Optional view properties.\n * @param context - Optional platform-specific context.\n */\n #sendOrQueueViewEvent(\n name: string,\n properties?: AnalyticsEventProperties,\n context?: AnalyticsContext,\n ): void {\n if (!this.#isEventQueuePersistenceEnabled) {\n this.#platformAdapter.view(name, properties, context);\n return;\n }\n\n const queuedEvent: AnalyticsQueuedViewEvent = {\n type: 'view',\n name,\n messageId: uuid(),\n timestamp: new Date().toISOString(),\n ...(properties === undefined ? {} : { properties }),\n ...(context === undefined ? {} : { context }),\n };\n\n this.#enqueueEvent(queuedEvent);\n }\n\n /**\n * Add an analytics event to the queue and send it.\n *\n * @param queuedEvent - The event to enqueue and deliver.\n */\n #enqueueEvent(queuedEvent: AnalyticsQueuedEvent): void {\n const eventQueue: Record<string, Json> = {\n ...(this.state.eventQueue ?? {}),\n [queuedEvent.messageId]: queuedEvent as unknown as Json,\n };\n\n this.update((state) => {\n state.eventQueue = eventQueue as never;\n });\n\n this.#sendQueuedEvent(queuedEvent);\n }\n\n /**\n * Send a queued event through the platform adapter.\n *\n * @param queuedEvent - The queued event to deliver.\n */\n #sendQueuedEvent(queuedEvent: AnalyticsQueuedEvent): void {\n const timestamp = new Date(queuedEvent.timestamp);\n\n if (Number.isNaN(timestamp.getTime())) {\n log('Dropping queued analytics event with invalid timestamp', {\n messageId: queuedEvent.messageId,\n });\n this.#removeQueuedEvent(queuedEvent.messageId);\n return;\n }\n\n const options: AnalyticsDeliveryOptions = {\n messageId: queuedEvent.messageId,\n timestamp,\n callback: (error?: unknown) => {\n if (error) {\n log('Queued analytics event delivery failed', {\n messageId: queuedEvent.messageId,\n error,\n });\n }\n\n this.#removeQueuedEvent(queuedEvent.messageId);\n },\n };\n\n try {\n if (queuedEvent.type === 'track') {\n this.#platformAdapter.track(\n queuedEvent.eventName,\n cloneDeep(queuedEvent.properties),\n cloneDeep(queuedEvent.context),\n options,\n );\n } else if (queuedEvent.type === 'identify') {\n this.#platformAdapter.identify(\n queuedEvent.userId,\n cloneDeep(queuedEvent.traits),\n cloneDeep(queuedEvent.context),\n options,\n );\n } else {\n this.#platformAdapter.view(\n queuedEvent.name,\n cloneDeep(queuedEvent.properties),\n cloneDeep(queuedEvent.context),\n options,\n );\n }\n } catch (error) {\n log('Error sending queued analytics event', {\n messageId: queuedEvent.messageId,\n error,\n });\n }\n }\n\n /**\n * Replay persisted analytics events.\n */\n #replayQueuedEvents(): void {\n if (!this.#isEventQueuePersistenceEnabled || !this.state.eventQueue) {\n return;\n }\n\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n this.#clearQueuedEvents();\n return;\n }\n\n for (const [messageId, queuedEvent] of Object.entries(\n this.state.eventQueue,\n )) {\n if (\n !isAnalyticsQueuedEvent(queuedEvent) ||\n queuedEvent.messageId !== messageId\n ) {\n log('Dropping invalid queued analytics event', { messageId });\n this.#removeQueuedEvent(messageId);\n continue;\n }\n\n this.#sendQueuedEvent(queuedEvent);\n }\n }\n\n /**\n * Remove a queued analytics event.\n *\n * @param messageId - The queued event message ID.\n */\n #removeQueuedEvent(messageId: string): void {\n const currentEventQueue = this.state.eventQueue;\n\n if (\n !currentEventQueue ||\n !Object.prototype.hasOwnProperty.call(currentEventQueue, messageId)\n ) {\n return;\n }\n\n const { [messageId]: _deletedEvent, ...eventQueue } = currentEventQueue;\n\n this.update((state) => {\n state.eventQueue = eventQueue as never;\n });\n }\n\n /**\n * Clear all queued analytics events.\n */\n #clearQueuedEvents(): void {\n if (\n !this.state.eventQueue ||\n Object.keys(this.state.eventQueue).length === 0\n ) {\n return;\n }\n\n this.update((state) => {\n state.eventQueue = {} as never;\n });\n }\n\n /**\n * Track an analytics event.\n *\n * Events are only tracked if analytics is enabled.\n *\n * @param event - Analytics event with properties and sensitive properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\n trackEvent(event: AnalyticsTrackingEvent, context?: AnalyticsContext): void {\n // Don't track if analytics is disabled\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n return;\n }\n\n // if event does not have properties, send event without properties\n // and return to prevent any additional processing\n if (!event.hasProperties) {\n this.#sendOrQueueTrackEvent(event.name, undefined, context);\n return;\n }\n\n // Track regular properties first if anonymous events feature is enabled\n if (this.#isAnonymousEventsFeatureEnabled) {\n // Note: Even if regular properties object is empty, we still send it to ensure\n // an event with user ID is tracked.\n this.#sendOrQueueTrackEvent(\n event.name,\n {\n ...event.properties,\n },\n context,\n );\n }\n\n const hasSensitiveProperties =\n Object.keys(event.sensitiveProperties).length > 0;\n\n if (!this.#isAnonymousEventsFeatureEnabled || hasSensitiveProperties) {\n this.#sendOrQueueTrackEvent(\n event.name,\n {\n ...event.properties,\n ...event.sensitiveProperties,\n ...(hasSensitiveProperties && { anonymous: true }),\n },\n context,\n );\n }\n }\n\n /**\n * Identify a user for analytics.\n *\n * @param traits - User traits/properties\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\n identify(traits?: AnalyticsUserTraits, context?: AnalyticsContext): void {\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n return;\n }\n\n // Delegate to platform adapter using the current analytics ID\n this.#sendOrQueueIdentifyEvent(this.state.analyticsId, traits, context);\n }\n\n /**\n * Track a page or screen view.\n *\n * @param name - The identifier/name of the page or screen being viewed (e.g., \"home\", \"settings\", \"wallet\")\n * @param properties - Optional properties associated with the view\n * @param context - Optional platform-specific context forwarded to the platform adapter.\n */\n trackView(\n name: string,\n properties?: AnalyticsEventProperties,\n context?: AnalyticsContext,\n ): void {\n if (!analyticsControllerSelectors.selectEnabled(this.state)) {\n return;\n }\n\n // Delegate to platform adapter\n this.#sendOrQueueViewEvent(name, properties, context);\n }\n\n /**\n * Opt in to analytics.\n */\n optIn(): void {\n this.update((state) => {\n state.optedIn = true;\n });\n }\n\n /**\n * Opt out of analytics.\n */\n optOut(): void {\n this.update((state) => {\n state.optedIn = false;\n });\n\n this.#clearQueuedEvents();\n }\n}\n"]}
|