@formo/analytics 1.19.10 → 1.21.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.
Files changed (55) hide show
  1. package/README.md +3 -1
  2. package/dist/cjs/src/FormoAnalytics.d.ts +17 -1
  3. package/dist/cjs/src/FormoAnalytics.js +150 -82
  4. package/dist/cjs/src/FormoAnalyticsProvider.js +5 -1
  5. package/dist/cjs/src/constants/base.d.ts +4 -0
  6. package/dist/cjs/src/constants/base.js +8 -1
  7. package/dist/cjs/src/lib/browser/browsers.d.ts +3 -0
  8. package/dist/cjs/src/lib/browser/browsers.js +132 -0
  9. package/dist/cjs/src/lib/consent.d.ts +35 -0
  10. package/dist/cjs/src/lib/consent.js +102 -0
  11. package/dist/cjs/src/lib/event/EventFactory.d.ts +10 -10
  12. package/dist/cjs/src/lib/event/EventFactory.js +272 -140
  13. package/dist/cjs/src/lib/event/EventManager.d.ts +1 -1
  14. package/dist/cjs/src/lib/event/EventManager.js +62 -9
  15. package/dist/cjs/src/lib/event/type.d.ts +2 -2
  16. package/dist/cjs/src/lib/index.d.ts +1 -0
  17. package/dist/cjs/src/lib/index.js +1 -0
  18. package/dist/cjs/src/lib/storage/built-in/blueprint.js +2 -1
  19. package/dist/cjs/src/lib/version.d.ts +1 -1
  20. package/dist/cjs/src/lib/version.js +1 -1
  21. package/dist/cjs/src/types/base.d.ts +3 -0
  22. package/dist/cjs/src/utils/address.d.ts +7 -0
  23. package/dist/cjs/src/utils/address.js +21 -1
  24. package/dist/cjs/src/utils/hash.d.ts +10 -0
  25. package/dist/cjs/src/utils/hash.js +21 -0
  26. package/dist/cjs/src/utils/index.d.ts +1 -0
  27. package/dist/cjs/src/utils/index.js +1 -0
  28. package/dist/esm/src/FormoAnalytics.d.ts +17 -1
  29. package/dist/esm/src/FormoAnalytics.js +152 -84
  30. package/dist/esm/src/FormoAnalyticsProvider.js +5 -1
  31. package/dist/esm/src/constants/base.d.ts +4 -0
  32. package/dist/esm/src/constants/base.js +7 -0
  33. package/dist/esm/src/lib/browser/browsers.d.ts +3 -0
  34. package/dist/esm/src/lib/browser/browsers.js +129 -0
  35. package/dist/esm/src/lib/consent.d.ts +35 -0
  36. package/dist/esm/src/lib/consent.js +97 -0
  37. package/dist/esm/src/lib/event/EventFactory.d.ts +10 -10
  38. package/dist/esm/src/lib/event/EventFactory.js +272 -140
  39. package/dist/esm/src/lib/event/EventManager.d.ts +1 -1
  40. package/dist/esm/src/lib/event/EventManager.js +62 -9
  41. package/dist/esm/src/lib/event/type.d.ts +2 -2
  42. package/dist/esm/src/lib/index.d.ts +1 -0
  43. package/dist/esm/src/lib/index.js +1 -0
  44. package/dist/esm/src/lib/storage/built-in/blueprint.js +2 -1
  45. package/dist/esm/src/lib/version.d.ts +1 -1
  46. package/dist/esm/src/lib/version.js +1 -1
  47. package/dist/esm/src/types/base.d.ts +3 -0
  48. package/dist/esm/src/utils/address.d.ts +7 -0
  49. package/dist/esm/src/utils/address.js +19 -0
  50. package/dist/esm/src/utils/hash.d.ts +10 -0
  51. package/dist/esm/src/utils/hash.js +18 -0
  52. package/dist/esm/src/utils/index.d.ts +1 -0
  53. package/dist/esm/src/utils/index.js +1 -0
  54. package/dist/index.umd.min.js +1 -1
  55. package/package.json +2 -2
