@formo/analytics-react-native 1.0.0 → 1.0.2

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 (63) hide show
  1. package/lib/commonjs/FormoAnalytics.js +141 -12
  2. package/lib/commonjs/FormoAnalytics.js.map +1 -1
  3. package/lib/commonjs/FormoAnalyticsProvider.js +3 -0
  4. package/lib/commonjs/FormoAnalyticsProvider.js.map +1 -1
  5. package/lib/commonjs/constants/events.js +30 -3
  6. package/lib/commonjs/constants/events.js.map +1 -1
  7. package/lib/commonjs/lib/crash/index.js +121 -0
  8. package/lib/commonjs/lib/crash/index.js.map +1 -0
  9. package/lib/commonjs/lib/event/EventFactory.js +88 -8
  10. package/lib/commonjs/lib/event/EventFactory.js.map +1 -1
  11. package/lib/commonjs/lib/lifecycle/index.js +29 -6
  12. package/lib/commonjs/lib/lifecycle/index.js.map +1 -1
  13. package/lib/commonjs/version.js +1 -1
  14. package/lib/module/FormoAnalytics.js +138 -8
  15. package/lib/module/FormoAnalytics.js.map +1 -1
  16. package/lib/module/FormoAnalyticsProvider.js +3 -0
  17. package/lib/module/FormoAnalyticsProvider.js.map +1 -1
  18. package/lib/module/constants/events.js +29 -2
  19. package/lib/module/constants/events.js.map +1 -1
  20. package/lib/module/lib/crash/index.js +117 -0
  21. package/lib/module/lib/crash/index.js.map +1 -0
  22. package/lib/module/lib/event/EventFactory.js +86 -8
  23. package/lib/module/lib/event/EventFactory.js.map +1 -1
  24. package/lib/module/lib/lifecycle/index.js +29 -6
  25. package/lib/module/lib/lifecycle/index.js.map +1 -1
  26. package/lib/module/version.js +1 -1
  27. package/lib/typescript/commonjs/FormoAnalytics.d.ts +52 -1
  28. package/lib/typescript/commonjs/FormoAnalytics.d.ts.map +1 -1
  29. package/lib/typescript/commonjs/FormoAnalyticsProvider.d.ts.map +1 -1
  30. package/lib/typescript/commonjs/constants/events.d.ts +23 -0
  31. package/lib/typescript/commonjs/constants/events.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/lib/crash/index.d.ts +41 -0
  33. package/lib/typescript/commonjs/lib/crash/index.d.ts.map +1 -0
  34. package/lib/typescript/commonjs/lib/event/EventFactory.d.ts +26 -7
  35. package/lib/typescript/commonjs/lib/event/EventFactory.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/lib/lifecycle/index.d.ts +10 -0
  37. package/lib/typescript/commonjs/lib/lifecycle/index.d.ts.map +1 -1
  38. package/lib/typescript/commonjs/types/base.d.ts +40 -0
  39. package/lib/typescript/commonjs/types/base.d.ts.map +1 -1
  40. package/lib/typescript/commonjs/version.d.ts +1 -1
  41. package/lib/typescript/module/FormoAnalytics.d.ts +52 -1
  42. package/lib/typescript/module/FormoAnalytics.d.ts.map +1 -1
  43. package/lib/typescript/module/FormoAnalyticsProvider.d.ts.map +1 -1
  44. package/lib/typescript/module/constants/events.d.ts +23 -0
  45. package/lib/typescript/module/constants/events.d.ts.map +1 -1
  46. package/lib/typescript/module/lib/crash/index.d.ts +41 -0
  47. package/lib/typescript/module/lib/crash/index.d.ts.map +1 -0
  48. package/lib/typescript/module/lib/event/EventFactory.d.ts +26 -7
  49. package/lib/typescript/module/lib/event/EventFactory.d.ts.map +1 -1
  50. package/lib/typescript/module/lib/lifecycle/index.d.ts +10 -0
  51. package/lib/typescript/module/lib/lifecycle/index.d.ts.map +1 -1
  52. package/lib/typescript/module/types/base.d.ts +40 -0
  53. package/lib/typescript/module/types/base.d.ts.map +1 -1
  54. package/lib/typescript/module/version.d.ts +1 -1
  55. package/package.json +8 -8
  56. package/src/FormoAnalytics.ts +151 -8
  57. package/src/FormoAnalyticsProvider.tsx +3 -0
  58. package/src/constants/events.ts +32 -2
  59. package/src/lib/crash/index.ts +145 -0
  60. package/src/lib/event/EventFactory.ts +115 -21
  61. package/src/lib/lifecycle/index.ts +35 -6
  62. package/src/types/base.ts +47 -0
  63. package/src/version.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"FormoAnalyticsProvider.d.ts","sourceRoot":"","sources":["../../../src/FormoAnalyticsProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAOZ,EAAE,EACH,MAAM,OAAO,CAAC;AAIf,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAsBvE,eAAO,MAAM,qBAAqB,gCACc,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,sBAAsB,EAAE,EAAE,CAAC,2BAA2B,CAwBlE,CAAC;AAgMF,eAAO,MAAM,QAAQ,QAAO,eAmB3B,CAAC"}
