rybbit.ts 1.0.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 +21 -0
- package/README.md +3 -0
- package/package.json +27 -0
- package/src/endpoints.ts +609 -0
- package/src/index.ts +16 -0
- package/src/types.ts +130 -0
- package/src/utility.ts +10 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jacob Humston
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rybbit.ts",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"module": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"format": "bunx prettier --write --cache .",
|
|
9
|
+
"compile": "del dist/ && bunx tsc",
|
|
10
|
+
"docs": "del docs/ && bunx typedoc src/index.ts --options typedoc.json"
|
|
11
|
+
},
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@types/node": "^25.3.0",
|
|
14
|
+
"del-cli": "^7.0.0",
|
|
15
|
+
"prettier": "^3.8.1",
|
|
16
|
+
"typedoc": "^0.28.17",
|
|
17
|
+
"typedoc-plugin-mdn-links": "^5.1.1",
|
|
18
|
+
"typedoc-rhineai-theme": "^1.2.0",
|
|
19
|
+
"typescript": "^5.9.3"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"src/",
|
|
23
|
+
"LICENSE",
|
|
24
|
+
"README.md",
|
|
25
|
+
"package.json"
|
|
26
|
+
]
|
|
27
|
+
}
|
package/src/endpoints.ts
ADDED
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
DateString,
|
|
3
|
+
TimeZone,
|
|
4
|
+
Filter,
|
|
5
|
+
Bucket,
|
|
6
|
+
Parameter,
|
|
7
|
+
Timestamp,
|
|
8
|
+
SortBy,
|
|
9
|
+
Order,
|
|
10
|
+
Mode,
|
|
11
|
+
Dimension
|
|
12
|
+
} from './types.js';
|
|
13
|
+
|
|
14
|
+
/** Route interfaces, used to construct URLs. */
|
|
15
|
+
export class Routes {
|
|
16
|
+
/** Base URL for this route constructor. */
|
|
17
|
+
#base: URL;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Create a new route constructor.
|
|
21
|
+
* @param base The base URL for this constructor.
|
|
22
|
+
*/
|
|
23
|
+
constructor(base: URL) {
|
|
24
|
+
this.#base = base;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Create a URL.
|
|
29
|
+
* @param path The path of this URL.
|
|
30
|
+
* @param queries The queries for this URL.
|
|
31
|
+
* @returns The created URL.
|
|
32
|
+
*/
|
|
33
|
+
#create(path: string, queries?: Record<string, string | undefined>): URL {
|
|
34
|
+
const url = new URL(`${this.#base.origin}${path}`);
|
|
35
|
+
|
|
36
|
+
if (queries) {
|
|
37
|
+
const search = url.searchParams;
|
|
38
|
+
for (const [name, value] of Object.entries(queries)) {
|
|
39
|
+
if (value === undefined) continue;
|
|
40
|
+
search.set(name, value);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return url;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// SITES
|
|
48
|
+
|
|
49
|
+
/** `GET` Returns details for a specific site */
|
|
50
|
+
getSite(siteId: number): URL {
|
|
51
|
+
return this.#create(`/api/sites/${siteId}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** `DELETE` Permanently deletes a site and all its data. Requires admin/owner role. */
|
|
55
|
+
deleteSite(siteId: number): URL {
|
|
56
|
+
return this.#create(`/api/sites/${siteId}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** `PUT` Updates site configuration settings. Requires admin/owner role. */
|
|
60
|
+
updateSiteConfig(siteId: number): URL {
|
|
61
|
+
return this.#create(`/api/sites/${siteId}/config`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** `GET` Returns the list of excluded IP addresses */
|
|
65
|
+
getExcludedIPs(siteId: number): URL {
|
|
66
|
+
return this.#create(`/api/sites/${siteId}/excluded-ips`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** `GET` Returns the list of excluded country codes */
|
|
70
|
+
getExcludedCountries(siteId: number): URL {
|
|
71
|
+
return this.#create(`/api/sites/${siteId}/excluded-counties`);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** `GET` Returns the private link key configuration */
|
|
75
|
+
getPrivateLinkConfig(siteId: number): URL {
|
|
76
|
+
return this.#create(`/api/sites/${siteId}/private-link-config`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** `POST` Generates or revokes a private link key. Requires admin/owner role. */
|
|
80
|
+
updatePrivateLinkConfig(siteId: number): URL {
|
|
81
|
+
return this.#create(`/api/sites/${siteId}/private-link-config`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ORGANIZATIONS
|
|
85
|
+
|
|
86
|
+
/** `GET` Returns all organizations the authenticated user is a member of, including all members for each organization */
|
|
87
|
+
getMyOrganizations(): URL {
|
|
88
|
+
return this.#create(`/api/organizations`);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** `POST` Creates a new site in an organization. Requires admin/owner role. */
|
|
92
|
+
createSite(organizationId: string): URL {
|
|
93
|
+
return this.#create(`/api/organizations/${organizationId}/sites`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/** `GET` Returns all members of an organization with user details */
|
|
97
|
+
getOrganizationMembers(organizationId: string): URL {
|
|
98
|
+
return this.#create(`/api/organizations/${organizationId}/members`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** `POST` Adds a user to an organization with a specified role */
|
|
102
|
+
addOrganizationMember(organizationId: string): URL {
|
|
103
|
+
return this.#create(`/api/organizations/${organizationId}/members`);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// OVERVIEW
|
|
107
|
+
|
|
108
|
+
/** `GET` Returns high-level analytics metrics for a site */
|
|
109
|
+
getOverview(
|
|
110
|
+
siteId: number,
|
|
111
|
+
startDate?: DateString,
|
|
112
|
+
endDate?: DateString,
|
|
113
|
+
timezone?: TimeZone,
|
|
114
|
+
filters?: Array<Filter>
|
|
115
|
+
): URL {
|
|
116
|
+
return this.#create(`/api/sites/${siteId}/overview`, {
|
|
117
|
+
start_date: startDate,
|
|
118
|
+
end_date: endDate,
|
|
119
|
+
time_zone: timezone,
|
|
120
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** `GET` Returns time-series analytics data broken down by time buckets */
|
|
125
|
+
getOverviewTimeSeries(
|
|
126
|
+
siteId: number,
|
|
127
|
+
startDate?: DateString,
|
|
128
|
+
endDate?: DateString,
|
|
129
|
+
timezone?: TimeZone,
|
|
130
|
+
filters?: Array<Filter>,
|
|
131
|
+
bucket?: Bucket
|
|
132
|
+
): URL {
|
|
133
|
+
return this.#create(`/api/sites/${siteId}/overview-bucketed`, {
|
|
134
|
+
start_date: startDate,
|
|
135
|
+
end_date: endDate,
|
|
136
|
+
time_zone: timezone,
|
|
137
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
138
|
+
bucket: bucket
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** `GET` Returns dimensional analytics broken down by a specific parameter */
|
|
143
|
+
getMetric(
|
|
144
|
+
siteId: number,
|
|
145
|
+
parameter: Parameter,
|
|
146
|
+
startDate?: DateString,
|
|
147
|
+
endDate?: DateString,
|
|
148
|
+
timezone?: TimeZone,
|
|
149
|
+
filters?: Array<Filter>,
|
|
150
|
+
limit?: number,
|
|
151
|
+
page?: number
|
|
152
|
+
): URL {
|
|
153
|
+
return this.#create(`/api/sites/${siteId}/metric`, {
|
|
154
|
+
start_date: startDate,
|
|
155
|
+
end_date: endDate,
|
|
156
|
+
time_zone: timezone,
|
|
157
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
158
|
+
parameter: parameter,
|
|
159
|
+
limit: limit?.toString(),
|
|
160
|
+
page: page?.toString()
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** `GET` Returns the count of active sessions within the specified time window */
|
|
165
|
+
getLiveVisitors(siteId: number, minutes?: number): URL {
|
|
166
|
+
return this.#create(`/api/sites/${siteId}/live-user-count`, {
|
|
167
|
+
minutes: minutes?.toString()
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// EVENTS
|
|
172
|
+
|
|
173
|
+
/** `GET` Returns a paginated list of events with cursor-based pagination */
|
|
174
|
+
getEvents(
|
|
175
|
+
siteId: number,
|
|
176
|
+
startDate?: DateString,
|
|
177
|
+
endDate?: DateString,
|
|
178
|
+
timezone?: TimeZone,
|
|
179
|
+
filters?: Array<Filter>,
|
|
180
|
+
pageSize?: number,
|
|
181
|
+
sinceTimestamp?: Timestamp,
|
|
182
|
+
beforeTimestamp?: Timestamp
|
|
183
|
+
): URL {
|
|
184
|
+
return this.#create(`/api/sites/${siteId}/events`, {
|
|
185
|
+
start_date: startDate,
|
|
186
|
+
end_date: endDate,
|
|
187
|
+
time_zone: timezone,
|
|
188
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
189
|
+
page_size: pageSize?.toString(),
|
|
190
|
+
since_timestamp: sinceTimestamp,
|
|
191
|
+
before_timestamp: beforeTimestamp
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** `GET` Returns list of unique custom event names with counts */
|
|
196
|
+
getEventNames(
|
|
197
|
+
siteId: number,
|
|
198
|
+
startDate?: DateString,
|
|
199
|
+
endDate?: DateString,
|
|
200
|
+
timezone?: TimeZone,
|
|
201
|
+
filters?: Array<Filter>
|
|
202
|
+
): URL {
|
|
203
|
+
return this.#create(`/api/sites/${siteId}/events/names`, {
|
|
204
|
+
start_date: startDate,
|
|
205
|
+
end_date: endDate,
|
|
206
|
+
time_zone: timezone,
|
|
207
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** `GET` Returns property key-value pairs for a specific event */
|
|
212
|
+
getEventProperties(
|
|
213
|
+
siteId: number,
|
|
214
|
+
eventName: string,
|
|
215
|
+
startDate?: DateString,
|
|
216
|
+
endDate?: DateString,
|
|
217
|
+
timezone?: TimeZone,
|
|
218
|
+
filters?: Array<Filter>
|
|
219
|
+
): URL {
|
|
220
|
+
return this.#create(`/api/sites/${siteId}/events/properties`, {
|
|
221
|
+
start_date: startDate,
|
|
222
|
+
end_date: endDate,
|
|
223
|
+
time_zone: timezone,
|
|
224
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
225
|
+
event_name: eventName
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** `GET` Returns outbound link clicks with occurrence counts */
|
|
230
|
+
getOutboundLinks(
|
|
231
|
+
siteId: number,
|
|
232
|
+
startDate?: DateString,
|
|
233
|
+
endDate?: DateString,
|
|
234
|
+
timezone?: TimeZone,
|
|
235
|
+
filters?: Array<Filter>
|
|
236
|
+
): URL {
|
|
237
|
+
return this.#create(`/api/sites/${siteId}/events/outbound`, {
|
|
238
|
+
start_date: startDate,
|
|
239
|
+
end_date: endDate,
|
|
240
|
+
time_zone: timezone,
|
|
241
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ERRORS
|
|
246
|
+
|
|
247
|
+
/** `GET` Returns unique error messages with occurrence and session counts */
|
|
248
|
+
getErrorNames(
|
|
249
|
+
siteId: number,
|
|
250
|
+
startDate?: DateString,
|
|
251
|
+
endDate?: DateString,
|
|
252
|
+
timezone?: TimeZone,
|
|
253
|
+
filters?: Array<Filter>,
|
|
254
|
+
page?: number,
|
|
255
|
+
limit?: number
|
|
256
|
+
): URL {
|
|
257
|
+
return this.#create(`/api/sites/${siteId}/error-names`, {
|
|
258
|
+
start_date: startDate,
|
|
259
|
+
end_date: endDate,
|
|
260
|
+
time_zone: timezone,
|
|
261
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
262
|
+
page: page?.toString(),
|
|
263
|
+
limit: limit?.toString()
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** `GET` Returns individual error occurrences with context and stack traces */
|
|
268
|
+
getErrorEvents(
|
|
269
|
+
siteId: number,
|
|
270
|
+
errorMessage: string,
|
|
271
|
+
startDate?: DateString,
|
|
272
|
+
endDate?: DateString,
|
|
273
|
+
timezone?: TimeZone,
|
|
274
|
+
filters?: Array<Filter>,
|
|
275
|
+
page?: number,
|
|
276
|
+
limit?: number
|
|
277
|
+
): URL {
|
|
278
|
+
return this.#create(`/api/sites/${siteId}/error-events`, {
|
|
279
|
+
start_date: startDate,
|
|
280
|
+
end_date: endDate,
|
|
281
|
+
time_zone: timezone,
|
|
282
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
283
|
+
page: page?.toString(),
|
|
284
|
+
limit: limit?.toString(),
|
|
285
|
+
errorMessage: errorMessage
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/** `GET` Returns error occurrence counts over time */
|
|
290
|
+
getErrorTimeSeries(
|
|
291
|
+
siteId: number,
|
|
292
|
+
errorMessage: string,
|
|
293
|
+
startDate?: DateString,
|
|
294
|
+
endDate?: DateString,
|
|
295
|
+
timezone?: TimeZone,
|
|
296
|
+
filters?: Array<Filter>,
|
|
297
|
+
bucket?: Bucket
|
|
298
|
+
): URL {
|
|
299
|
+
return this.#create(`/api/sites/${siteId}/error-bucketed`, {
|
|
300
|
+
start_date: startDate,
|
|
301
|
+
end_date: endDate,
|
|
302
|
+
time_zone: timezone,
|
|
303
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
304
|
+
bucket: bucket,
|
|
305
|
+
errorMessage: errorMessage
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// GOALS
|
|
310
|
+
|
|
311
|
+
/** `GET` Returns paginated list of goals with conversion metrics */
|
|
312
|
+
getGoals(
|
|
313
|
+
siteId: number,
|
|
314
|
+
startDate?: DateString,
|
|
315
|
+
endDate?: DateString,
|
|
316
|
+
timezone?: TimeZone,
|
|
317
|
+
filters?: Array<Filter>,
|
|
318
|
+
page?: number,
|
|
319
|
+
pageSize?: number,
|
|
320
|
+
sortBy?: SortBy,
|
|
321
|
+
order?: Order
|
|
322
|
+
): URL {
|
|
323
|
+
return this.#create(`/api/sites/${siteId}/goals`, {
|
|
324
|
+
start_date: startDate,
|
|
325
|
+
end_date: endDate,
|
|
326
|
+
time_zone: timezone,
|
|
327
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
328
|
+
page: page?.toString(),
|
|
329
|
+
page_size: pageSize?.toString(),
|
|
330
|
+
sort: sortBy,
|
|
331
|
+
order: order
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/** `GET` Returns sessions that completed a specific goal */
|
|
336
|
+
getGoalSessions(
|
|
337
|
+
siteId: number,
|
|
338
|
+
goalId: number,
|
|
339
|
+
startDate?: DateString,
|
|
340
|
+
endDate?: DateString,
|
|
341
|
+
timezone?: TimeZone,
|
|
342
|
+
filters?: Array<Filter>,
|
|
343
|
+
page?: number,
|
|
344
|
+
limit?: number
|
|
345
|
+
): URL {
|
|
346
|
+
return this.#create(`/api/sites/${siteId}/goals/${goalId}/sessions`, {
|
|
347
|
+
start_date: startDate,
|
|
348
|
+
end_date: endDate,
|
|
349
|
+
time_zone: timezone,
|
|
350
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
351
|
+
page: page?.toString(),
|
|
352
|
+
limit: limit?.toString()
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/** `POST` Creates a new goal */
|
|
357
|
+
createGoal(siteId: number): URL {
|
|
358
|
+
return this.#create(`/api/sites/${siteId}/goals`);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/** `PUT` Updates an existing goal */
|
|
362
|
+
updateGoal(siteId: number, goalId: number): URL {
|
|
363
|
+
return this.#create(`/api/sites/${siteId}/goals/${goalId}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** `DELETE` Deletes a goal */
|
|
367
|
+
deleteGoal(siteId: number, goalId: number): URL {
|
|
368
|
+
return this.#create(`/api/sites/${siteId}/goals/${goalId}`);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// FUNNELS
|
|
372
|
+
|
|
373
|
+
/** `GET` Returns all saved funnels for a site */
|
|
374
|
+
getFunnels(siteId: number): URL {
|
|
375
|
+
return this.#create(`/api/sites/${siteId}/funnels`);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/** `GET` Analyzes funnel conversion data step-by-step */
|
|
379
|
+
analyzeFunnel(
|
|
380
|
+
siteId: number,
|
|
381
|
+
startDate?: DateString,
|
|
382
|
+
endDate?: DateString,
|
|
383
|
+
timezone?: TimeZone,
|
|
384
|
+
filters?: Array<Filter>
|
|
385
|
+
): URL {
|
|
386
|
+
return this.#create(`/api/sites/${siteId}/funnels/analyze`, {
|
|
387
|
+
start_date: startDate,
|
|
388
|
+
end_date: endDate,
|
|
389
|
+
time_zone: timezone,
|
|
390
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** `GET` Returns sessions that reached or dropped at a specific funnel step */
|
|
395
|
+
getFunnelStepSessions(
|
|
396
|
+
siteId: number,
|
|
397
|
+
stepNumber: number,
|
|
398
|
+
mode: Mode,
|
|
399
|
+
startDate?: DateString,
|
|
400
|
+
endDate?: DateString,
|
|
401
|
+
timezone?: TimeZone,
|
|
402
|
+
filters?: Array<Filter>,
|
|
403
|
+
page?: number,
|
|
404
|
+
limit?: number
|
|
405
|
+
): URL {
|
|
406
|
+
return this.#create(`/api/sites/${siteId}/funnels/${stepNumber}/sessions`, {
|
|
407
|
+
start_date: startDate,
|
|
408
|
+
end_date: endDate,
|
|
409
|
+
time_zone: timezone,
|
|
410
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
411
|
+
mode: mode,
|
|
412
|
+
page: page?.toString(),
|
|
413
|
+
limit: limit?.toString()
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** `POST` Creates a saved funnel */
|
|
418
|
+
createFunnel(siteId: number): URL {
|
|
419
|
+
return this.#create(`/api/sites/${siteId}/funnels`);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/** `DELETE` Deletes a saved funnel */
|
|
423
|
+
deleteFunnel(siteId: number, funnelId: number): URL {
|
|
424
|
+
return this.#create(`/api/sites/${siteId}/funnels/${funnelId}`);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// PERFORMANCE
|
|
428
|
+
|
|
429
|
+
/** `GET` Returns aggregate Core Web Vitals metrics */
|
|
430
|
+
getPerformanceOverview(
|
|
431
|
+
siteId: number,
|
|
432
|
+
startDate?: DateString,
|
|
433
|
+
endDate?: DateString,
|
|
434
|
+
timezone?: TimeZone,
|
|
435
|
+
filters?: Array<Filter>
|
|
436
|
+
): URL {
|
|
437
|
+
return this.#create(`/api/sites/${siteId}/performance/overview`, {
|
|
438
|
+
start_date: startDate,
|
|
439
|
+
end_date: endDate,
|
|
440
|
+
time_zone: timezone,
|
|
441
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/** `GET` Returns performance metrics over time */
|
|
446
|
+
getPerformanceTimeSeries(
|
|
447
|
+
siteId: number,
|
|
448
|
+
startDate?: DateString,
|
|
449
|
+
endDate?: DateString,
|
|
450
|
+
timezone?: TimeZone,
|
|
451
|
+
filters?: Array<Filter>,
|
|
452
|
+
bucket?: Bucket
|
|
453
|
+
): URL {
|
|
454
|
+
return this.#create(`/api/sites/${siteId}/performance/time-series`, {
|
|
455
|
+
start_date: startDate,
|
|
456
|
+
end_date: endDate,
|
|
457
|
+
time_zone: timezone,
|
|
458
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
459
|
+
bucket: bucket
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
/** `GET` Returns performance breakdown by dimension */
|
|
464
|
+
getPerformanceByDimension(
|
|
465
|
+
siteId: number,
|
|
466
|
+
dimension: Dimension,
|
|
467
|
+
startDate?: DateString,
|
|
468
|
+
endDate?: DateString,
|
|
469
|
+
timezone?: TimeZone,
|
|
470
|
+
filters?: Array<Filter>,
|
|
471
|
+
page?: number,
|
|
472
|
+
limit?: number,
|
|
473
|
+
sortBy?: SortBy,
|
|
474
|
+
sortOrder?: Order
|
|
475
|
+
): URL {
|
|
476
|
+
return this.#create(`/api/sites/${siteId}/performance/by-dimension`, {
|
|
477
|
+
start_date: startDate,
|
|
478
|
+
end_date: endDate,
|
|
479
|
+
time_zone: timezone,
|
|
480
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
481
|
+
dimension: dimension,
|
|
482
|
+
page: page?.toString(),
|
|
483
|
+
limit: limit?.toString(),
|
|
484
|
+
sort_by: sortBy,
|
|
485
|
+
sort_order: sortOrder
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
// SESSIONS
|
|
490
|
+
|
|
491
|
+
/** `GET` Returns a paginated list of sessions */
|
|
492
|
+
getSessions(
|
|
493
|
+
siteId: number,
|
|
494
|
+
startDate?: DateString,
|
|
495
|
+
endDate?: DateString,
|
|
496
|
+
timezone?: TimeZone,
|
|
497
|
+
filters?: Array<Filter>,
|
|
498
|
+
page?: number,
|
|
499
|
+
limit?: number,
|
|
500
|
+
userId?: string,
|
|
501
|
+
identifiedOnly?: boolean
|
|
502
|
+
): URL {
|
|
503
|
+
return this.#create(`/api/sites/${siteId}/sessions`, {
|
|
504
|
+
start_date: startDate,
|
|
505
|
+
end_date: endDate,
|
|
506
|
+
time_zone: timezone,
|
|
507
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
508
|
+
page: page?.toString(),
|
|
509
|
+
limit: limit?.toString(),
|
|
510
|
+
user_id: userId,
|
|
511
|
+
identified_only: identifiedOnly?.toString()
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/** `GET` Returns detailed session information with events */
|
|
516
|
+
getSession(siteId: number, sessionId: string, limit?: number, offset?: number): URL {
|
|
517
|
+
return this.#create(`/api/sites/${siteId}/sessions/${sessionId}`, {
|
|
518
|
+
limit: limit?.toString(),
|
|
519
|
+
offset: offset?.toString()
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/** `GET` Returns aggregated session locations for map visualization */
|
|
524
|
+
getSessionLocations(
|
|
525
|
+
siteId: number,
|
|
526
|
+
startDate?: DateString,
|
|
527
|
+
endDate?: DateString,
|
|
528
|
+
timezone?: TimeZone,
|
|
529
|
+
filters?: Array<Filter>
|
|
530
|
+
): URL {
|
|
531
|
+
return this.#create(`/api/sites/${siteId}/session-locations`, {
|
|
532
|
+
start_date: startDate,
|
|
533
|
+
end_date: endDate,
|
|
534
|
+
time_zone: timezone,
|
|
535
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// USERS
|
|
540
|
+
|
|
541
|
+
/** `GET` Returns a paginated list of users */
|
|
542
|
+
getUsers(
|
|
543
|
+
siteId: number,
|
|
544
|
+
startDate?: DateString,
|
|
545
|
+
endDate?: DateString,
|
|
546
|
+
timezone?: TimeZone,
|
|
547
|
+
filters?: Array<Filter>,
|
|
548
|
+
page?: number,
|
|
549
|
+
pageSize?: number,
|
|
550
|
+
sortBy?: SortBy,
|
|
551
|
+
sortOrder?: Order,
|
|
552
|
+
identifiedOnly?: boolean
|
|
553
|
+
): URL {
|
|
554
|
+
return this.#create(`/api/sites/${siteId}/users`, {
|
|
555
|
+
start_date: startDate,
|
|
556
|
+
end_date: endDate,
|
|
557
|
+
time_zone: timezone,
|
|
558
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
559
|
+
page: page?.toString(),
|
|
560
|
+
page_size: pageSize?.toString(),
|
|
561
|
+
sort_by: sortBy,
|
|
562
|
+
sort_order: sortOrder,
|
|
563
|
+
identified_only: identifiedOnly?.toString()
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/** `GET` Returns daily session counts for a specific user */
|
|
568
|
+
getUserSessionCount(siteId: number, userId: string, timezone?: TimeZone): URL {
|
|
569
|
+
return this.#create(`/api/sites/${siteId}/users/session-count`, {
|
|
570
|
+
user_id: userId,
|
|
571
|
+
timezone: timezone
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/** `GET` Returns detailed user profile information */
|
|
576
|
+
getUserInfo(siteId: number, userId: string): URL {
|
|
577
|
+
return this.#create(`/api/sites/${siteId}/users/${userId}`);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// MISC
|
|
581
|
+
|
|
582
|
+
/** `GET` Returns cohort-based retention analysis */
|
|
583
|
+
getRetention(siteId: number, mode?: Mode, range?: number): URL {
|
|
584
|
+
return this.#create(`/api/sites/${siteId}/retention`, {
|
|
585
|
+
mode: mode,
|
|
586
|
+
range: range?.toString()
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
/** `GET` Returns most common page navigation paths */
|
|
591
|
+
getJourneys(
|
|
592
|
+
siteId: number,
|
|
593
|
+
startDate?: DateString,
|
|
594
|
+
endDate?: DateString,
|
|
595
|
+
timezone?: TimeZone,
|
|
596
|
+
filters?: Array<Filter>,
|
|
597
|
+
steps?: number,
|
|
598
|
+
limit?: number
|
|
599
|
+
): URL {
|
|
600
|
+
return this.#create(`/api/sites/${siteId}/users`, {
|
|
601
|
+
start_date: startDate,
|
|
602
|
+
end_date: endDate,
|
|
603
|
+
time_zone: timezone,
|
|
604
|
+
filters: filters !== undefined ? JSON.stringify(filters) : undefined,
|
|
605
|
+
steps: steps?.toString(),
|
|
606
|
+
limit: limit?.toString()
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
Bucket,
|
|
3
|
+
DateString,
|
|
4
|
+
Dimension,
|
|
5
|
+
Filter,
|
|
6
|
+
FilterParameter,
|
|
7
|
+
FilterType,
|
|
8
|
+
Mode,
|
|
9
|
+
Order,
|
|
10
|
+
Parameter,
|
|
11
|
+
SortBy,
|
|
12
|
+
Timestamp,
|
|
13
|
+
TimeZone
|
|
14
|
+
} from './types.js';
|
|
15
|
+
export { toDateString } from './utility.js';
|
|
16
|
+
export { Routes } from './endpoints.js';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A date with the format of `year-month-day`.
|
|
3
|
+
* Example: `2019-02-24`
|
|
4
|
+
*/
|
|
5
|
+
export type DateString = `${number}-${number}-${number}`;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* An ISO 8601 formatted timestamp.
|
|
9
|
+
* Example: `2024-01-31T14:00:00.000Z`
|
|
10
|
+
*/
|
|
11
|
+
export type Timestamp = string;
|
|
12
|
+
|
|
13
|
+
/** List of timezones. */
|
|
14
|
+
export type TimeZone =
|
|
15
|
+
| 'system'
|
|
16
|
+
| 'Pacific/Honolulu'
|
|
17
|
+
| 'America/Anchorage'
|
|
18
|
+
| 'America/Los_Angeles'
|
|
19
|
+
| 'America/Denver'
|
|
20
|
+
| 'America/Chicago'
|
|
21
|
+
| 'America/New_York'
|
|
22
|
+
| 'America/Halifax'
|
|
23
|
+
| 'America/Sao_Paulo'
|
|
24
|
+
| 'Atlantic/South_Georgia'
|
|
25
|
+
| 'Atlantic/Azores'
|
|
26
|
+
| 'UTC'
|
|
27
|
+
| 'Europe/London'
|
|
28
|
+
| 'Europe/Paris'
|
|
29
|
+
| 'Europe/Berlin'
|
|
30
|
+
| 'Europe/Helsinki'
|
|
31
|
+
| 'Europe/Moscow'
|
|
32
|
+
| 'Asia/Dubai'
|
|
33
|
+
| 'Asia/Karachi'
|
|
34
|
+
| 'Asia/Kolkata'
|
|
35
|
+
| 'Asia/Dhaka'
|
|
36
|
+
| 'Asia/Bangkok'
|
|
37
|
+
| 'Asia/Singapore'
|
|
38
|
+
| 'Asia/Shanghai'
|
|
39
|
+
| 'Asia/Tokyo'
|
|
40
|
+
| 'Australia/Sydney'
|
|
41
|
+
| 'Pacific/Auckland';
|
|
42
|
+
|
|
43
|
+
/** List of buckets. */
|
|
44
|
+
export type Bucket =
|
|
45
|
+
| 'minute'
|
|
46
|
+
| 'five_minutes'
|
|
47
|
+
| 'ten_minutes'
|
|
48
|
+
| 'fifteen_minutes'
|
|
49
|
+
| 'hour'
|
|
50
|
+
| 'day'
|
|
51
|
+
| 'week'
|
|
52
|
+
| 'month'
|
|
53
|
+
| 'week'
|
|
54
|
+
| 'year';
|
|
55
|
+
|
|
56
|
+
/** List of parameters. */
|
|
57
|
+
export type Parameter =
|
|
58
|
+
| 'pathname'
|
|
59
|
+
| 'page_title'
|
|
60
|
+
| 'country'
|
|
61
|
+
| 'region'
|
|
62
|
+
| 'city'
|
|
63
|
+
| 'browser'
|
|
64
|
+
| 'operating_system'
|
|
65
|
+
| 'device_type'
|
|
66
|
+
| 'referrer'
|
|
67
|
+
| 'channel'
|
|
68
|
+
| 'utm_source'
|
|
69
|
+
| 'utm_medium'
|
|
70
|
+
| 'utm_campaign'
|
|
71
|
+
| 'utm_term'
|
|
72
|
+
| 'utm_content'
|
|
73
|
+
| 'language'
|
|
74
|
+
| 'entry_page'
|
|
75
|
+
| 'exit_page'
|
|
76
|
+
| 'event_name';
|
|
77
|
+
|
|
78
|
+
/** List of sort by choices. */
|
|
79
|
+
export type SortBy =
|
|
80
|
+
| 'goalId'
|
|
81
|
+
| 'name'
|
|
82
|
+
| 'goalType'
|
|
83
|
+
| 'createdAt'
|
|
84
|
+
| 'first_seen'
|
|
85
|
+
| 'last_seen'
|
|
86
|
+
| 'pageviews'
|
|
87
|
+
| 'sessions'
|
|
88
|
+
| 'events';
|
|
89
|
+
|
|
90
|
+
/** Lust of order choices. */
|
|
91
|
+
export type Order = 'asc' | 'desc';
|
|
92
|
+
|
|
93
|
+
/** List of modes. */
|
|
94
|
+
export type Mode = 'day' | 'week' | 'reached' | 'dropped';
|
|
95
|
+
|
|
96
|
+
/** List of dimensions. */
|
|
97
|
+
export type Dimension = 'pathname' | 'country' | 'browser' | 'operating_system' | 'device_type';
|
|
98
|
+
|
|
99
|
+
/** List of filter parameters. */
|
|
100
|
+
export type FilterParameter =
|
|
101
|
+
| 'country'
|
|
102
|
+
| 'region'
|
|
103
|
+
| 'city'
|
|
104
|
+
| 'browser'
|
|
105
|
+
| 'operating_system'
|
|
106
|
+
| 'device_type'
|
|
107
|
+
| 'pathname'
|
|
108
|
+
| 'referrer'
|
|
109
|
+
| 'utm_source'
|
|
110
|
+
| 'utm_medium'
|
|
111
|
+
| 'utm_campaign'
|
|
112
|
+
| 'channel'
|
|
113
|
+
| 'entry_page'
|
|
114
|
+
| 'exit_page'
|
|
115
|
+
| 'language';
|
|
116
|
+
|
|
117
|
+
/** List of filter types. */
|
|
118
|
+
export type FilterType = 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'regex';
|
|
119
|
+
|
|
120
|
+
/** A filter object. */
|
|
121
|
+
export interface Filter {
|
|
122
|
+
/** {@linkcode FilterParameter Parameter} of this filter. */
|
|
123
|
+
parameter: FilterParameter;
|
|
124
|
+
|
|
125
|
+
/** {@linkcode FilterType Type} of filter. */
|
|
126
|
+
type: FilterType;
|
|
127
|
+
|
|
128
|
+
/** Values of this filter. */
|
|
129
|
+
value: Array<string>;
|
|
130
|
+
}
|
package/src/utility.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DateString } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Converts a {@linkcode Date} to {@linkcode DateString}.
|
|
5
|
+
* @param date The {@linkcode Date} to convert.
|
|
6
|
+
* @returns The converted {@linkcode DateString}.
|
|
7
|
+
*/
|
|
8
|
+
export function toDateString(date: Date): DateString {
|
|
9
|
+
return date.toISOString().split('T')[0] as DateString;
|
|
10
|
+
}
|