@@ -1,12 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_PROVIDER_ICON = exports.LOCAL_ANONYMOUS_ID_KEY = exports.SESSION_USER_ID_KEY = exports.SESSION_CURRENT_URL_KEY = exports.SESSION_WALLET_IDENTIFIED_KEY = exports.SESSION_WALLET_DETECTED_KEY = exports.SESSION_TRAFFIC_SOURCE_KEY = void 0;
3
+ exports.BLOCKED_ADDRESSES = exports.DEAD_ADDRESS = exports.ZERO_ADDRESS = exports.DEFAULT_PROVIDER_ICON = exports.CONSENT_OPT_OUT_KEY = exports.LOCAL_ANONYMOUS_ID_KEY = exports.SESSION_USER_ID_KEY = exports.SESSION_CURRENT_URL_KEY = exports.SESSION_WALLET_IDENTIFIED_KEY = exports.SESSION_WALLET_DETECTED_KEY = exports.SESSION_TRAFFIC_SOURCE_KEY = void 0;
4
4
  exports.SESSION_TRAFFIC_SOURCE_KEY = "traffic-source";
5
5
  exports.SESSION_WALLET_DETECTED_KEY = "wallet-detected";
6
6
  exports.SESSION_WALLET_IDENTIFIED_KEY = "wallet-identified";
7
7
  exports.SESSION_CURRENT_URL_KEY = "analytics-current-url";
8
8
  exports.SESSION_USER_ID_KEY = "user-id";
9
9
  exports.LOCAL_ANONYMOUS_ID_KEY = "anonymous-id";
10
+ // Consent management keys
11
+ exports.CONSENT_OPT_OUT_KEY = "opt-out-tracking";
10
12
  // Default provider icon (empty data URL)
11
13
  exports.DEFAULT_PROVIDER_ICON = 'data:image/svg+xml;base64,';
14
+ // Blocked addresses that should not emit events
15
+ exports.ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
16
+ exports.DEAD_ADDRESS = "0x000000000000000000000000000000000000dEaD";
17
+ // Array of all blocked addresses for easy checking
18
+ exports.BLOCKED_ADDRESSES = [exports.ZERO_ADDRESS, exports.DEAD_ADDRESS];
12
19
  //# sourceMappingURL=base.js.map
