tangled
alpha
login
or
join now
tijs.org
/
driftline-client
0
fork
atom
Typescript client for Driftline analytics
0
fork
atom
overview
issues
pulls
pipelines
Add comprehensive JSDoc documentation
tijs.org
3 months ago
79f862e7
e150c442
+136
-17
3 changed files
expand all
collapse all
unified
split
CHANGELOG.md
deno.json
mod.ts
+8
CHANGELOG.md
···
1
1
# Changelog
2
2
3
3
+
## [0.1.2] - 2025-11-28
4
4
+
5
5
+
### Added
6
6
+
7
7
+
- Full JSDoc documentation for all exports
8
8
+
- Module-level documentation with examples
9
9
+
- Examples for all public methods
10
10
+
3
11
## [0.1.1] - 2025-11-28
4
12
5
13
### Fixed
+1
-1
deno.json
···
1
1
{
2
2
"name": "@tijs/driftline-client",
3
3
-
"version": "0.1.1",
3
3
+
"version": "0.1.2",
4
4
"license": "MIT",
5
5
"exports": "./mod.ts",
6
6
"compilerOptions": {
+127
-16
mod.ts
···
1
1
/**
2
2
-
* Driftline Analytics Client
2
2
+
* @module
3
3
*
4
4
-
* TypeScript client for tracking analytics events from ATProto app views.
4
4
+
* Driftline Analytics Client - anonymous analytics for ATProto app views.
5
5
*
6
6
-
* Usage:
7
7
-
* const uid = await deriveUidFromDid(user.did, YOUR_APP_SALT);
8
8
-
* const analytics = new AnalyticsClient({
9
9
-
* appView: "xyz.kipclip.feed",
10
10
-
* env: "prod",
11
11
-
* collectorUrl: "https://driftline.val.run",
12
12
-
* apiKey: YOUR_API_KEY,
13
13
-
* uid,
14
14
-
* });
6
6
+
* @example Basic usage
7
7
+
* ```ts
8
8
+
* import { AnalyticsClient, deriveUidFromDid } from "@tijs/driftline-client";
15
9
*
16
16
-
* await analytics.trackAccountCreated();
17
17
-
* await analytics.trackView("HomeScreen");
18
18
-
* await analytics.trackAction("checkin_created", "CheckinScreen", { placeType: "cafe" });
10
10
+
* // Derive anonymous user ID from DID
11
11
+
* const uid = await deriveUidFromDid(user.did, "your-app-secret-salt");
12
12
+
*
13
13
+
* const analytics = new AnalyticsClient({
14
14
+
* appView: "kipclip.com",
15
15
+
* env: "prod",
16
16
+
* collectorUrl: "https://driftline.val.run",
17
17
+
* apiKey: "your-api-key",
18
18
+
* uid,
19
19
+
* });
20
20
+
*
21
21
+
* // Track events
22
22
+
* await analytics.trackAccountCreated();
23
23
+
* await analytics.trackView("HomeScreen");
24
24
+
* await analytics.trackAction("checkin_created", "CheckinScreen", { placeType: "cafe" });
25
25
+
* ```
19
26
*/
20
27
28
28
+
/**
29
29
+
* Environment type for analytics events.
30
30
+
* Use "dev" for development/testing, "prod" for production.
31
31
+
*/
21
32
export type Environment = "dev" | "prod";
33
33
+
34
34
+
/**
35
35
+
* Type of analytics event.
36
36
+
* - `account` - Track account creation (once per user)
37
37
+
* - `view` - Track screen/page impressions
38
38
+
* - `action` - Track user actions (clicks, submissions, etc.)
39
39
+
*/
22
40
export type EventType = "account" | "view" | "action";
23
41
42
42
+
/**
43
43
+
* Analytics event payload sent to the collector.
44
44
+
*/
24
45
export type AnalyticsEvent = {
46
46
+
/** Event schema version, always 1 */
25
47
v: 1;
48
48
+
/** App view identifier (e.g., "kipclip.com") */
26
49
appView: string;
50
50
+
/** Environment: "dev" or "prod" */
27
51
env: Environment;
52
52
+
/** ISO 8601 timestamp */
28
53
ts: string;
54
54
+
/** Pseudonymous user ID (12-char hex) */
29
55
uid: string;
56
56
+
/** Event type */
30
57
type: EventType;
58
58
+
/** Event name (e.g., "account_created", "screen_impression", "checkin_created") */
31
59
name: string;
60
60
+
/** Screen/page name (optional) */
32
61
screen?: string;
62
62
+
/** Additional properties (optional) */
33
63
props?: Record<string, unknown>;
34
64
};
35
65
66
66
+
/**
67
67
+
* Configuration for the AnalyticsClient.
68
68
+
*
69
69
+
* @example
70
70
+
* ```ts
71
71
+
* const config: AnalyticsClientConfig = {
72
72
+
* appView: "kipclip.com",
73
73
+
* env: "prod",
74
74
+
* collectorUrl: "https://driftline.val.run",
75
75
+
* apiKey: "your-api-key",
76
76
+
* uid: "a1b2c3d4e5f6",
77
77
+
* };
78
78
+
* ```
79
79
+
*/
36
80
export type AnalyticsClientConfig = {
81
81
+
/** App view identifier (e.g., "kipclip.com") */
37
82
appView: string;
83
83
+
/** Environment: "dev" or "prod" */
38
84
env: Environment;
85
85
+
/** Driftline collector URL */
39
86
collectorUrl: string;
87
87
+
/** API key for authentication */
40
88
apiKey: string;
89
89
+
/** Pseudonymous user ID from {@link deriveUidFromDid} */
41
90
uid: string;
42
91
};
43
92
93
93
+
/**
94
94
+
* Client for sending analytics events to Driftline.
95
95
+
*
96
96
+
* @example
97
97
+
* ```ts
98
98
+
* import { AnalyticsClient, deriveUidFromDid } from "@tijs/driftline-client";
99
99
+
*
100
100
+
* const uid = await deriveUidFromDid(user.did, "your-salt");
101
101
+
*
102
102
+
* const analytics = new AnalyticsClient({
103
103
+
* appView: "kipclip.com",
104
104
+
* env: "prod",
105
105
+
* collectorUrl: "https://driftline.val.run",
106
106
+
* apiKey: "your-api-key",
107
107
+
* uid,
108
108
+
* });
109
109
+
*
110
110
+
* await analytics.trackView("HomeScreen");
111
111
+
* await analytics.trackAction("button_clicked", "HomeScreen", { buttonId: "submit" });
112
112
+
* ```
113
113
+
*/
44
114
export class AnalyticsClient {
115
115
+
/**
116
116
+
* Create a new AnalyticsClient instance.
117
117
+
*
118
118
+
* @param cfg - Client configuration
119
119
+
*/
45
120
constructor(private cfg: AnalyticsClientConfig) {}
46
121
47
122
private createEvent(
···
98
173
/**
99
174
* Track when an account is first created/registered for this app view.
100
175
* Should only be called once per user.
176
176
+
*
177
177
+
* @param props - Optional additional properties
178
178
+
*
179
179
+
* @example
180
180
+
* ```ts
181
181
+
* await analytics.trackAccountCreated();
182
182
+
* await analytics.trackAccountCreated({ referrer: "twitter" });
183
183
+
* ```
101
184
*/
102
185
async trackAccountCreated(props?: Record<string, unknown>): Promise<void> {
103
186
const event = this.createEvent(
···
111
194
112
195
/**
113
196
* Track a screen/view impression.
197
197
+
*
198
198
+
* @param screen - Screen or page name
199
199
+
* @param props - Optional additional properties
200
200
+
*
201
201
+
* @example
202
202
+
* ```ts
203
203
+
* await analytics.trackView("HomeScreen");
204
204
+
* await analytics.trackView("ProfileScreen", { userId: "123" });
205
205
+
* ```
114
206
*/
115
207
async trackView(
116
208
screen: string,
···
122
214
123
215
/**
124
216
* Track a user action.
217
217
+
*
218
218
+
* @param name - Action name (e.g., "checkin_created", "button_clicked")
219
219
+
* @param screen - Optional screen where the action occurred
220
220
+
* @param props - Optional additional properties
221
221
+
*
222
222
+
* @example
223
223
+
* ```ts
224
224
+
* await analytics.trackAction("checkin_created");
225
225
+
* await analytics.trackAction("checkin_created", "CheckinScreen");
226
226
+
* await analytics.trackAction("checkin_created", "CheckinScreen", { placeType: "cafe" });
227
227
+
* ```
125
228
*/
126
229
async trackAction(
127
230
name: string,
···
134
237
}
135
238
136
239
/**
137
137
-
* Derive a pseudonymous user ID from a DID.
240
240
+
* Derive a pseudonymous user ID from a DID using SHA-256.
241
241
+
*
138
242
* The same DID + salt will always produce the same uid.
139
139
-
* Different salts (per app view) produce different uids for the same DID.
243
243
+
* Different salts (per app view) produce different uids for the same DID,
244
244
+
* preventing cross-app-view tracking.
140
245
*
141
246
* @param did - The user's DID (e.g., "did:plc:...")
142
247
* @param salt - App-specific salt (keep secret, store in env vars)
143
248
* @returns 12-character hex string
249
249
+
*
250
250
+
* @example
251
251
+
* ```ts
252
252
+
* const uid = await deriveUidFromDid("did:plc:abc123", "my-secret-salt");
253
253
+
* // Returns something like "a1b2c3d4e5f6"
254
254
+
* ```
144
255
*/
145
256
export async function deriveUidFromDid(
146
257
did: string,