@molecule/app-analytics 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +111 -24
- package/README.md +158 -80
- package/dist/auto-tracking.d.ts +110 -14
- package/dist/auto-tracking.d.ts.map +1 -1
- package/dist/auto-tracking.js +55 -62
- package/dist/auto-tracking.js.map +1 -1
- package/package.json +4 -4
package/LICENSE
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
Apache License
|
|
2
3
|
Version 2.0, January 2004
|
|
3
4
|
http://www.apache.org/licenses/
|
|
@@ -34,21 +35,33 @@
|
|
|
34
35
|
|
|
35
36
|
"Work" shall mean the work of authorship, whether in Source or
|
|
36
37
|
Object form, made available under the License, as indicated by a
|
|
37
|
-
copyright notice that is included in or attached to the work
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
38
40
|
|
|
39
41
|
"Derivative Works" shall mean any work, whether in Source or Object
|
|
40
42
|
form, that is based on (or derived from) the Work and for which the
|
|
41
43
|
editorial revisions, annotations, elaborations, or other modifications
|
|
42
|
-
represent, as a whole, an original work of authorship.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
49
62
|
|
|
50
63
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
51
|
-
on behalf of whom a Contribution has been received by
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
52
65
|
subsequently incorporated within the Work.
|
|
53
66
|
|
|
54
67
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
@@ -61,8 +74,18 @@
|
|
|
61
74
|
3. Grant of Patent License. Subject to the terms and conditions of
|
|
62
75
|
this License, each Contributor hereby grants to You a perpetual,
|
|
63
76
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
64
|
-
|
|
65
|
-
and otherwise transfer the Work
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
66
89
|
|
|
67
90
|
4. Redistribution. You may reproduce and distribute copies of the
|
|
68
91
|
Work or Derivative Works thereof in any medium, with or without
|
|
@@ -84,23 +107,87 @@
|
|
|
84
107
|
(d) If the Work includes a "NOTICE" text file as part of its
|
|
85
108
|
distribution, then any Derivative Works that You distribute must
|
|
86
109
|
include a readable copy of the attribution notices contained
|
|
87
|
-
within such NOTICE file
|
|
88
|
-
|
|
89
|
-
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
90
138
|
|
|
91
139
|
6. Trademarks. This License does not grant permission to use the trade
|
|
92
|
-
names, trademarks, service marks, or product names of the Licensor
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
93
143
|
|
|
94
144
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
95
|
-
agreed to in writing, Licensor provides the Work
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
104
191
|
|
|
105
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
106
193
|
you may not use this file except in compliance with the License.
|
package/README.md
CHANGED
|
@@ -3,20 +3,20 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
|
3
3
|
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
4
|
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
5
|
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
-
Generated: 2026-
|
|
6
|
+
Generated: 2026-10-24T04:18:36.696Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/app-analytics
|
|
10
10
|
|
|
11
|
-
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
-
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
-
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
-
|
|
15
11
|
Frontend analytics interface for molecule.dev.
|
|
16
12
|
|
|
17
13
|
Provides a unified analytics API that can be backed by different
|
|
18
14
|
implementations (PostHog, Mixpanel, etc.).
|
|
19
15
|
|
|
16
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
17
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
18
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
19
|
+
|
|
20
20
|
## Quick Start
|
|
21
21
|
|
|
22
22
|
```typescript
|
|
@@ -47,6 +47,88 @@ npm install @molecule/app-analytics @molecule/app-bond
|
|
|
47
47
|
|
|
48
48
|
### Interfaces
|
|
49
49
|
|
|
50
|
+
#### `AnalyticsAuthUser`
|
|
51
|
+
|
|
52
|
+
The default auth profile: an immutable `id` plus the traits analytics records.
|
|
53
|
+
|
|
54
|
+
An app whose auth client carries its OWN profile (no `id`) still auto-tracks
|
|
55
|
+
auth events — it passes `identifyUser` to say which field identifies the user
|
|
56
|
+
(see {@link AutoTrackingOptions}).
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
interface AnalyticsAuthUser {
|
|
60
|
+
/** Unique user identifier. */
|
|
61
|
+
id: string
|
|
62
|
+
/** User email address. */
|
|
63
|
+
email?: string
|
|
64
|
+
/** User display name. */
|
|
65
|
+
name?: string
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### `AutoTrackingOptions`
|
|
70
|
+
|
|
71
|
+
Auto-tracking sources and the identity adapter. Pass any combination of
|
|
72
|
+
sources — only provided sources are tracked. Works for both web and mobile
|
|
73
|
+
apps.
|
|
74
|
+
|
|
75
|
+
`TUser` is the profile the auth client hands to its listeners. The default,
|
|
76
|
+
{@link AnalyticsAuthUser}, has an `id`, and it is identified by that field
|
|
77
|
+
with no extra wiring. An app whose profile has no `id` (e.g.
|
|
78
|
+
`{ username, email, bio }`) passes an `identifyUser` extractor; it is
|
|
79
|
+
REQUIRED for such a profile, so a client cannot be wired into tracking with
|
|
80
|
+
no identity at all and `userId: undefined` never reaches a provider. That
|
|
81
|
+
requirement is applied by {@link setupAutoTracking}'s parameter (see
|
|
82
|
+
{@link IdentityRequirement}), not by this interface, so the options bag stays
|
|
83
|
+
declaration-mergeable:
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
declare module '@molecule/app-analytics' {
|
|
87
|
+
interface AutoTrackingOptions {
|
|
88
|
+
label?: string
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
interface AutoTrackingOptions<TUser extends object = AnalyticsAuthUser> {
|
|
95
|
+
/** Auth client for login/logout/register/error events. */
|
|
96
|
+
authClient?: AuthClientLike<TUser>
|
|
97
|
+
/**
|
|
98
|
+
* Which field of the profile identifies the user in analytics — required when
|
|
99
|
+
* the profile has no `id: string`. The default reads `id`, `email` and `name`.
|
|
100
|
+
* Return `null` when the session has no stable identity: the sign-in is still
|
|
101
|
+
* tracked, without an `identify` call or a `userId`.
|
|
102
|
+
*/
|
|
103
|
+
identifyUser?: IdentifyUser<TUser>
|
|
104
|
+
/** Router for page view tracking. */
|
|
105
|
+
router?: RouterLike
|
|
106
|
+
/** HTTP client for error tracking. */
|
|
107
|
+
httpClient?: HttpClientLike
|
|
108
|
+
/** Lifecycle client for app foreground/background and deep link tracking. */
|
|
109
|
+
lifecycleClient?: LifecycleClientLike
|
|
110
|
+
/** Push client for notification received/tapped tracking. */
|
|
111
|
+
pushClient?: PushClientLike
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
#### `AnalyticsUserProps`
|
|
116
|
+
|
|
117
|
+
User properties for analytics identification.
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
interface AnalyticsUserProps {
|
|
121
|
+
/** Unique user identifier. */
|
|
122
|
+
userId: string
|
|
123
|
+
/** User email address. */
|
|
124
|
+
email?: string
|
|
125
|
+
/** User display name. */
|
|
126
|
+
name?: string
|
|
127
|
+
/** Arbitrary key-value traits to associate with the user. */
|
|
128
|
+
traits?: Record<string, unknown>
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
50
132
|
#### `AnalyticsEvent`
|
|
51
133
|
|
|
52
134
|
Event properties for analytics tracking.
|
|
@@ -148,78 +230,81 @@ interface AnalyticsProvider {
|
|
|
148
230
|
}
|
|
149
231
|
```
|
|
150
232
|
|
|
151
|
-
|
|
233
|
+
### Types
|
|
152
234
|
|
|
153
|
-
|
|
235
|
+
#### `IdentifyUser`
|
|
236
|
+
|
|
237
|
+
Maps a signed-in profile to the identity analytics records for it.
|
|
238
|
+
|
|
239
|
+
Return `null` when this session has no stable identity to record (an
|
|
240
|
+
anonymous or throwaway session): the sign-in is then tracked without an
|
|
241
|
+
`identify` call instead of sending an undefined `userId`.
|
|
154
242
|
|
|
155
243
|
```typescript
|
|
156
|
-
|
|
157
|
-
/** Unique user identifier. */
|
|
158
|
-
userId: string
|
|
159
|
-
/** User email address. */
|
|
160
|
-
email?: string
|
|
161
|
-
/** User display name. */
|
|
162
|
-
name?: string
|
|
163
|
-
/** Arbitrary key-value traits to associate with the user. */
|
|
164
|
-
traits?: Record<string, unknown>
|
|
165
|
-
}
|
|
244
|
+
type IdentifyUser<TUser> = (user: TUser) => AnalyticsUserProps | null
|
|
166
245
|
```
|
|
167
246
|
|
|
168
|
-
#### `
|
|
247
|
+
#### `IdentityRequirement`
|
|
169
248
|
|
|
170
|
-
|
|
171
|
-
|
|
249
|
+
The identity rule for one profile: a profile with `id: string` may omit
|
|
250
|
+
`identifyUser`, a profile without one must pass it. Applied to
|
|
251
|
+
{@link setupAutoTracking}'s parameter so {@link AutoTrackingOptions} stays an
|
|
252
|
+
interface that apps can augment.
|
|
172
253
|
|
|
173
254
|
```typescript
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
/** Router for page view tracking. */
|
|
178
|
-
router?: RouterLike
|
|
179
|
-
/** HTTP client for error tracking. */
|
|
180
|
-
httpClient?: HttpClientLike
|
|
181
|
-
/** Lifecycle client for app foreground/background and deep link tracking. */
|
|
182
|
-
lifecycleClient?: LifecycleClientLike
|
|
183
|
-
/** Push client for notification received/tapped tracking. */
|
|
184
|
-
pushClient?: PushClientLike
|
|
185
|
-
}
|
|
255
|
+
type IdentityRequirement<TUser extends object> = [TUser] extends [{ id: string }]
|
|
256
|
+
? { identifyUser?: IdentifyUser<TUser> }
|
|
257
|
+
: { identifyUser: IdentifyUser<TUser> }
|
|
186
258
|
```
|
|
187
259
|
|
|
188
260
|
### Functions
|
|
189
261
|
|
|
190
|
-
#### `
|
|
262
|
+
#### `setupAutoTracking(options)`
|
|
191
263
|
|
|
192
|
-
|
|
264
|
+
Sets up automatic analytics tracking for auth events, route changes,
|
|
265
|
+
HTTP errors, app lifecycle transitions, push notifications, and deep links.
|
|
266
|
+
Returns a cleanup function that removes all subscriptions.
|
|
267
|
+
|
|
268
|
+
Pass any combination of sources — only provided sources are tracked.
|
|
269
|
+
|
|
270
|
+
The analytics provider is resolved at EVENT time, not at setup time — so
|
|
271
|
+
`setupAutoTracking()` may safely run before the analytics bond is set
|
|
272
|
+
(events fired before bonding no-op; events fired after are tracked).
|
|
273
|
+
|
|
274
|
+
The default-profile call takes an inline `getClient()`: it is typed as the
|
|
275
|
+
default {@link AnalyticsAuthUser}, so `identifyUser` stays optional exactly
|
|
276
|
+
as before. An app whose client carries its own profile names that profile —
|
|
277
|
+
either on the auth client and an `identifyUser` extractor, or as the setup's
|
|
278
|
+
type argument — and a profile with no `id: string` must pass `identifyUser`.
|
|
193
279
|
|
|
194
280
|
```typescript
|
|
195
|
-
function
|
|
281
|
+
function setupAutoTracking(options: AutoTrackingOptions<AnalyticsAuthUser>): () => void
|
|
196
282
|
```
|
|
197
283
|
|
|
198
|
-
|
|
284
|
+
- `options` — Sources to auto-track.
|
|
199
285
|
|
|
200
|
-
|
|
286
|
+
**Returns:** A cleanup function that removes all event subscriptions.
|
|
201
287
|
|
|
202
|
-
|
|
203
|
-
|
|
288
|
+
#### `setProvider(provider)`
|
|
289
|
+
|
|
290
|
+
Registers an analytics provider as the active singleton.
|
|
204
291
|
|
|
205
292
|
```typescript
|
|
206
|
-
function
|
|
293
|
+
function setProvider(provider: AnalyticsProvider): void
|
|
207
294
|
```
|
|
208
295
|
|
|
209
|
-
|
|
296
|
+
- `provider` — The analytics provider implementation to bond.
|
|
210
297
|
|
|
211
|
-
#### `
|
|
298
|
+
#### `getProvider()`
|
|
212
299
|
|
|
213
|
-
|
|
300
|
+
Retrieves the bonded analytics provider. Returns a no-op provider if
|
|
301
|
+
none is bonded, so analytics calls never throw.
|
|
214
302
|
|
|
215
303
|
```typescript
|
|
216
|
-
function
|
|
304
|
+
function getProvider(): AnalyticsProvider
|
|
217
305
|
```
|
|
218
306
|
|
|
219
|
-
|
|
220
|
-
- `traits` — Optional traits describing the group.
|
|
221
|
-
|
|
222
|
-
**Returns:** A promise that resolves when group association completes or fails silently.
|
|
307
|
+
**Returns:** The bonded analytics provider, or a silent no-op fallback.
|
|
223
308
|
|
|
224
309
|
#### `hasProvider()`
|
|
225
310
|
|
|
@@ -243,69 +328,62 @@ function identify(user: AnalyticsUserProps): Promise<void>
|
|
|
243
328
|
|
|
244
329
|
**Returns:** A promise that resolves when identification completes or fails silently.
|
|
245
330
|
|
|
246
|
-
#### `
|
|
331
|
+
#### `track(event)`
|
|
247
332
|
|
|
248
|
-
Tracks a
|
|
333
|
+
Tracks a named event with optional properties. Errors are silently ignored.
|
|
249
334
|
|
|
250
335
|
```typescript
|
|
251
|
-
function
|
|
336
|
+
function track(event: AnalyticsEvent): Promise<void>
|
|
252
337
|
```
|
|
253
338
|
|
|
254
|
-
- `
|
|
339
|
+
- `event` — The event to track (name and optional properties).
|
|
255
340
|
|
|
256
|
-
**Returns:** A promise that resolves when
|
|
341
|
+
**Returns:** A promise that resolves when tracking completes or fails silently.
|
|
257
342
|
|
|
258
|
-
#### `
|
|
343
|
+
#### `page(pageView)`
|
|
259
344
|
|
|
260
|
-
|
|
345
|
+
Tracks a page view event. Errors are silently ignored.
|
|
261
346
|
|
|
262
347
|
```typescript
|
|
263
|
-
function
|
|
348
|
+
function page(pageView: AnalyticsPageView): Promise<void>
|
|
264
349
|
```
|
|
265
350
|
|
|
266
|
-
|
|
351
|
+
- `pageView` — The page view data (name, path, referrer, etc.).
|
|
267
352
|
|
|
268
|
-
|
|
353
|
+
**Returns:** A promise that resolves when page tracking completes or fails silently.
|
|
269
354
|
|
|
270
|
-
|
|
355
|
+
#### `group(groupId, traits)`
|
|
356
|
+
|
|
357
|
+
Associates the current user with a group/organization. Errors are silently ignored.
|
|
271
358
|
|
|
272
359
|
```typescript
|
|
273
|
-
function
|
|
360
|
+
function group(groupId: string, traits?: Record<string, unknown>): Promise<void>
|
|
274
361
|
```
|
|
275
362
|
|
|
276
|
-
- `
|
|
277
|
-
|
|
278
|
-
#### `setupAutoTracking(options)`
|
|
363
|
+
- `groupId` — The group identifier.
|
|
364
|
+
- `traits` — Optional traits describing the group.
|
|
279
365
|
|
|
280
|
-
|
|
281
|
-
HTTP errors, app lifecycle transitions, push notifications, and deep links.
|
|
282
|
-
Returns a cleanup function that removes all subscriptions.
|
|
366
|
+
**Returns:** A promise that resolves when group association completes or fails silently.
|
|
283
367
|
|
|
284
|
-
|
|
368
|
+
#### `reset()`
|
|
285
369
|
|
|
286
|
-
|
|
287
|
-
`setupAutoTracking()` may safely run before the analytics bond is set
|
|
288
|
-
(events fired before bonding no-op; events fired after are tracked).
|
|
370
|
+
Resets the analytics state (e.g. on logout). Errors are silently ignored.
|
|
289
371
|
|
|
290
372
|
```typescript
|
|
291
|
-
function
|
|
373
|
+
function reset(): Promise<void>
|
|
292
374
|
```
|
|
293
375
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
**Returns:** A cleanup function that removes all event subscriptions.
|
|
376
|
+
**Returns:** A promise that resolves when reset completes or fails silently.
|
|
297
377
|
|
|
298
|
-
#### `
|
|
378
|
+
#### `flush()`
|
|
299
379
|
|
|
300
|
-
|
|
380
|
+
Flushes any queued analytics events to the backend. Errors are silently ignored.
|
|
301
381
|
|
|
302
382
|
```typescript
|
|
303
|
-
function
|
|
383
|
+
function flush(): Promise<void>
|
|
304
384
|
```
|
|
305
385
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
**Returns:** A promise that resolves when tracking completes or fails silently.
|
|
386
|
+
**Returns:** A promise that resolves when flush completes or fails silently.
|
|
309
387
|
|
|
310
388
|
## Available Providers
|
|
311
389
|
|
package/dist/auto-tracking.d.ts
CHANGED
|
@@ -7,23 +7,46 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
|
+
import type { AnalyticsUserProps } from './types.js';
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
+
* The default auth profile: an immutable `id` plus the traits analytics records.
|
|
13
|
+
*
|
|
14
|
+
* An app whose auth client carries its OWN profile (no `id`) still auto-tracks
|
|
15
|
+
* auth events — it passes `identifyUser` to say which field identifies the user
|
|
16
|
+
* (see {@link AutoTrackingOptions}).
|
|
17
|
+
*/
|
|
18
|
+
export interface AnalyticsAuthUser {
|
|
19
|
+
/** Unique user identifier. */
|
|
20
|
+
id: string;
|
|
21
|
+
/** User email address. */
|
|
22
|
+
email?: string;
|
|
23
|
+
/** User display name. */
|
|
24
|
+
name?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Maps a signed-in profile to the identity analytics records for it.
|
|
28
|
+
*
|
|
29
|
+
* Return `null` when this session has no stable identity to record (an
|
|
30
|
+
* anonymous or throwaway session): the sign-in is then tracked without an
|
|
31
|
+
* `identify` call instead of sending an undefined `userId`.
|
|
32
|
+
*
|
|
33
|
+
* @template TUser - The app's own profile shape.
|
|
34
|
+
*/
|
|
35
|
+
export type IdentifyUser<TUser> = (user: TUser) => AnalyticsUserProps | null;
|
|
36
|
+
/**
|
|
37
|
+
* Minimal auth event shape (mirrors `@molecule/app-auth` AuthEvent), typed by
|
|
38
|
+
* the app's profile.
|
|
12
39
|
*/
|
|
13
|
-
interface
|
|
40
|
+
interface AuthEventLike<TUser> {
|
|
14
41
|
type: 'login' | 'logout' | 'register' | 'refresh' | 'error';
|
|
15
|
-
user?:
|
|
16
|
-
id: string;
|
|
17
|
-
email?: string;
|
|
18
|
-
name?: string;
|
|
19
|
-
};
|
|
42
|
+
user?: TUser;
|
|
20
43
|
error?: string;
|
|
21
44
|
}
|
|
22
45
|
/**
|
|
23
46
|
* Minimal auth client interface for auto-tracking.
|
|
24
47
|
*/
|
|
25
|
-
interface AuthClientLike {
|
|
26
|
-
addEventListener(listener: (event:
|
|
48
|
+
interface AuthClientLike<TUser> {
|
|
49
|
+
addEventListener(listener: (event: AuthEventLike<TUser>) => void): () => void;
|
|
27
50
|
}
|
|
28
51
|
/**
|
|
29
52
|
* Minimal route location shape (mirrors `@molecule/app-routing` RouteLocation).
|
|
@@ -100,12 +123,40 @@ interface PushClientLike {
|
|
|
100
123
|
onNotificationAction(listener: (event: NotificationActionEventLike) => void): () => void;
|
|
101
124
|
}
|
|
102
125
|
/**
|
|
103
|
-
* Auto-tracking
|
|
104
|
-
* sources are tracked. Works for both web and mobile
|
|
126
|
+
* Auto-tracking sources and the identity adapter. Pass any combination of
|
|
127
|
+
* sources — only provided sources are tracked. Works for both web and mobile
|
|
128
|
+
* apps.
|
|
129
|
+
*
|
|
130
|
+
* `TUser` is the profile the auth client hands to its listeners. The default,
|
|
131
|
+
* {@link AnalyticsAuthUser}, has an `id`, and it is identified by that field
|
|
132
|
+
* with no extra wiring. An app whose profile has no `id` (e.g.
|
|
133
|
+
* `{ username, email, bio }`) passes an `identifyUser` extractor; it is
|
|
134
|
+
* REQUIRED for such a profile, so a client cannot be wired into tracking with
|
|
135
|
+
* no identity at all and `userId: undefined` never reaches a provider. That
|
|
136
|
+
* requirement is applied by {@link setupAutoTracking}'s parameter (see
|
|
137
|
+
* {@link IdentityRequirement}), not by this interface, so the options bag stays
|
|
138
|
+
* declaration-mergeable:
|
|
139
|
+
*
|
|
140
|
+
* ```typescript
|
|
141
|
+
* declare module '@molecule/app-analytics' {
|
|
142
|
+
* interface AutoTrackingOptions {
|
|
143
|
+
* label?: string
|
|
144
|
+
* }
|
|
145
|
+
* }
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @template TUser - The auth client's profile shape.
|
|
105
149
|
*/
|
|
106
|
-
export interface AutoTrackingOptions {
|
|
150
|
+
export interface AutoTrackingOptions<TUser extends object = AnalyticsAuthUser> {
|
|
107
151
|
/** Auth client for login/logout/register/error events. */
|
|
108
|
-
authClient?: AuthClientLike
|
|
152
|
+
authClient?: AuthClientLike<TUser>;
|
|
153
|
+
/**
|
|
154
|
+
* Which field of the profile identifies the user in analytics — required when
|
|
155
|
+
* the profile has no `id: string`. The default reads `id`, `email` and `name`.
|
|
156
|
+
* Return `null` when the session has no stable identity: the sign-in is still
|
|
157
|
+
* tracked, without an `identify` call or a `userId`.
|
|
158
|
+
*/
|
|
159
|
+
identifyUser?: IdentifyUser<TUser>;
|
|
109
160
|
/** Router for page view tracking. */
|
|
110
161
|
router?: RouterLike;
|
|
111
162
|
/** HTTP client for error tracking. */
|
|
@@ -115,6 +166,21 @@ export interface AutoTrackingOptions {
|
|
|
115
166
|
/** Push client for notification received/tapped tracking. */
|
|
116
167
|
pushClient?: PushClientLike;
|
|
117
168
|
}
|
|
169
|
+
/**
|
|
170
|
+
* The identity rule for one profile: a profile with `id: string` may omit
|
|
171
|
+
* `identifyUser`, a profile without one must pass it. Applied to
|
|
172
|
+
* {@link setupAutoTracking}'s parameter so {@link AutoTrackingOptions} stays an
|
|
173
|
+
* interface that apps can augment.
|
|
174
|
+
*
|
|
175
|
+
* @template TUser - The auth client's profile shape.
|
|
176
|
+
*/
|
|
177
|
+
export type IdentityRequirement<TUser extends object> = [TUser] extends [{
|
|
178
|
+
id: string;
|
|
179
|
+
}] ? {
|
|
180
|
+
identifyUser?: IdentifyUser<TUser>;
|
|
181
|
+
} : {
|
|
182
|
+
identifyUser: IdentifyUser<TUser>;
|
|
183
|
+
};
|
|
118
184
|
/**
|
|
119
185
|
* Sets up automatic analytics tracking for auth events, route changes,
|
|
120
186
|
* HTTP errors, app lifecycle transitions, push notifications, and deep links.
|
|
@@ -126,6 +192,12 @@ export interface AutoTrackingOptions {
|
|
|
126
192
|
* `setupAutoTracking()` may safely run before the analytics bond is set
|
|
127
193
|
* (events fired before bonding no-op; events fired after are tracked).
|
|
128
194
|
*
|
|
195
|
+
* The default-profile call takes an inline `getClient()`: it is typed as the
|
|
196
|
+
* default {@link AnalyticsAuthUser}, so `identifyUser` stays optional exactly
|
|
197
|
+
* as before. An app whose client carries its own profile names that profile —
|
|
198
|
+
* either on the auth client and an `identifyUser` extractor, or as the setup's
|
|
199
|
+
* type argument — and a profile with no `id: string` must pass `identifyUser`.
|
|
200
|
+
*
|
|
129
201
|
* @example
|
|
130
202
|
* ```typescript
|
|
131
203
|
* // Web app
|
|
@@ -135,6 +207,12 @@ export interface AutoTrackingOptions {
|
|
|
135
207
|
* httpClient: getHttp(),
|
|
136
208
|
* })
|
|
137
209
|
*
|
|
210
|
+
* // An app whose profile has no `id` says which field identifies the user:
|
|
211
|
+
* const cleanup = setupAutoTracking({
|
|
212
|
+
* authClient: authClient, // createJWTAuthClient<SessionUser>(…)
|
|
213
|
+
* identifyUser: (user) => ({ userId: user.username, email: user.email }),
|
|
214
|
+
* })
|
|
215
|
+
*
|
|
138
216
|
* // Mobile app (React Native) — add lifecycle and push
|
|
139
217
|
* const cleanup = setupAutoTracking({
|
|
140
218
|
* authClient: getClient(),
|
|
@@ -151,6 +229,24 @@ export interface AutoTrackingOptions {
|
|
|
151
229
|
* @param options - Sources to auto-track.
|
|
152
230
|
* @returns A cleanup function that removes all event subscriptions.
|
|
153
231
|
*/
|
|
154
|
-
export declare
|
|
232
|
+
export declare function setupAutoTracking(options: AutoTrackingOptions<AnalyticsAuthUser>): () => void;
|
|
233
|
+
/**
|
|
234
|
+
* Sets up automatic analytics tracking for an app whose auth client carries its
|
|
235
|
+
* own profile. `identifyUser` is required when that profile has no `id: string`.
|
|
236
|
+
*
|
|
237
|
+
* @template TUser - The auth client's profile shape.
|
|
238
|
+
* @param options - Sources to auto-track.
|
|
239
|
+
* @returns A cleanup function that removes all event subscriptions.
|
|
240
|
+
*/
|
|
241
|
+
export declare function setupAutoTracking<TUser extends object>(options: AutoTrackingOptions<TUser> & IdentityRequirement<TUser>): () => void;
|
|
242
|
+
/**
|
|
243
|
+
* Keeps derived options (`Parameters<typeof setupAutoTracking>[0]`) on the default profile.
|
|
244
|
+
* The first default overload also supplies contextual typing for nested untyped client calls;
|
|
245
|
+
* the custom-profile overload between them requires an identity extractor where needed.
|
|
246
|
+
*
|
|
247
|
+
* @param options - Sources to auto-track with the default profile.
|
|
248
|
+
* @returns A cleanup function that removes all event subscriptions.
|
|
249
|
+
*/
|
|
250
|
+
export declare function setupAutoTracking(options: AutoTrackingOptions<AnalyticsAuthUser>): () => void;
|
|
155
251
|
export {};
|
|
156
252
|
//# sourceMappingURL=auto-tracking.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-tracking.d.ts","sourceRoot":"","sources":["../src/auto-tracking.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"auto-tracking.d.ts","sourceRoot":"","sources":["../src/auto-tracking.ts"],"names":[],"mappings":"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"}
|
package/dist/auto-tracking.js
CHANGED
|
@@ -8,79 +8,72 @@
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
import { getProvider } from './provider.js';
|
|
11
|
-
|
|
12
|
-
* Sets up automatic analytics tracking for auth events, route changes,
|
|
13
|
-
* HTTP errors, app lifecycle transitions, push notifications, and deep links.
|
|
14
|
-
* Returns a cleanup function that removes all subscriptions.
|
|
15
|
-
*
|
|
16
|
-
* Pass any combination of sources — only provided sources are tracked.
|
|
17
|
-
*
|
|
18
|
-
* The analytics provider is resolved at EVENT time, not at setup time — so
|
|
19
|
-
* `setupAutoTracking()` may safely run before the analytics bond is set
|
|
20
|
-
* (events fired before bonding no-op; events fired after are tracked).
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```typescript
|
|
24
|
-
* // Web app
|
|
25
|
-
* const cleanup = setupAutoTracking({
|
|
26
|
-
* authClient: getClient(),
|
|
27
|
-
* router: getRouter(),
|
|
28
|
-
* httpClient: getHttp(),
|
|
29
|
-
* })
|
|
30
|
-
*
|
|
31
|
-
* // Mobile app (React Native) — add lifecycle and push
|
|
32
|
-
* const cleanup = setupAutoTracking({
|
|
33
|
-
* authClient: getClient(),
|
|
34
|
-
* router: getRouter(),
|
|
35
|
-
* httpClient: getHttp(),
|
|
36
|
-
* lifecycleClient: getLifecycleProvider(),
|
|
37
|
-
* pushClient: getPushProvider(),
|
|
38
|
-
* })
|
|
39
|
-
*
|
|
40
|
-
* // Later, to remove all listeners:
|
|
41
|
-
* cleanup()
|
|
42
|
-
* ```
|
|
43
|
-
*
|
|
44
|
-
* @param options - Sources to auto-track.
|
|
45
|
-
* @returns A cleanup function that removes all event subscriptions.
|
|
46
|
-
*/
|
|
47
|
-
export const setupAutoTracking = (options) => {
|
|
11
|
+
export function setupAutoTracking(options) {
|
|
48
12
|
const cleanups = [];
|
|
49
13
|
// Resolve the provider per event — capturing getProvider() once at setup
|
|
50
14
|
// permanently baked in the no-op provider whenever setupAutoTracking() ran
|
|
51
15
|
// before the analytics bond was set, silently dropping every event forever.
|
|
52
16
|
const analytics = () => getProvider();
|
|
17
|
+
/**
|
|
18
|
+
* The identity to record for a profile: the app's own extractor when given,
|
|
19
|
+
* otherwise the default `id`/`email`/`name` fields. `null` means this session
|
|
20
|
+
* has no identity to record — no `identify`, and no `userId` on the event.
|
|
21
|
+
*
|
|
22
|
+
* @param user - The profile a sign-in event carried.
|
|
23
|
+
* @returns The identity, or `null` when none can be read.
|
|
24
|
+
*/
|
|
25
|
+
const identityOf = (user) => {
|
|
26
|
+
if (options.identifyUser)
|
|
27
|
+
return options.identifyUser(user);
|
|
28
|
+
if (!('id' in user) || typeof user.id !== 'string' || user.id === '')
|
|
29
|
+
return null;
|
|
30
|
+
const identity = { userId: user.id };
|
|
31
|
+
if ('email' in user && typeof user.email === 'string')
|
|
32
|
+
identity.email = user.email;
|
|
33
|
+
if ('name' in user && typeof user.name === 'string')
|
|
34
|
+
identity.name = user.name;
|
|
35
|
+
return identity;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Identifies the signed-in user and tracks the sign-in event.
|
|
39
|
+
*
|
|
40
|
+
* When there is no identity ({@link IdentifyUser} returned `null`, or the
|
|
41
|
+
* profile carries no readable `id`), the `identify` call is skipped and the
|
|
42
|
+
* sign-in is STILL tracked — without a `userId` — so `auth.login` and
|
|
43
|
+
* `auth.register` counts are not silently lost for anonymous sessions.
|
|
44
|
+
*
|
|
45
|
+
* @param name - `auth.login` or `auth.register`.
|
|
46
|
+
* @param user - The profile the event carried.
|
|
47
|
+
*/
|
|
48
|
+
const trackSignIn = (name, user) => {
|
|
49
|
+
if (!user)
|
|
50
|
+
return;
|
|
51
|
+
const identity = identityOf(user);
|
|
52
|
+
if (identity) {
|
|
53
|
+
analytics()
|
|
54
|
+
.identify(identity)
|
|
55
|
+
.catch(() => { });
|
|
56
|
+
analytics()
|
|
57
|
+
.track({ name, properties: { userId: identity.userId } })
|
|
58
|
+
.catch(() => { });
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// No identity means the app said this session has none (or the profile has
|
|
62
|
+
// no id and no extractor reached this client): never send `userId:
|
|
63
|
+
// undefined`, but do not drop the sign-in event either.
|
|
64
|
+
analytics()
|
|
65
|
+
.track({ name })
|
|
66
|
+
.catch(() => { });
|
|
67
|
+
};
|
|
53
68
|
// Auth events
|
|
54
69
|
if (options.authClient) {
|
|
55
70
|
const removeListener = options.authClient.addEventListener((event) => {
|
|
56
71
|
switch (event.type) {
|
|
57
72
|
case 'login':
|
|
58
|
-
|
|
59
|
-
analytics()
|
|
60
|
-
.identify({
|
|
61
|
-
userId: event.user.id,
|
|
62
|
-
email: event.user.email,
|
|
63
|
-
name: event.user.name,
|
|
64
|
-
})
|
|
65
|
-
.catch(() => { });
|
|
66
|
-
analytics()
|
|
67
|
-
.track({ name: 'auth.login', properties: { userId: event.user.id } })
|
|
68
|
-
.catch(() => { });
|
|
69
|
-
}
|
|
73
|
+
trackSignIn('auth.login', event.user);
|
|
70
74
|
break;
|
|
71
75
|
case 'register':
|
|
72
|
-
|
|
73
|
-
analytics()
|
|
74
|
-
.identify({
|
|
75
|
-
userId: event.user.id,
|
|
76
|
-
email: event.user.email,
|
|
77
|
-
name: event.user.name,
|
|
78
|
-
})
|
|
79
|
-
.catch(() => { });
|
|
80
|
-
analytics()
|
|
81
|
-
.track({ name: 'auth.register', properties: { userId: event.user.id } })
|
|
82
|
-
.catch(() => { });
|
|
83
|
-
}
|
|
76
|
+
trackSignIn('auth.register', event.user);
|
|
84
77
|
break;
|
|
85
78
|
case 'logout':
|
|
86
79
|
analytics()
|
|
@@ -192,5 +185,5 @@ export const setupAutoTracking = (options) => {
|
|
|
192
185
|
return () => {
|
|
193
186
|
cleanups.forEach((fn) => fn());
|
|
194
187
|
};
|
|
195
|
-
}
|
|
188
|
+
}
|
|
196
189
|
//# sourceMappingURL=auto-tracking.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-tracking.js","sourceRoot":"","sources":["../src/auto-tracking.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"auto-tracking.js","sourceRoot":"","sources":["../src/auto-tracking.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/app-analytics",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Frontend analytics interface for molecule.dev",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"@molecule/app-bond": "^1.0.1"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@molecule/app-bond": "1.0.
|
|
36
|
-
"@types/node": "26.
|
|
35
|
+
"@molecule/app-bond": "1.0.3",
|
|
36
|
+
"@types/node": "26.6.5",
|
|
37
37
|
"typescript": "6.0.3",
|
|
38
|
-
"vitest": "4.1.
|
|
38
|
+
"vitest": "4.1.12"
|
|
39
39
|
},
|
|
40
40
|
"repository": {
|
|
41
41
|
"type": "git",
|