@@ -0,0 +1,3 @@
1
+ export type BrowserName = "brave" | "chrome" | "edge" | "firefox" | "safari" | "opera" | "unknown";
2
+ export declare function detectBrowser(): Promise<BrowserName>;
3
+ //# sourceMappingURL=browsers.d.ts.map
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __generator = (this && this.__generator) || function (thisArg, body) {
12
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
+ function verb(n) { return function (v) { return step([n, v]); }; }
15
+ function step(op) {
16
+ if (f) throw new TypeError("Generator is already executing.");
17
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
18
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19
+ if (y = 0, t) op = [op[0] & 2, t.value];
20
+ switch (op[0]) {
21
+ case 0: case 1: t = op; break;
22
+ case 4: _.label++; return { value: op[1], done: false };
23
+ case 5: _.label++; y = op[1]; op = [0]; continue;
24
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
+ default:
26
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
+ if (t[2]) _.ops.pop();
31
+ _.trys.pop(); continue;
32
+ }
33
+ op = body.call(thisArg, _);
34
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
+ }
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.detectBrowser = detectBrowser;
40
+ var inFlight = null;
41
+ var cached = null;
42
+ function getUA() {
43
+ try {
44
+ return typeof globalThis.navigator !== "undefined"
45
+ ? globalThis.navigator.userAgent
46
+ : "";
47
+ }
48
+ catch (_a) {
49
+ return "";
50
+ }
51
+ }
52
+ function isBraveHeuristic() {
53
+ return __awaiter(this, void 0, void 0, function () {
54
+ var nav, ok, _a, brands;
55
+ var _b, _c;
56
+ return __generator(this, function (_d) {
57
+ switch (_d.label) {
58
+ case 0:
59
+ nav = typeof globalThis.navigator !== "undefined"
60
+ ? globalThis.navigator
61
+ : undefined;
62
+ if (!nav)
63
+ return [2 /*return*/, false];
64
+ _d.label = 1;
65
+ case 1:
66
+ _d.trys.push([1, 4, , 5]);
67
+ if (!((_b = nav.brave) === null || _b === void 0 ? void 0 : _b.isBrave)) return [3 /*break*/, 3];
68
+ return [4 /*yield*/, nav.brave.isBrave().catch(function () { return false; })];
69
+ case 2:
70
+ ok = _d.sent();
71
+ if (ok)
72
+ return [2 /*return*/, true];
73
+ _d.label = 3;
74
+ case 3: return [3 /*break*/, 5];
75
+ case 4:
76
+ _a = _d.sent();
77
+ return [3 /*break*/, 5];
78
+ case 5:
79
+ try {
80
+ brands = (_c = nav.userAgentData) === null || _c === void 0 ? void 0 : _c.brands;
81
+ if (brands === null || brands === void 0 ? void 0 : brands.some(function (b) { return /Brave/i.test(b.brand); }))
82
+ return [2 /*return*/, true];
83
+ }
84
+ catch (_e) { }
85
+ try {
86
+ if (/Brave/i.test(nav.userAgent))
87
+ return [2 /*return*/, true];
88
+ }
89
+ catch (_f) { }
90
+ return [2 /*return*/, false];
91
+ }
92
+ });
93
+ });
94
+ }
95
+ function classifyNonBrave(ua) {
96
+ if (/Firefox\/\d+/i.test(ua))
97
+ return "firefox";
98
+ if (/Edg\/\d+/i.test(ua))
99
+ return "edge";
100
+ if (/OPR\/\d+/i.test(ua))
101
+ return "opera";
102
+ if (/Safari\/\d+/i.test(ua) && !/Chrome\/\d+/i.test(ua))
103
+ return "safari";
104
+ if (/Chrome\/\d+/i.test(ua))
105
+ return "chrome";
106
+ return "unknown";
107
+ }
108
+ function detectBrowser() {
109
+ var _this = this;
110
+ if (cached)
111
+ return Promise.resolve(cached);
112
+ if (inFlight)
113
+ return inFlight;
114
+ inFlight = (function () { return __awaiter(_this, void 0, void 0, function () {
115
+ var ua, brave;
116
+ return __generator(this, function (_a) {
117
+ switch (_a.label) {
118
+ case 0:
119
+ ua = getUA();
120
+ return [4 /*yield*/, isBraveHeuristic().catch(function () { return false; })];
121
+ case 1:
122
+ brave = _a.sent();
123
+ cached = brave ? "brave" : classifyNonBrave(ua);
124
+ return [2 /*return*/, cached];
125
+ }
126
+ });
127
+ }); })().finally(function () {
128
+ inFlight = null; // subsequent calls hit cache
129
+ });
130
+ return inFlight;
131
+ }
132
+ //# sourceMappingURL=browsers.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Consent management utilities for handling tracking consent flags in cookies.
3
+ * These functions bypass the consent-aware storage system to ensure consent
4
+ * preferences are always stored persistently for compliance purposes.
5
+ *
6
+ * All consent cookies are project-specific to avoid conflicts between different
7
+ * Formo projects on the same domain.
8
+ */
9
+ /**
10
+ * Set a consent flag directly in cookies, bypassing the consent-aware storage system.
11
+ * Uses cookies for consent storage to ensure:
12
+ * - Cross-domain/subdomain compatibility
13
+ * - Server-side accessibility for compliance auditing
14
+ * - Regulatory compliance (GDPR/CCPA requirements)
15
+ * - Explicit expiration handling
16
+ * - Project isolation (no conflicts between different Formo projects)
17
+ * @param projectId - The project identifier (writeKey)
18
+ * @param key - The cookie key
19
+ * @param value - The cookie value
20
+ */
21
+ export declare function setConsentFlag(projectId: string, key: string, value: string): void;
22
+ /**
23
+ * Get a consent flag directly from cookies, bypassing the consent-aware storage system
24
+ * @param projectId - The project identifier (writeKey)
25
+ * @param key - The cookie key
26
+ * @returns The cookie value or null if not found
27
+ */
28
+ export declare function getConsentFlag(projectId: string, key: string): string | null;
29
+ /**
30
+ * Remove a consent flag directly from cookies, bypassing the consent-aware storage system
31
+ * @param projectId - The project identifier (writeKey)
32
+ * @param key - The cookie key
33
+ */
34
+ export declare function removeConsentFlag(projectId: string, key: string): void;
35
+ //# sourceMappingURL=consent.d.ts.map
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ /**
3
+ * Consent management utilities for handling tracking consent flags in cookies.
4
+ * These functions bypass the consent-aware storage system to ensure consent
5
+ * preferences are always stored persistently for compliance purposes.
6
+ *
7
+ * All consent cookies are project-specific to avoid conflicts between different
8
+ * Formo projects on the same domain.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.setConsentFlag = setConsentFlag;
12
+ exports.getConsentFlag = getConsentFlag;
13
+ exports.removeConsentFlag = removeConsentFlag;
14
+ var hash_1 = require("../utils/hash");
15
+ /**
16
+ * Generate a project-specific cookie key to avoid conflicts between different Formo projects
17
+ * Uses hashed writeKey for privacy and security
18
+ * @param projectId - The project identifier (writeKey)
19
+ * @param key - The base cookie key
20
+ * @returns Project-specific cookie key
21
+ */
22
+ function getProjectSpecificKey(projectId, key) {
23
+ return "formo_".concat((0, hash_1.secureHash)(projectId), "_").concat(key);
24
+ }
25
+ /**
26
+ * Set a consent flag directly in cookies, bypassing the consent-aware storage system.
27
+ * Uses cookies for consent storage to ensure:
28
+ * - Cross-domain/subdomain compatibility
29
+ * - Server-side accessibility for compliance auditing
30
+ * - Regulatory compliance (GDPR/CCPA requirements)
31
+ * - Explicit expiration handling
32
+ * - Project isolation (no conflicts between different Formo projects)
33
+ * @param projectId - The project identifier (writeKey)
34
+ * @param key - The cookie key
35
+ * @param value - The cookie value
36
+ */
37
+ function setConsentFlag(projectId, key, value) {
38
+ var _a;
39
+ if (typeof document !== 'undefined') {
40
+ var projectSpecificKey = getProjectSpecificKey(projectId, key);
41
+ var expires = new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toUTCString(); // 1 year (GDPR compliant)
42
+ var isSecure = ((_a = window === null || window === void 0 ? void 0 : window.location) === null || _a === void 0 ? void 0 : _a.protocol) === 'https:';
43
+ // Enhanced privacy settings: Secure (HTTPS), SameSite=Strict for consent cookies
44
+ document.cookie = "".concat(projectSpecificKey, "=").concat(encodeURIComponent(value), "; expires=").concat(expires, "; path=/; SameSite=Strict").concat(isSecure ? '; Secure' : '');
45
+ }
46
+ }
47
+ /**
48
+ * Get a consent flag directly from cookies, bypassing the consent-aware storage system
49
+ * @param projectId - The project identifier (writeKey)
50
+ * @param key - The cookie key
51
+ * @returns The cookie value or null if not found
52
+ */
53
+ function getConsentFlag(projectId, key) {
54
+ if (typeof document === 'undefined')
55
+ return null;
56
+ var projectSpecificKey = getProjectSpecificKey(projectId, key);
57
+ var cookies = document.cookie.split(';');
58
+ for (var _i = 0, cookies_1 = cookies; _i < cookies_1.length; _i++) {
59
+ var cookie = cookies_1[_i];
60
+ var trimmed = cookie.trim();
61
+ var eqIdx = trimmed.indexOf('=');
62
+ if (eqIdx === -1)
63
+ continue;
64
+ var cookieKey = trimmed.substring(0, eqIdx);
65
+ var cookieValue = trimmed.substring(eqIdx + 1);
66
+ if (cookieKey === projectSpecificKey) {
67
+ return decodeURIComponent(cookieValue || '');
68
+ }
69
+ }
70
+ return null;
71
+ }
72
+ /**
73
+ * Remove a consent flag directly from cookies, bypassing the consent-aware storage system
74
+ * @param projectId - The project identifier (writeKey)
75
+ * @param key - The cookie key
76
+ */
77
+ function removeConsentFlag(projectId, key) {
78
+ var projectSpecificKey = getProjectSpecificKey(projectId, key);
79
+ deleteCookieDirectly(projectSpecificKey);
80
+ }
81
+ /**
82
+ * Delete a cookie directly, handling various domain scenarios
83
+ * @param cookieName - The name of the cookie to delete
84
+ */
85
+ function deleteCookieDirectly(cookieName) {
86
+ if (typeof document === 'undefined')
87
+ return;
88
+ // Clear from current domain/path
89
+ document.cookie = "".concat(cookieName, "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;");
90
+ // Try to clear from parent domain if it's a proper multi-level domain
91
+ if (typeof window !== 'undefined') {
92
+ var hostname = window.location.hostname;
93
+ var parts = hostname.split('.');
94
+ // Only try parent domain deletion for proper domains with multiple parts
95
+ // Skip localhost and single-level domains
96
+ if (parts.length >= 2 && hostname !== 'localhost') {
97
+ var domain = parts.slice(-2).join('.');
98
+ document.cookie = "".concat(cookieName, "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; domain=.").concat(domain, ";");
99
+ }
100
+ }
101
+ }
102
+ //# sourceMappingURL=consent.js.map
@@ -16,16 +16,16 @@ declare class EventFactory implements IEventFactory {
16
16
  */
17
17
  private getPageProperties;
18
18
  private getEnrichedEvent;
19
- generatePageEvent(category?: string, name?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
20
- generateDetectWalletEvent(providerName: string, rdns: string, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
21
- generateIdentifyEvent(providerName: string, rdns: string, address: Nullable<Address>, userId?: Nullable<string>, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
22
- generateConnectEvent(chainId: ChainID, address: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
23
- generateDisconnectEvent(chainId?: ChainID, address?: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
24
- generateChainChangedEvent(chainId: ChainID, address: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
25
- generateSignatureEvent(status: SignatureStatus, chainId: ChainID, address: Address, message: string, signatureHash?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
26
- generateTransactionEvent(status: TransactionStatus, chainId: ChainID, address: Address, data: string, to: string, value: string, transactionHash?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
27
- generateTrackEvent(event: string, properties?: IFormoEventProperties, context?: IFormoEventContext): IFormoEvent;
28
- create(event: APIEvent, address?: Address, userId?: string): IFormoEvent;
19
+ generatePageEvent(category?: string, name?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
20
+ generateDetectWalletEvent(providerName: string, rdns: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
21
+ generateIdentifyEvent(providerName: string, rdns: string, address: Nullable<Address>, userId?: Nullable<string>, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
22
+ generateConnectEvent(chainId: ChainID, address: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
23
+ generateDisconnectEvent(chainId?: ChainID, address?: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
24
+ generateChainChangedEvent(chainId: ChainID, address: Address, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
25
+ generateSignatureEvent(status: SignatureStatus, chainId: ChainID, address: Address, message: string, signatureHash?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
26
+ generateTransactionEvent(status: TransactionStatus, chainId: ChainID, address: Address, data: string, to: string, value: string, transactionHash?: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
27
+ generateTrackEvent(event: string, properties?: IFormoEventProperties, context?: IFormoEventContext): Promise<IFormoEvent>;
28
+ create(event: APIEvent, address?: Address, userId?: string): Promise<IFormoEvent>;
29
29
  }
30
30
  export { EventFactory };
31
31
  //# sourceMappingURL=EventFactory.d.ts.map