1
+ {"version":3,"file":"FormoAnalyticsProvider.d.ts","sourceRoot":"","sources":["../../../src/FormoAnalyticsProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAOZ,EAAE,EACH,MAAM,OAAO,CAAC;AAIf,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAyBvE,eAAO,MAAM,qBAAqB,gCACc,CAAC;AAEjD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,sBAAsB,EAAE,EAAE,CAAC,2BAA2B,CAwBlE,CAAC;AAgMF,eAAO,MAAM,QAAQ,QAAO,eAmB3B,CAAC"}
@@ -21,4 +21,27 @@ export type TEventChannel = Lowercase<EventChannel>;
21
21
  export declare const CHANNEL: TEventChannel;
22
22
  export declare const VERSION = "0";
23
23
  export declare const SESSION_TIMEOUT_MS: number;
24
+ /**
25
+ * Reserved lifecycle and campaign event names, per the Segment spec that
26
+ * RudderStack, PostHog and Amplitude all adopted verbatim.
27
+ *
28
+ * These are ordinary `track` events on the wire — the names are what make them
29
+ * recognisable to downstream analytics, so they must match the spec exactly,
30
+ * including capitalisation and spacing.
31
+ *
32
+ * @see https://segment.com/docs/connections/spec/mobile/
33
+ */
34
+ export declare const LIFECYCLE_EVENT: {
35
+ readonly APPLICATION_INSTALLED: "Application Installed";
36
+ readonly APPLICATION_UPDATED: "Application Updated";
37
+ readonly APPLICATION_OPENED: "Application Opened";
38
+ readonly APPLICATION_BACKGROUNDED: "Application Backgrounded";
39
+ readonly APPLICATION_FOREGROUNDED: "Application Foregrounded";
40
+ readonly APPLICATION_CRASHED: "Application Crashed";
41
+ readonly DEEP_LINK_OPENED: "Deep Link Opened";
42
+ readonly PUSH_NOTIFICATION_RECEIVED: "Push Notification Received";
43
+ readonly PUSH_NOTIFICATION_TAPPED: "Push Notification Tapped";
44
+ readonly PUSH_NOTIFICATION_BOUNCED: "Push Notification Bounced";
45
+ };
46
+ export type TLifecycleEvent = (typeof LIFECYCLE_EVENT)[keyof typeof LIFECYCLE_EVENT];
24
47
  //# sourceMappingURL=events.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../src/constants/events.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,KAAK,UAAU;IACf,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,KAAK,UAAU;CAChB;AAED,oBAAY,YAAY;IACtB,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;AAC9C,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;AAGpD,eAAO,MAAM,OAAO,EAAE,aAAwB,CAAC;AAC/C,eAAO,MAAM,OAAO,MAAM,CAAC;AAI3B,eAAO,MAAM,kBAAkB,QAAiB,CAAC"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../../src/constants/events.ts"],"names":[],"mappings":"AAAA,oBAAY,SAAS;IACnB,IAAI,SAAS;IACb,MAAM,WAAW;IACjB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,UAAU,eAAe;IACzB,KAAK,UAAU;IACf,SAAS,cAAc;IACvB,WAAW,gBAAgB;IAC3B,KAAK,UAAU;CAChB;AAED,oBAAY,YAAY;IACtB,GAAG,QAAQ;IACX,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;CAClB;AAED,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;AAC9C,MAAM,MAAM,aAAa,GAAG,SAAS,CAAC,YAAY,CAAC,CAAC;AAGpD,eAAO,MAAM,OAAO,EAAE,aAAwB,CAAC;AAC/C,eAAO,MAAM,OAAO,MAAM,CAAC;AAQ3B,eAAO,MAAM,kBAAkB,QAAiB,CAAC;AAEjD;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;CAWlB,CAAC;AAEX,MAAM,MAAM,eAAe,GACzB,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,OAAO,eAAe,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * JavaScript crash reporting.
3
+ *
4
+ * Emits the Segment-spec `Application Crashed` event for unhandled JS errors by
5
+ * wrapping React Native's global error handler.
6
+ *
7
+ * Scope: JavaScript errors only. A native crash (a Swift/Kotlin exception, an
8
+ * OOM kill, a watchdog termination) never reaches the JS runtime, so it cannot
9
+ * be observed from here — that needs a native crash reporter.
10
+ */
11
+ /** Interface for the analytics instance to avoid circular deps */
12
+ interface IAnalyticsInstance {
13
+ track(event: string, properties?: Record<string, unknown>): Promise<void>;
14
+ flush(): Promise<void>;
15
+ }
16
+ export declare class CrashReporter {
17
+ private analytics;
18
+ private previousHandler;
19
+ private installedHandler;
20
+ private started;
21
+ constructor(analytics: IAnalyticsInstance);
22
+ /**
23
+ * Install the global error handler.
24
+ *
25
+ * The previous handler is always called afterwards — React Native's default
26
+ * handler is what shows the redbox in dev and terminates the app on a fatal
27
+ * error in production, and a customer's crash reporter (Sentry, Bugsnag) may
28
+ * also be in the chain. Swallowing it would break both.
29
+ */
30
+ start(): void;
31
+ private report;
32
+ /**
33
+ * Restore the previous handler.
34
+ *
35
+ * Only restores if ours is still the installed handler — if something else
36
+ * wrapped us afterwards, replacing the chain would unhook that too.
37
+ */
38
+ cleanup(): void;
39
+ }
40
+ export {};
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/crash/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAaH,kEAAkE;AAClE,UAAU,kBAAkB;IAC1B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAWD,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,eAAe,CAA2B;IAClD,OAAO,CAAC,gBAAgB,CAA2B;IACnD,OAAO,CAAC,OAAO,CAAS;gBAEZ,SAAS,EAAE,kBAAkB;IAIzC;;;;;;;OAOG;IACH,KAAK,IAAI,IAAI;IA4Cb,OAAO,CAAC,MAAM;IAqBd;;;;;OAKG;IACH,OAAO,IAAI,IAAI;CAkBhB"}
@@ -20,15 +20,20 @@ import { IEventFactory } from "./types";
20
20
  */
21
21
  export declare function getSessionId(): string;
22
22
  /**
23
- * Build a representative User-Agent string from structured device info.
23
+ * Compose a screen view's `page_url` as `app://<bundle id>/<screen>`.
24
24
  *
25
- * The ingestion pipeline classifies device / os / browser purely from the
26
- * user_agent string; a mobile event with an empty UA is bucketed as "unknown".
27
- * Platforms without a native UA (e.g. Expo, where DeviceInfo.getUserAgent() is
28
- * unavailable) would otherwise report device=os=unknown. We synthesize a UA
29
- * containing the tokens the classifier keys off (iphone/ipad/android + version)
30
- * so mobile device and OS resolve correctly. Returns "" for unknown platforms.
25
+ * Well-formed on purpose: the bundle id occupies the authority slot and the
26
+ * screen the path, so a standard URL parser yields both without any
27
+ * mobile-specific handling the same shape as `https://<host>/<path>`.
28
+ *
29
+ * @param bundleId Application bundle id, e.g. "com.acme.wallet". When empty the
30
+ * authority is omitted (`app:///<screen>`), which still parses to a correct
31
+ * path; the pipeline resolves origin from context in that case.
32
+ * @param name Screen name. Leading slashes are stripped so a router-style name
33
+ * ("/tabs/leaderboard") does not produce a doubled separator.
31
34
  */
35
+ export declare function buildScreenUrl(bundleId: string, name: string): string;
36
+ export declare function resolveExpoDeviceType(deviceType: number | null | undefined, tabletEnumValue: number | null | undefined): "tablet" | "mobile";
32
37
  export declare function synthesizeUserAgent(info: {
33
38
  os_name: string;
34
39
  os_version: string;
@@ -41,6 +46,8 @@ export declare function synthesizeUserAgent(info: {
41
46
  */
42
47
  declare class EventFactory implements IEventFactory {
43
48
  private options?;
49
+ /** Memoised device/app identity — see getDeviceInfo(). */
50
+ private deviceInfoPromise?;
44
51
  constructor(options?: Options);
45
52
  /**
46
53
  * Get device timezone
@@ -66,7 +73,19 @@ declare class EventFactory implements IEventFactory {
66
73
  * Get device information
67
74
  * Supports both react-native-device-info (bare RN) and expo-device/expo-application (Expo Go)
68
75
  */
76
+ /**
77
+ * The app bundle id as it will appear in context.
78
+ *
79
+ * Must mirror generateContext's precedence: an explicitly configured
80
+ * `options.app.bundleId` overrides whatever the native modules report. Reading
81
+ * getDeviceInfo() alone would ignore that configuration and silently fall back
82
+ * to the authority-less URL form — and on React Native Web, where neither
83
+ * react-native-device-info nor expo-application resolves a bundle id, that is
84
+ * the ONLY value available.
85
+ */
86
+ private resolveAppBundleId;
69
87
  private getDeviceInfo;
88
+ private resolveDeviceInfo;
70
89
  /**
71
90
  * Generate context with mobile-specific metadata
72
91
  */
@@ -1 +1 @@
1
- {"version":3,"file":"EventFactory.d.ts","sourceRoot":"","sources":["../../../../../src/lib/event/EventFactory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EventFactory.d.ts","sourceRoot":"","sources":["../../../../../src/lib/event/EventFactory.ts"],"names":[],"mappings":"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"}
@@ -6,8 +6,15 @@
6
6
  * - Application Updated (version/build changed)
7
7
  * - Application Opened (every cold start + foreground return)
8
8
  * - Application Backgrounded (app goes to background)
9
+ * - Application Foregrounded (foreground return; opt-in, see AutocaptureOptions)
9
10
  *
10
11
  * Detection is JS-side using AsyncStorage (no native modules required).
12
+ *
13
+ * The remaining spec events live outside this manager because they are not
14
+ * AppState-driven: `Deep Link Opened` is emitted from the Linking hook in
15
+ * FormoAnalytics, `Application Crashed` from lib/crash, and the push
16
+ * notification events from explicit FormoAnalytics methods (the SDK cannot
17
+ * observe push delivery without a native module).
11
18
  */
12
19
  /** Interface for the analytics instance to avoid circular deps */
13
20
  interface IAnalyticsInstance {
@@ -18,6 +25,7 @@ export declare class AppLifecycleManager {
18
25
  private appStateSubscription;
19
26
  private lastAppState;
20
27
  private appVersionInfo;
28
+ private trackForegrounded;
21
29
  constructor(analytics: IAnalyticsInstance);
22
30
  /**
23
31
  * Initialize lifecycle tracking.
@@ -26,6 +34,8 @@ export declare class AppLifecycleManager {
26
34
  start(appOptions?: {
27
35
  version?: string;
28
36
  build?: string;
37
+ }, options?: {
38
+ trackForegrounded?: boolean;
29
39
  }): Promise<void>;
30
40
  /**
31
41
  * Compare stored version/build with current to detect install or update.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/lifecycle/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAWH,kEAAkE;AAClE,UAAU,kBAAkB;IAC1B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAgDD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,oBAAoB,CAAuC;IACnE,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,cAAc,CAA8C;gBAExD,SAAS,EAAE,kBAAkB;IAIzC;;;OAGG;IACG,KAAK,CACT,UAAU,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAChD,OAAO,CAAC,IAAI,CAAC;IAiChB;;;;OAIG;YACW,qBAAqB;IAkDnC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAkC5B;;OAEG;IACH,OAAO,IAAI,IAAI;CAOhB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/lifecycle/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAYH,kEAAkE;AAClE,UAAU,kBAAkB;IAC1B,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAgDD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,oBAAoB,CAAuC;IACnE,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,iBAAiB,CAAS;gBAEtB,SAAS,EAAE,kBAAkB;IAIzC;;;OAGG;IACG,KAAK,CACT,UAAU,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EACjD,OAAO,CAAC,EAAE;QAAE,iBAAiB,CAAC,EAAE,OAAO,CAAA;KAAE,GACxC,OAAO,CAAC,IAAI,CAAC;IAkChB;;;;OAIG;YACW,qBAAqB;IAkDnC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAoD5B;;OAEG;IACH,OAAO,IAAI,IAAI;CAOhB"}
@@ -49,6 +49,9 @@ export interface IFormoAnalytics {
49
49
  rdns?: string;
50
50
  }, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
51
51
  track(event: string, properties?: IFormoEventProperties, context?: IFormoEventContext, callback?: (...args: unknown[]) => void): Promise<void>;
52
+ pushNotificationReceived(properties?: IFormoEventProperties): Promise<void>;
53
+ pushNotificationTapped(properties?: IFormoEventProperties): Promise<void>;
54
+ pushNotificationBounced(properties?: IFormoEventProperties): Promise<void>;
52
55
  flush(): Promise<void>;
53
56
  setTrafficSourceFromUrl(url: string): void;
54
57
  optOutTracking(): void;
@@ -99,6 +102,43 @@ export interface AutocaptureOptions {
99
102
  * @default true
100
103
  */
101
104
  lifecycle?: boolean;
105
+ /**
106
+ * Emit `Application Foregrounded` on every background → active transition,
107
+ * in addition to the `Application Opened` (with `from_background: true`) that
108
+ * already fires there.
109
+ *
110
+ * Off by default because it doubles foreground event volume and adds no
111
+ * information: `Application Opened` with `from_background: true` already
112
+ * marks the same transition. Enable it if you consume the Segment spec's
113
+ * `Application Foregrounded` name directly — e.g. when migrating dashboards
114
+ * or destinations from Segment or RudderStack. Requires `lifecycle`.
115
+ * @default false
116
+ */
117
+ foregrounded?: boolean;
118
+ /**
119
+ * Track `Deep Link Opened` when the app is launched or resumed via a deep
120
+ * link or universal link, with the `url` property.
121
+ *
122
+ * Independent of `attribution.deeplinks`, which controls whether the link's
123
+ * UTM/referral parameters are parsed into event context. This option is only
124
+ * about emitting the event; the SDK still needs `attribution.deeplinks` to
125
+ * observe links at all.
126
+ * @default true
127
+ */
128
+ deepLinks?: boolean;
129
+ /**
130
+ * Track `Application Crashed` on unhandled JavaScript errors, with the error
131
+ * message, stack, and whether React Native considered it fatal.
132
+ *
133
+ * Off by default because enabling it installs a global error handler
134
+ * (`ErrorUtils.setGlobalHandler`). The previous handler is always invoked
135
+ * afterwards, so React Native's redbox and any crash reporter you already use
136
+ * keep working — but installing one implicitly on an SDK upgrade is a
137
+ * surprise, so it is opt-in. Covers JS errors only: native crashes need a
138
+ * native crash reporter.
139
+ * @default false
140
+ */
141
+ crashes?: boolean;
102
142
  }
103
143
  /**
104
144
  * Configuration options for attribution capture.
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/types/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../../src/types/base.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export declare const version = "1.0.0";
1
+ export declare const version = "1.0.2";
2
2
  //# sourceMappingURL=version.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formo/analytics-react-native",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Formo Analytics SDK for React Native - Track wallet events and user analytics in mobile dApps",
5
5
  "packageManager": "pnpm@11.1.1",
6
6
  "repository": {
@@ -99,24 +99,24 @@
99
99
  "ethereum-cryptography": "3.2.0"
100
100
  },
101
101
  "devDependencies": {
102
- "@babel/preset-env": "^7.29.5",
103
- "@babel/preset-react": "^7.28.5",
102
+ "@babel/preset-env": "^8.0.2",
103
+ "@babel/preset-react": "^8.0.1",
104
104
  "@babel/preset-typescript": "^7.28.5",
105
105
  "@react-native-async-storage/async-storage": "^1.21.0",
106
- "@react-native/babel-preset": "^0.85.3",
106
+ "@react-native/babel-preset": "^0.86.0",
107
107
  "@types/jest": "^30.0.0",
108
108
  "@types/react": "^19.2.14",
109
109
  "@typescript-eslint/eslint-plugin": "^8.59.3",
110
110
  "@typescript-eslint/parser": "^8.59.3",
111
111
  "babel-jest": "^30.4.1",
112
112
  "eslint": "^10.3.0",
113
- "expo-application": "^55.0.15",
114
- "expo-device": "^55.0.17",
113
+ "expo-application": "^57.0.2",
114
+ "expo-device": "^57.0.1",
115
115
  "jest": "^30.4.1",
116
116
  "react": "^19.2.6",
117
- "react-native": "^0.85.3",
117
+ "react-native": "^0.86.0",
118
118
  "react-native-builder-bob": "^0.41.0",
119
- "react-native-device-info": "^14.0.0",
119
+ "react-native-device-info": "^15.0.2",
120
120
  "typescript": "^6.0.3",
121
121
  "typescript-eslint": "^8.59.3"
122
122
  },
@@ -14,6 +14,7 @@ import {
14
14
  CONSENT_OPT_OUT_KEY,
15
15
  TEventType,
16
16
  } from "./constants";
17
+ import { LIFECYCLE_EVENT } from "./constants/events";
17
18
  import { initStorageManager, storage, AsyncStorageInterface } from "./lib/storage";
18
19
  import { EventManager, EventQueue, IEventManager } from "./lib/event";
19
20
  import { logger, Logger } from "./lib/logger";
@@ -25,6 +26,7 @@ import {
25
26
  import { FormoAnalyticsSession } from "./lib/session";
26
27
  import { WagmiEventHandler } from "./lib/wagmi";
27
28
  import { AppLifecycleManager } from "./lib/lifecycle";
29
+ import { CrashReporter } from "./lib/crash";
28
30
  import {
29
31
  Address,
30
32
  ChainID,
@@ -42,12 +44,21 @@ import { parseTrafficSource, updateStoredTrafficSource } from "./utils/trafficSo
42
44
  import { captureInstallReferrer } from "./lib/installReferrer";
43
45
  import { Linking, EmitterSubscription } from "react-native";
44
46
 
47
+ /**
48
+ * Autocapture behaviors that are OFF unless explicitly enabled, because
49
+ * turning them on by default would change how an existing app behaves after a
50
+ * routine SDK upgrade. See AutocaptureOptions for the reasoning per option.
51
+ */
52
+ const OPT_IN_AUTOCAPTURE = new Set<string>(["foregrounded", "crashes"]);
53
+
45
54
  export class FormoAnalytics implements IFormoAnalytics {
46
55
  private session: FormoAnalyticsSession;
47
56
  private eventManager: IEventManager;
48
57
  private eventQueue: EventQueue;
49
58
  private wagmiHandler?: WagmiEventHandler;
50
59
  private lifecycleManager?: AppLifecycleManager;
60
+ private crashReporter?: CrashReporter;
61
+ private initialDeepLinkUrl?: string;
51
62
  private linkingSubscription?: EmitterSubscription;
52
63
 
53
64
  config: Config;
@@ -142,7 +153,16 @@ export class FormoAnalytics implements IFormoAnalytics {
142
153
  // is a fast native bridge call; the Android Play Install Referrer is a fast
143
154
  // one-shot native call (and no-ops instantly when the native module or the
144
155
  // platform isn't Android), so awaiting it does not meaningfully delay init.
145
- if (analytics.isAttributionEnabled("deeplinks")) {
156
+ // Hook Linking if EITHER consumer needs it. The two flags control different
157
+ // things — attribution.deeplinks parses UTMs into context, autocapture
158
+ // .deepLinks emits Deep Link Opened — but both depend on observing the link
159
+ // in the first place. Gating the hook on attribution alone silently
160
+ // disabled the event for anyone who turned attribution off, with no
161
+ // indication that an unrelated setting was responsible.
162
+ if (
163
+ analytics.isAttributionEnabled("deeplinks") ||
164
+ analytics.isAutocaptureEnabled("deepLinks")
165
+ ) {
146
166
  try {
147
167
  await analytics.startDeepLinkCapture();
148
168
  } catch (error) {
@@ -166,12 +186,32 @@ export class FormoAnalytics implements IFormoAnalytics {
166
186
  if (analytics.isAutocaptureEnabled("lifecycle")) {
167
187
  try {
168
188
  analytics.lifecycleManager = new AppLifecycleManager(analytics);
169
- await analytics.lifecycleManager.start(options?.app);
189
+ await analytics.lifecycleManager.start(options?.app, {
190
+ trackForegrounded: analytics.isAutocaptureEnabled("foregrounded"),
191
+ });
170
192
  } catch (error) {
171
193
  logger.error("FormoAnalytics: Failed to initialize lifecycle tracking", error);
172
194
  }
173
195
  }
174
196
 
197
+ // Emit Deep Link Opened for the launch URL AFTER lifecycle tracking, so it
198
+ // follows Application Opened as the Segment spec orders it.
199
+ try {
200
+ await analytics.trackInitialDeepLink();
201
+ } catch (error) {
202
+ logger.error("FormoAnalytics: Failed to track initial deep link", error);
203
+ }
204
+
205
+ // Opt-in: installs a global JS error handler (chained, never swallowing).
206
+ if (analytics.isAutocaptureEnabled("crashes")) {
207
+ try {
208
+ analytics.crashReporter = new CrashReporter(analytics);
209
+ analytics.crashReporter.start();
210
+ } catch (error) {
211
+ logger.error("FormoAnalytics: Failed to initialize crash tracking", error);
212
+ }
213
+ }
214
+
175
215
  // Call ready callback
176
216
  if (options?.ready) {
177
217
  options.ready(analytics);
@@ -188,17 +228,102 @@ export class FormoAnalytics implements IFormoAnalytics {
188
228
  private async startDeepLinkCapture(): Promise<void> {
189
229
  try {
190
230
  const url = await Linking.getInitialURL();
191
- if (url) this.setTrafficSourceFromUrl(url);
231
+ if (url) {
232
+ if (this.isAttributionEnabled("deeplinks")) {
233
+ this.setTrafficSourceFromUrl(url);
234
+ }
235
+ // Held, not emitted: this runs before lifecycle tracking starts, and
236
+ // the Segment spec orders `Deep Link Opened` after `Application
237
+ // Opened`. Emitted by trackInitialDeepLink() once lifecycle has fired.
238
+ this.initialDeepLinkUrl = url;
239
+ }
192
240
  } catch (error) {
193
241
  logger.debug("FormoAnalytics: Linking.getInitialURL failed", error);
194
242
  }
195
243
 
196
244
  // Runtime deep links (foreground opens, universal links).
197
245
  this.linkingSubscription = Linking.addEventListener("url", (event) => {
198
- if (event?.url) this.setTrafficSourceFromUrl(event.url);
246
+ if (!event?.url) return;
247
+ // Each behaviour checks its own flag: the hook may exist because only one
248
+ // of them is enabled.
249
+ if (this.isAttributionEnabled("deeplinks")) {
250
+ this.setTrafficSourceFromUrl(event.url);
251
+ }
252
+ void this.trackDeepLinkOpened(event.url);
199
253
  });
200
254
  }
201
255
 
256
+ /**
257
+ * Emit `Deep Link Opened` for the URL the app was launched with, if any.
258
+ * Separate from capture so it can be ordered after `Application Opened`.
259
+ */
260
+ private async trackInitialDeepLink(): Promise<void> {
261
+ const url = this.initialDeepLinkUrl;
262
+ this.initialDeepLinkUrl = undefined;
263
+ if (url) await this.trackDeepLinkOpened(url);
264
+ }
265
+
266
+ /**
267
+ * Emit the Segment-spec `Deep Link Opened` event.
268
+ *
269
+ * `provider` is deliberately omitted: the spec uses it to name the
270
+ * attribution provider that resolved the link (Branch, Adjust, …). The SDK
271
+ * reads the link straight from React Native's Linking API, so there is no
272
+ * provider to name, and emitting a placeholder would misreport the source.
273
+ */
274
+ private async trackDeepLinkOpened(url: string): Promise<void> {
275
+ if (!this.isAutocaptureEnabled("deepLinks")) return;
276
+ try {
277
+ await this.track(LIFECYCLE_EVENT.DEEP_LINK_OPENED, { url });
278
+ } catch (error) {
279
+ logger.error("FormoAnalytics: Error tracking Deep Link Opened", error);
280
+ }
281
+ }
282
+
283
+ /**
284
+ * Track that a push notification was delivered to the device.
285
+ *
286
+ * Push delivery cannot be observed without a native module, so the SDK
287
+ * cannot autocapture these — call this from your push handler
288
+ * (`@react-native-firebase/messaging`, `expo-notifications`, …).
289
+ *
290
+ * @param properties Segment's push spec suggests `campaign_id`, `campaign_name`,
291
+ * `message_id`, `action` and `title`/`body`. Any properties are accepted.
292
+ *
293
+ * @example
294
+ * ```tsx
295
+ * messaging().onMessage(async (message) => {
296
+ * await formo.pushNotificationReceived({ message_id: message.messageId });
297
+ * });
298
+ * ```
299
+ */
300
+ public async pushNotificationReceived(
301
+ properties?: IFormoEventProperties
302
+ ): Promise<void> {
303
+ await this.track(LIFECYCLE_EVENT.PUSH_NOTIFICATION_RECEIVED, properties);
304
+ }
305
+
306
+ /**
307
+ * Track that the user opened the app by tapping a push notification.
308
+ * See {@link pushNotificationReceived} for why this is not autocaptured.
309
+ */
310
+ public async pushNotificationTapped(
311
+ properties?: IFormoEventProperties
312
+ ): Promise<void> {
313
+ await this.track(LIFECYCLE_EVENT.PUSH_NOTIFICATION_TAPPED, properties);
314
+ }
315
+
316
+ /**
317
+ * Track that a push notification was not delivered — e.g. the OS suppressed
318
+ * it, or the device token was rejected.
319
+ * See {@link pushNotificationReceived} for why this is not autocaptured.
320
+ */
321
+ public async pushNotificationBounced(
322
+ properties?: IFormoEventProperties
323
+ ): Promise<void> {
324
+ await this.track(LIFECYCLE_EVENT.PUSH_NOTIFICATION_BOUNCED, properties);
325
+ }
326
+
202
327
  /**
203
328
  * Track a screen view (mobile equivalent of page view)
204
329
  */
@@ -272,6 +397,11 @@ export class FormoAnalytics implements IFormoAnalytics {
272
397
  public async cleanup(): Promise<void> {
273
398
  logger.info("FormoAnalytics: Cleaning up resources");
274
399
 
400
+ if (this.crashReporter) {
401
+ this.crashReporter.cleanup();
402
+ this.crashReporter = undefined;
403
+ }
404
+
275
405
  if (this.lifecycleManager) {
276
406
  this.lifecycleManager.cleanup();
277
407
  this.lifecycleManager = undefined;
@@ -631,6 +761,12 @@ export class FormoAnalytics implements IFormoAnalytics {
631
761
  * Applies only to event-generating behaviors (wallet events, lifecycle
632
762
  * events). Attribution is controlled separately via `options.attribution`
633
763
  * because it enriches events rather than generating them.
764
+ *
765
+ * Most behaviors are on unless explicitly disabled. The two in
766
+ * {@link OPT_IN_AUTOCAPTURE} invert that and require an explicit `true`,
767
+ * because switching them on by default would change existing apps on a
768
+ * version bump: `foregrounded` doubles foreground event volume, and
769
+ * `crashes` installs a global error handler.
634
770
  */
635
771
  public isAutocaptureEnabled(
636
772
  eventType:
@@ -640,13 +776,20 @@ export class FormoAnalytics implements IFormoAnalytics {
640
776
  | "transaction"
641
777
  | "chain"
642
778
  | "lifecycle"
779
+ | "foregrounded"
780
+ | "deepLinks"
781
+ | "crashes"
643
782
  ): boolean {
783
+ const isOptIn = OPT_IN_AUTOCAPTURE.has(eventType);
784
+
644
785
  if (this.options.autocapture === undefined) {
645
- return true;
786
+ return !isOptIn;
646
787
  }
647
788
 
789
+ // `autocapture: true` means "the usual set", not "everything including the
790
+ // opt-in behaviors" — those still need naming individually.
648
791
  if (typeof this.options.autocapture === "boolean") {
649
- return this.options.autocapture;
792
+ return this.options.autocapture && !isOptIn;
650
793
  }
651
794
 
652
795
  if (
@@ -654,10 +797,10 @@ export class FormoAnalytics implements IFormoAnalytics {
654
797
  typeof this.options.autocapture === "object"
655
798
  ) {
656
799
  const eventConfig = this.options.autocapture[eventType];
657
- return eventConfig !== false;
800
+ return isOptIn ? eventConfig === true : eventConfig !== false;
658
801
  }
659
802
 
660
- return true;
803
+ return !isOptIn;
661
804
  }
662
805
 
663
806
  /**
@@ -25,6 +25,9 @@ const defaultContext: IFormoAnalytics = {
25
25
  transaction: () => Promise.resolve(),
26
26
  identify: () => Promise.resolve(),
27
27
  track: () => Promise.resolve(),
28
+ pushNotificationReceived: () => Promise.resolve(),
29
+ pushNotificationTapped: () => Promise.resolve(),
30
+ pushNotificationBounced: () => Promise.resolve(),
28
31
  flush: () => Promise.resolve(),
29
32
  setTrafficSourceFromUrl: () => {},
30
33
  optOutTracking: () => {},
@@ -25,6 +25,36 @@ export type TEventChannel = Lowercase<EventChannel>;
25
25
  export const CHANNEL: TEventChannel = "mobile";
26
26
  export const VERSION = "0";
27
27
 
28
- // Session inactivity timeout (30 min), matching the GA4/Segment default. A new
29
- // session_id is minted once the gap since the last tracked event exceeds this.
28
+ // Session inactivity timeout (30 min), matching the GA4 default and Formo's own
29
+ // web SDK. A new session_id is minted once the gap since the last tracked event
30
+ // exceeds this. Note that mobile-first vendors run tighter: RudderStack and
31
+ // Amplitude both default to 5 min on mobile (vs 30 on web) and rotate on
32
+ // foreground rather than on inactivity. We keep 30 min so a user's mobile and
33
+ // web sessions are directly comparable.
30
34
  export const SESSION_TIMEOUT_MS = 30 * 60 * 1000;
35
+
36
+ /**
37
+ * Reserved lifecycle and campaign event names, per the Segment spec that
38
+ * RudderStack, PostHog and Amplitude all adopted verbatim.
39
+ *
40
+ * These are ordinary `track` events on the wire — the names are what make them
41
+ * recognisable to downstream analytics, so they must match the spec exactly,
42
+ * including capitalisation and spacing.
43
+ *
44
+ * @see https://segment.com/docs/connections/spec/mobile/
45
+ */
46
+ export const LIFECYCLE_EVENT = {
47
+ APPLICATION_INSTALLED: "Application Installed",
48
+ APPLICATION_UPDATED: "Application Updated",
49
+ APPLICATION_OPENED: "Application Opened",
50
+ APPLICATION_BACKGROUNDED: "Application Backgrounded",
51
+ APPLICATION_FOREGROUNDED: "Application Foregrounded",
52
+ APPLICATION_CRASHED: "Application Crashed",
53
+ DEEP_LINK_OPENED: "Deep Link Opened",
54
+ PUSH_NOTIFICATION_RECEIVED: "Push Notification Received",
55
+ PUSH_NOTIFICATION_TAPPED: "Push Notification Tapped",
56
+ PUSH_NOTIFICATION_BOUNCED: "Push Notification Bounced",
57
+ } as const;
58
+
59
+ export type TLifecycleEvent =
60
+ (typeof LIFECYCLE_EVENT)[keyof typeof LIFECYCLE_EVENT];