digital-tools 2.0.2 → 2.1.1
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/CHANGELOG.md +17 -0
- package/package.json +3 -4
- package/src/define.js +267 -0
- package/src/entities/advertising.js +999 -0
- package/src/entities/ai.js +756 -0
- package/src/entities/analytics.js +1588 -0
- package/src/entities/automation.js +601 -0
- package/src/entities/communication.js +1150 -0
- package/src/entities/crm.js +1386 -0
- package/src/entities/design.js +546 -0
- package/src/entities/development.js +2212 -0
- package/src/entities/document.js +874 -0
- package/src/entities/ecommerce.js +1429 -0
- package/src/entities/experiment.js +1039 -0
- package/src/entities/finance.js +3478 -0
- package/src/entities/forms.js +1892 -0
- package/src/entities/hr.js +661 -0
- package/src/entities/identity.js +997 -0
- package/src/entities/index.js +282 -0
- package/src/entities/infrastructure.js +1153 -0
- package/src/entities/knowledge.js +1438 -0
- package/src/entities/marketing.js +1610 -0
- package/src/entities/media.js +1634 -0
- package/src/entities/notification.js +1199 -0
- package/src/entities/presentation.js +1274 -0
- package/src/entities/productivity.js +1317 -0
- package/src/entities/project-management.js +1136 -0
- package/src/entities/recruiting.js +736 -0
- package/src/entities/shipping.js +509 -0
- package/src/entities/signature.js +1102 -0
- package/src/entities/site.js +222 -0
- package/src/entities/spreadsheet.js +1341 -0
- package/src/entities/storage.js +1198 -0
- package/src/entities/support.js +1166 -0
- package/src/entities/video-conferencing.js +1750 -0
- package/src/entities/video.js +950 -0
- package/src/entities.js +1663 -0
- package/src/index.js +74 -0
- package/src/providers/analytics/index.js +17 -0
- package/src/providers/analytics/mixpanel.js +255 -0
- package/src/providers/calendar/cal-com.js +303 -0
- package/src/providers/calendar/google-calendar.js +335 -0
- package/src/providers/calendar/index.js +20 -0
- package/src/providers/crm/hubspot.js +566 -0
- package/src/providers/crm/index.js +17 -0
- package/src/providers/development/github.js +472 -0
- package/src/providers/development/index.js +17 -0
- package/src/providers/ecommerce/index.js +17 -0
- package/src/providers/ecommerce/shopify.js +378 -0
- package/src/providers/email/index.js +20 -0
- package/src/providers/email/resend.js +258 -0
- package/src/providers/email/sendgrid.js +161 -0
- package/src/providers/finance/index.js +17 -0
- package/src/providers/finance/stripe.js +549 -0
- package/src/providers/forms/index.js +17 -0
- package/src/providers/forms/typeform.js +500 -0
- package/src/providers/index.js +123 -0
- package/src/providers/knowledge/index.js +17 -0
- package/src/providers/knowledge/notion.js +389 -0
- package/src/providers/marketing/index.js +17 -0
- package/src/providers/marketing/mailchimp.js +443 -0
- package/src/providers/media/cloudinary.js +318 -0
- package/src/providers/media/index.js +17 -0
- package/src/providers/messaging/index.js +20 -0
- package/src/providers/messaging/slack.js +393 -0
- package/src/providers/messaging/twilio-sms.js +249 -0
- package/src/providers/project-management/index.js +17 -0
- package/src/providers/project-management/linear.js +575 -0
- package/src/providers/registry.js +86 -0
- package/src/providers/spreadsheet/google-sheets.js +375 -0
- package/src/providers/spreadsheet/index.js +20 -0
- package/src/providers/spreadsheet/xlsx.js +423 -0
- package/src/providers/storage/index.js +24 -0
- package/src/providers/storage/s3.js +419 -0
- package/src/providers/support/index.js +17 -0
- package/src/providers/support/zendesk.js +373 -0
- package/src/providers/tasks/index.js +17 -0
- package/src/providers/tasks/todoist.js +286 -0
- package/src/providers/types.js +9 -0
- package/src/providers/video-conferencing/google-meet.js +286 -0
- package/src/providers/video-conferencing/index.js +31 -0
- package/src/providers/video-conferencing/jitsi.js +254 -0
- package/src/providers/video-conferencing/teams.js +270 -0
- package/src/providers/video-conferencing/zoom.js +332 -0
- package/src/registry.js +128 -0
- package/src/tools/communication.js +184 -0
- package/src/tools/data.js +205 -0
- package/src/tools/index.js +11 -0
- package/src/tools/web.js +137 -0
- package/src/types.js +10 -0
- package/test/define.test.js +306 -0
- package/test/registry.test.js +357 -0
- package/test/tools.test.js +363 -0
|
@@ -0,0 +1,1039 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Experimentation & Analytics Entity Types (Nouns)
|
|
3
|
+
*
|
|
4
|
+
* Entities for product analytics, feature flags, A/B testing, and user tracking.
|
|
5
|
+
* Covers Google Analytics, PostHog, Mixpanel, LaunchDarkly, etc.
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
// =============================================================================
|
|
10
|
+
// Session
|
|
11
|
+
// =============================================================================
|
|
12
|
+
/**
|
|
13
|
+
* Session entity
|
|
14
|
+
*
|
|
15
|
+
* Represents a user session for analytics tracking
|
|
16
|
+
*/
|
|
17
|
+
export const Session = {
|
|
18
|
+
singular: 'session',
|
|
19
|
+
plural: 'sessions',
|
|
20
|
+
description: 'A user session for analytics tracking',
|
|
21
|
+
properties: {
|
|
22
|
+
// Identity
|
|
23
|
+
sessionId: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
description: 'Unique session identifier',
|
|
26
|
+
},
|
|
27
|
+
userId: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
optional: true,
|
|
30
|
+
description: 'Identified user ID (if logged in)',
|
|
31
|
+
},
|
|
32
|
+
anonymousId: {
|
|
33
|
+
type: 'string',
|
|
34
|
+
optional: true,
|
|
35
|
+
description: 'Anonymous visitor ID',
|
|
36
|
+
},
|
|
37
|
+
// Timing
|
|
38
|
+
startedAt: {
|
|
39
|
+
type: 'datetime',
|
|
40
|
+
description: 'Session start time',
|
|
41
|
+
},
|
|
42
|
+
endedAt: {
|
|
43
|
+
type: 'datetime',
|
|
44
|
+
optional: true,
|
|
45
|
+
description: 'Session end time',
|
|
46
|
+
},
|
|
47
|
+
duration: {
|
|
48
|
+
type: 'number',
|
|
49
|
+
optional: true,
|
|
50
|
+
description: 'Session duration in seconds',
|
|
51
|
+
},
|
|
52
|
+
// Context
|
|
53
|
+
device: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
optional: true,
|
|
56
|
+
description: 'Device type: desktop, mobile, tablet',
|
|
57
|
+
examples: ['desktop', 'mobile', 'tablet'],
|
|
58
|
+
},
|
|
59
|
+
browser: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
optional: true,
|
|
62
|
+
description: 'Browser name and version',
|
|
63
|
+
},
|
|
64
|
+
os: {
|
|
65
|
+
type: 'string',
|
|
66
|
+
optional: true,
|
|
67
|
+
description: 'Operating system',
|
|
68
|
+
},
|
|
69
|
+
screenResolution: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
optional: true,
|
|
72
|
+
description: 'Screen resolution',
|
|
73
|
+
},
|
|
74
|
+
// Location
|
|
75
|
+
country: {
|
|
76
|
+
type: 'string',
|
|
77
|
+
optional: true,
|
|
78
|
+
description: 'Country code',
|
|
79
|
+
},
|
|
80
|
+
region: {
|
|
81
|
+
type: 'string',
|
|
82
|
+
optional: true,
|
|
83
|
+
description: 'Region/state',
|
|
84
|
+
},
|
|
85
|
+
city: {
|
|
86
|
+
type: 'string',
|
|
87
|
+
optional: true,
|
|
88
|
+
description: 'City',
|
|
89
|
+
},
|
|
90
|
+
timezone: {
|
|
91
|
+
type: 'string',
|
|
92
|
+
optional: true,
|
|
93
|
+
description: 'Timezone',
|
|
94
|
+
},
|
|
95
|
+
// Source
|
|
96
|
+
referrer: {
|
|
97
|
+
type: 'url',
|
|
98
|
+
optional: true,
|
|
99
|
+
description: 'Referrer URL',
|
|
100
|
+
},
|
|
101
|
+
utmSource: {
|
|
102
|
+
type: 'string',
|
|
103
|
+
optional: true,
|
|
104
|
+
description: 'UTM source',
|
|
105
|
+
},
|
|
106
|
+
utmMedium: {
|
|
107
|
+
type: 'string',
|
|
108
|
+
optional: true,
|
|
109
|
+
description: 'UTM medium',
|
|
110
|
+
},
|
|
111
|
+
utmCampaign: {
|
|
112
|
+
type: 'string',
|
|
113
|
+
optional: true,
|
|
114
|
+
description: 'UTM campaign',
|
|
115
|
+
},
|
|
116
|
+
landingPage: {
|
|
117
|
+
type: 'url',
|
|
118
|
+
optional: true,
|
|
119
|
+
description: 'Landing page URL',
|
|
120
|
+
},
|
|
121
|
+
// Engagement
|
|
122
|
+
pageviews: {
|
|
123
|
+
type: 'number',
|
|
124
|
+
optional: true,
|
|
125
|
+
description: 'Number of pageviews',
|
|
126
|
+
},
|
|
127
|
+
events: {
|
|
128
|
+
type: 'number',
|
|
129
|
+
optional: true,
|
|
130
|
+
description: 'Number of events',
|
|
131
|
+
},
|
|
132
|
+
bounced: {
|
|
133
|
+
type: 'boolean',
|
|
134
|
+
optional: true,
|
|
135
|
+
description: 'Whether session bounced',
|
|
136
|
+
},
|
|
137
|
+
converted: {
|
|
138
|
+
type: 'boolean',
|
|
139
|
+
optional: true,
|
|
140
|
+
description: 'Whether session converted',
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
relationships: {
|
|
144
|
+
user: {
|
|
145
|
+
type: 'Contact',
|
|
146
|
+
required: false,
|
|
147
|
+
description: 'Identified user',
|
|
148
|
+
},
|
|
149
|
+
events: {
|
|
150
|
+
type: 'AnalyticsEvent[]',
|
|
151
|
+
description: 'Events in this session',
|
|
152
|
+
},
|
|
153
|
+
pageviews: {
|
|
154
|
+
type: 'Pageview[]',
|
|
155
|
+
description: 'Pageviews in this session',
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
actions: ['track', 'identify', 'end', 'merge'],
|
|
159
|
+
events: ['started', 'identified', 'ended', 'converted', 'bounced'],
|
|
160
|
+
};
|
|
161
|
+
// =============================================================================
|
|
162
|
+
// Analytics Event
|
|
163
|
+
// =============================================================================
|
|
164
|
+
/**
|
|
165
|
+
* Analytics event entity
|
|
166
|
+
*
|
|
167
|
+
* Represents a tracked analytics event
|
|
168
|
+
*/
|
|
169
|
+
export const AnalyticsEvent = {
|
|
170
|
+
singular: 'analytics event',
|
|
171
|
+
plural: 'analytics events',
|
|
172
|
+
description: 'A tracked analytics event',
|
|
173
|
+
properties: {
|
|
174
|
+
// Identity
|
|
175
|
+
eventName: {
|
|
176
|
+
type: 'string',
|
|
177
|
+
description: 'Event name',
|
|
178
|
+
},
|
|
179
|
+
eventType: {
|
|
180
|
+
type: 'string',
|
|
181
|
+
optional: true,
|
|
182
|
+
description: 'Event type: track, page, identify, group',
|
|
183
|
+
examples: ['track', 'page', 'identify', 'group'],
|
|
184
|
+
},
|
|
185
|
+
// Properties
|
|
186
|
+
properties: {
|
|
187
|
+
type: 'json',
|
|
188
|
+
optional: true,
|
|
189
|
+
description: 'Event properties',
|
|
190
|
+
},
|
|
191
|
+
// Context
|
|
192
|
+
timestamp: {
|
|
193
|
+
type: 'datetime',
|
|
194
|
+
description: 'Event timestamp',
|
|
195
|
+
},
|
|
196
|
+
sessionId: {
|
|
197
|
+
type: 'string',
|
|
198
|
+
optional: true,
|
|
199
|
+
description: 'Session ID',
|
|
200
|
+
},
|
|
201
|
+
userId: {
|
|
202
|
+
type: 'string',
|
|
203
|
+
optional: true,
|
|
204
|
+
description: 'User ID',
|
|
205
|
+
},
|
|
206
|
+
anonymousId: {
|
|
207
|
+
type: 'string',
|
|
208
|
+
optional: true,
|
|
209
|
+
description: 'Anonymous ID',
|
|
210
|
+
},
|
|
211
|
+
// Location
|
|
212
|
+
url: {
|
|
213
|
+
type: 'url',
|
|
214
|
+
optional: true,
|
|
215
|
+
description: 'Page URL where event occurred',
|
|
216
|
+
},
|
|
217
|
+
path: {
|
|
218
|
+
type: 'string',
|
|
219
|
+
optional: true,
|
|
220
|
+
description: 'Page path',
|
|
221
|
+
},
|
|
222
|
+
// Device context
|
|
223
|
+
context: {
|
|
224
|
+
type: 'json',
|
|
225
|
+
optional: true,
|
|
226
|
+
description: 'Event context (device, location, etc.)',
|
|
227
|
+
},
|
|
228
|
+
// Value
|
|
229
|
+
value: {
|
|
230
|
+
type: 'number',
|
|
231
|
+
optional: true,
|
|
232
|
+
description: 'Numeric value (e.g., revenue)',
|
|
233
|
+
},
|
|
234
|
+
currency: {
|
|
235
|
+
type: 'string',
|
|
236
|
+
optional: true,
|
|
237
|
+
description: 'Currency code for value',
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
relationships: {
|
|
241
|
+
session: {
|
|
242
|
+
type: 'Session',
|
|
243
|
+
required: false,
|
|
244
|
+
backref: 'events',
|
|
245
|
+
description: 'Parent session',
|
|
246
|
+
},
|
|
247
|
+
user: {
|
|
248
|
+
type: 'Contact',
|
|
249
|
+
required: false,
|
|
250
|
+
description: 'User who triggered event',
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
actions: ['track', 'query', 'aggregate', 'export'],
|
|
254
|
+
events: ['tracked'],
|
|
255
|
+
};
|
|
256
|
+
/**
|
|
257
|
+
* Pageview entity
|
|
258
|
+
*/
|
|
259
|
+
export const Pageview = {
|
|
260
|
+
singular: 'pageview',
|
|
261
|
+
plural: 'pageviews',
|
|
262
|
+
description: 'A page view event',
|
|
263
|
+
properties: {
|
|
264
|
+
url: {
|
|
265
|
+
type: 'url',
|
|
266
|
+
description: 'Page URL',
|
|
267
|
+
},
|
|
268
|
+
path: {
|
|
269
|
+
type: 'string',
|
|
270
|
+
description: 'Page path',
|
|
271
|
+
},
|
|
272
|
+
title: {
|
|
273
|
+
type: 'string',
|
|
274
|
+
optional: true,
|
|
275
|
+
description: 'Page title',
|
|
276
|
+
},
|
|
277
|
+
referrer: {
|
|
278
|
+
type: 'url',
|
|
279
|
+
optional: true,
|
|
280
|
+
description: 'Referrer URL',
|
|
281
|
+
},
|
|
282
|
+
timestamp: {
|
|
283
|
+
type: 'datetime',
|
|
284
|
+
description: 'Pageview timestamp',
|
|
285
|
+
},
|
|
286
|
+
timeOnPage: {
|
|
287
|
+
type: 'number',
|
|
288
|
+
optional: true,
|
|
289
|
+
description: 'Time spent on page in seconds',
|
|
290
|
+
},
|
|
291
|
+
scrollDepth: {
|
|
292
|
+
type: 'number',
|
|
293
|
+
optional: true,
|
|
294
|
+
description: 'Scroll depth percentage',
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
relationships: {
|
|
298
|
+
session: {
|
|
299
|
+
type: 'Session',
|
|
300
|
+
backref: 'pageviews',
|
|
301
|
+
description: 'Parent session',
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
actions: ['track', 'query'],
|
|
305
|
+
events: ['tracked'],
|
|
306
|
+
};
|
|
307
|
+
// =============================================================================
|
|
308
|
+
// Segment
|
|
309
|
+
// =============================================================================
|
|
310
|
+
/**
|
|
311
|
+
* Segment entity
|
|
312
|
+
*
|
|
313
|
+
* Represents a user segment for targeting
|
|
314
|
+
*/
|
|
315
|
+
export const Segment = {
|
|
316
|
+
singular: 'segment',
|
|
317
|
+
plural: 'segments',
|
|
318
|
+
description: 'A user segment for targeting and analysis',
|
|
319
|
+
properties: {
|
|
320
|
+
// Identity
|
|
321
|
+
name: {
|
|
322
|
+
type: 'string',
|
|
323
|
+
description: 'Segment name',
|
|
324
|
+
},
|
|
325
|
+
key: {
|
|
326
|
+
type: 'string',
|
|
327
|
+
optional: true,
|
|
328
|
+
description: 'Segment key/identifier',
|
|
329
|
+
},
|
|
330
|
+
description: {
|
|
331
|
+
type: 'string',
|
|
332
|
+
optional: true,
|
|
333
|
+
description: 'Segment description',
|
|
334
|
+
},
|
|
335
|
+
// Definition
|
|
336
|
+
type: {
|
|
337
|
+
type: 'string',
|
|
338
|
+
description: 'Segment type: static, dynamic, computed',
|
|
339
|
+
examples: ['static', 'dynamic', 'computed'],
|
|
340
|
+
},
|
|
341
|
+
rules: {
|
|
342
|
+
type: 'json',
|
|
343
|
+
optional: true,
|
|
344
|
+
description: 'Segment rules/conditions',
|
|
345
|
+
},
|
|
346
|
+
query: {
|
|
347
|
+
type: 'string',
|
|
348
|
+
optional: true,
|
|
349
|
+
description: 'Segment query definition',
|
|
350
|
+
},
|
|
351
|
+
// Membership
|
|
352
|
+
userCount: {
|
|
353
|
+
type: 'number',
|
|
354
|
+
optional: true,
|
|
355
|
+
description: 'Number of users in segment',
|
|
356
|
+
},
|
|
357
|
+
percentOfTotal: {
|
|
358
|
+
type: 'number',
|
|
359
|
+
optional: true,
|
|
360
|
+
description: 'Percentage of total users',
|
|
361
|
+
},
|
|
362
|
+
// Sync
|
|
363
|
+
syncEnabled: {
|
|
364
|
+
type: 'boolean',
|
|
365
|
+
optional: true,
|
|
366
|
+
description: 'Whether segment syncs to destinations',
|
|
367
|
+
},
|
|
368
|
+
lastSyncedAt: {
|
|
369
|
+
type: 'datetime',
|
|
370
|
+
optional: true,
|
|
371
|
+
description: 'Last sync timestamp',
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
relationships: {
|
|
375
|
+
users: {
|
|
376
|
+
type: 'Contact[]',
|
|
377
|
+
description: 'Users in this segment',
|
|
378
|
+
},
|
|
379
|
+
campaigns: {
|
|
380
|
+
type: 'Campaign[]',
|
|
381
|
+
description: 'Campaigns targeting this segment',
|
|
382
|
+
},
|
|
383
|
+
experiments: {
|
|
384
|
+
type: 'Experiment[]',
|
|
385
|
+
description: 'Experiments using this segment',
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
actions: [
|
|
389
|
+
'create',
|
|
390
|
+
'update',
|
|
391
|
+
'delete',
|
|
392
|
+
'addUser',
|
|
393
|
+
'removeUser',
|
|
394
|
+
'sync',
|
|
395
|
+
'refresh',
|
|
396
|
+
'export',
|
|
397
|
+
],
|
|
398
|
+
events: [
|
|
399
|
+
'created',
|
|
400
|
+
'updated',
|
|
401
|
+
'deleted',
|
|
402
|
+
'userAdded',
|
|
403
|
+
'userRemoved',
|
|
404
|
+
'synced',
|
|
405
|
+
'refreshed',
|
|
406
|
+
],
|
|
407
|
+
};
|
|
408
|
+
// =============================================================================
|
|
409
|
+
// Feature Flag
|
|
410
|
+
// =============================================================================
|
|
411
|
+
/**
|
|
412
|
+
* Feature flag entity
|
|
413
|
+
*
|
|
414
|
+
* Represents a feature flag for controlled rollouts
|
|
415
|
+
*/
|
|
416
|
+
export const FeatureFlag = {
|
|
417
|
+
singular: 'feature flag',
|
|
418
|
+
plural: 'feature flags',
|
|
419
|
+
description: 'A feature flag for controlled feature rollouts',
|
|
420
|
+
properties: {
|
|
421
|
+
// Identity
|
|
422
|
+
key: {
|
|
423
|
+
type: 'string',
|
|
424
|
+
description: 'Feature flag key',
|
|
425
|
+
},
|
|
426
|
+
name: {
|
|
427
|
+
type: 'string',
|
|
428
|
+
optional: true,
|
|
429
|
+
description: 'Human-readable name',
|
|
430
|
+
},
|
|
431
|
+
description: {
|
|
432
|
+
type: 'string',
|
|
433
|
+
optional: true,
|
|
434
|
+
description: 'Flag description',
|
|
435
|
+
},
|
|
436
|
+
// Type
|
|
437
|
+
type: {
|
|
438
|
+
type: 'string',
|
|
439
|
+
description: 'Flag type: boolean, string, number, json',
|
|
440
|
+
examples: ['boolean', 'string', 'number', 'json'],
|
|
441
|
+
},
|
|
442
|
+
defaultValue: {
|
|
443
|
+
type: 'json',
|
|
444
|
+
description: 'Default value when flag is off',
|
|
445
|
+
},
|
|
446
|
+
// Status
|
|
447
|
+
enabled: {
|
|
448
|
+
type: 'boolean',
|
|
449
|
+
description: 'Whether flag is enabled',
|
|
450
|
+
},
|
|
451
|
+
archived: {
|
|
452
|
+
type: 'boolean',
|
|
453
|
+
optional: true,
|
|
454
|
+
description: 'Whether flag is archived',
|
|
455
|
+
},
|
|
456
|
+
// Targeting
|
|
457
|
+
rules: {
|
|
458
|
+
type: 'json',
|
|
459
|
+
optional: true,
|
|
460
|
+
description: 'Targeting rules',
|
|
461
|
+
},
|
|
462
|
+
percentRollout: {
|
|
463
|
+
type: 'number',
|
|
464
|
+
optional: true,
|
|
465
|
+
description: 'Percentage of users to enable',
|
|
466
|
+
},
|
|
467
|
+
userTargets: {
|
|
468
|
+
type: 'string',
|
|
469
|
+
array: true,
|
|
470
|
+
optional: true,
|
|
471
|
+
description: 'Specific user IDs to target',
|
|
472
|
+
},
|
|
473
|
+
segmentTargets: {
|
|
474
|
+
type: 'string',
|
|
475
|
+
array: true,
|
|
476
|
+
optional: true,
|
|
477
|
+
description: 'Segments to target',
|
|
478
|
+
},
|
|
479
|
+
// Variants
|
|
480
|
+
variants: {
|
|
481
|
+
type: 'json',
|
|
482
|
+
optional: true,
|
|
483
|
+
description: 'Flag variants for multivariate flags',
|
|
484
|
+
},
|
|
485
|
+
// Environment
|
|
486
|
+
environments: {
|
|
487
|
+
type: 'json',
|
|
488
|
+
optional: true,
|
|
489
|
+
description: 'Per-environment settings',
|
|
490
|
+
},
|
|
491
|
+
// Tags
|
|
492
|
+
tags: {
|
|
493
|
+
type: 'string',
|
|
494
|
+
array: true,
|
|
495
|
+
optional: true,
|
|
496
|
+
description: 'Tags for organization',
|
|
497
|
+
},
|
|
498
|
+
},
|
|
499
|
+
relationships: {
|
|
500
|
+
experiments: {
|
|
501
|
+
type: 'Experiment[]',
|
|
502
|
+
description: 'Experiments using this flag',
|
|
503
|
+
},
|
|
504
|
+
segments: {
|
|
505
|
+
type: 'Segment[]',
|
|
506
|
+
description: 'Segments targeted by this flag',
|
|
507
|
+
},
|
|
508
|
+
},
|
|
509
|
+
actions: [
|
|
510
|
+
'create',
|
|
511
|
+
'update',
|
|
512
|
+
'delete',
|
|
513
|
+
'enable',
|
|
514
|
+
'disable',
|
|
515
|
+
'archive',
|
|
516
|
+
'unarchive',
|
|
517
|
+
'setRollout',
|
|
518
|
+
'addRule',
|
|
519
|
+
'removeRule',
|
|
520
|
+
'addUserTarget',
|
|
521
|
+
'removeUserTarget',
|
|
522
|
+
'addVariant',
|
|
523
|
+
'removeVariant',
|
|
524
|
+
],
|
|
525
|
+
events: [
|
|
526
|
+
'created',
|
|
527
|
+
'updated',
|
|
528
|
+
'deleted',
|
|
529
|
+
'enabled',
|
|
530
|
+
'disabled',
|
|
531
|
+
'archived',
|
|
532
|
+
'unarchived',
|
|
533
|
+
'rolloutChanged',
|
|
534
|
+
'ruleAdded',
|
|
535
|
+
'ruleRemoved',
|
|
536
|
+
'evaluated',
|
|
537
|
+
],
|
|
538
|
+
};
|
|
539
|
+
// =============================================================================
|
|
540
|
+
// Experiment
|
|
541
|
+
// =============================================================================
|
|
542
|
+
/**
|
|
543
|
+
* Experiment entity
|
|
544
|
+
*
|
|
545
|
+
* Represents an A/B test or experiment
|
|
546
|
+
*/
|
|
547
|
+
export const Experiment = {
|
|
548
|
+
singular: 'experiment',
|
|
549
|
+
plural: 'experiments',
|
|
550
|
+
description: 'An A/B test or experiment',
|
|
551
|
+
properties: {
|
|
552
|
+
// Identity
|
|
553
|
+
key: {
|
|
554
|
+
type: 'string',
|
|
555
|
+
description: 'Experiment key',
|
|
556
|
+
},
|
|
557
|
+
name: {
|
|
558
|
+
type: 'string',
|
|
559
|
+
description: 'Experiment name',
|
|
560
|
+
},
|
|
561
|
+
description: {
|
|
562
|
+
type: 'string',
|
|
563
|
+
optional: true,
|
|
564
|
+
description: 'Experiment description',
|
|
565
|
+
},
|
|
566
|
+
hypothesis: {
|
|
567
|
+
type: 'string',
|
|
568
|
+
optional: true,
|
|
569
|
+
description: 'Experiment hypothesis',
|
|
570
|
+
},
|
|
571
|
+
// Type
|
|
572
|
+
type: {
|
|
573
|
+
type: 'string',
|
|
574
|
+
description: 'Experiment type: ab, multivariate, holdout',
|
|
575
|
+
examples: ['ab', 'multivariate', 'holdout'],
|
|
576
|
+
},
|
|
577
|
+
// Status
|
|
578
|
+
status: {
|
|
579
|
+
type: 'string',
|
|
580
|
+
description: 'Experiment status: draft, running, paused, completed, archived',
|
|
581
|
+
examples: ['draft', 'running', 'paused', 'completed', 'archived'],
|
|
582
|
+
},
|
|
583
|
+
// Timing
|
|
584
|
+
startedAt: {
|
|
585
|
+
type: 'datetime',
|
|
586
|
+
optional: true,
|
|
587
|
+
description: 'Experiment start date',
|
|
588
|
+
},
|
|
589
|
+
endedAt: {
|
|
590
|
+
type: 'datetime',
|
|
591
|
+
optional: true,
|
|
592
|
+
description: 'Experiment end date',
|
|
593
|
+
},
|
|
594
|
+
scheduledStart: {
|
|
595
|
+
type: 'datetime',
|
|
596
|
+
optional: true,
|
|
597
|
+
description: 'Scheduled start date',
|
|
598
|
+
},
|
|
599
|
+
scheduledEnd: {
|
|
600
|
+
type: 'datetime',
|
|
601
|
+
optional: true,
|
|
602
|
+
description: 'Scheduled end date',
|
|
603
|
+
},
|
|
604
|
+
// Variants
|
|
605
|
+
variants: {
|
|
606
|
+
type: 'json',
|
|
607
|
+
description: 'Experiment variants with traffic allocation',
|
|
608
|
+
},
|
|
609
|
+
controlVariant: {
|
|
610
|
+
type: 'string',
|
|
611
|
+
optional: true,
|
|
612
|
+
description: 'Control variant key',
|
|
613
|
+
},
|
|
614
|
+
// Targeting
|
|
615
|
+
trafficAllocation: {
|
|
616
|
+
type: 'number',
|
|
617
|
+
optional: true,
|
|
618
|
+
description: 'Percentage of traffic in experiment',
|
|
619
|
+
},
|
|
620
|
+
targetingRules: {
|
|
621
|
+
type: 'json',
|
|
622
|
+
optional: true,
|
|
623
|
+
description: 'Targeting rules',
|
|
624
|
+
},
|
|
625
|
+
// Goals
|
|
626
|
+
primaryMetric: {
|
|
627
|
+
type: 'string',
|
|
628
|
+
optional: true,
|
|
629
|
+
description: 'Primary success metric',
|
|
630
|
+
},
|
|
631
|
+
secondaryMetrics: {
|
|
632
|
+
type: 'string',
|
|
633
|
+
array: true,
|
|
634
|
+
optional: true,
|
|
635
|
+
description: 'Secondary metrics to track',
|
|
636
|
+
},
|
|
637
|
+
minimumDetectableEffect: {
|
|
638
|
+
type: 'number',
|
|
639
|
+
optional: true,
|
|
640
|
+
description: 'Minimum detectable effect size',
|
|
641
|
+
},
|
|
642
|
+
// Results
|
|
643
|
+
sampleSize: {
|
|
644
|
+
type: 'number',
|
|
645
|
+
optional: true,
|
|
646
|
+
description: 'Required sample size',
|
|
647
|
+
},
|
|
648
|
+
currentSampleSize: {
|
|
649
|
+
type: 'number',
|
|
650
|
+
optional: true,
|
|
651
|
+
description: 'Current sample size',
|
|
652
|
+
},
|
|
653
|
+
statisticalSignificance: {
|
|
654
|
+
type: 'number',
|
|
655
|
+
optional: true,
|
|
656
|
+
description: 'Statistical significance level',
|
|
657
|
+
},
|
|
658
|
+
winningVariant: {
|
|
659
|
+
type: 'string',
|
|
660
|
+
optional: true,
|
|
661
|
+
description: 'Winning variant (if determined)',
|
|
662
|
+
},
|
|
663
|
+
lift: {
|
|
664
|
+
type: 'number',
|
|
665
|
+
optional: true,
|
|
666
|
+
description: 'Measured lift percentage',
|
|
667
|
+
},
|
|
668
|
+
pValue: {
|
|
669
|
+
type: 'number',
|
|
670
|
+
optional: true,
|
|
671
|
+
description: 'P-value',
|
|
672
|
+
},
|
|
673
|
+
confidenceInterval: {
|
|
674
|
+
type: 'json',
|
|
675
|
+
optional: true,
|
|
676
|
+
description: 'Confidence interval',
|
|
677
|
+
},
|
|
678
|
+
},
|
|
679
|
+
relationships: {
|
|
680
|
+
featureFlag: {
|
|
681
|
+
type: 'FeatureFlag',
|
|
682
|
+
required: false,
|
|
683
|
+
description: 'Associated feature flag',
|
|
684
|
+
},
|
|
685
|
+
segments: {
|
|
686
|
+
type: 'Segment[]',
|
|
687
|
+
description: 'Target segments',
|
|
688
|
+
},
|
|
689
|
+
results: {
|
|
690
|
+
type: 'ExperimentResult[]',
|
|
691
|
+
description: 'Experiment results',
|
|
692
|
+
},
|
|
693
|
+
},
|
|
694
|
+
actions: [
|
|
695
|
+
'create',
|
|
696
|
+
'update',
|
|
697
|
+
'delete',
|
|
698
|
+
'start',
|
|
699
|
+
'pause',
|
|
700
|
+
'resume',
|
|
701
|
+
'stop',
|
|
702
|
+
'archive',
|
|
703
|
+
'addVariant',
|
|
704
|
+
'removeVariant',
|
|
705
|
+
'setTraffic',
|
|
706
|
+
'declareWinner',
|
|
707
|
+
],
|
|
708
|
+
events: [
|
|
709
|
+
'created',
|
|
710
|
+
'updated',
|
|
711
|
+
'deleted',
|
|
712
|
+
'started',
|
|
713
|
+
'paused',
|
|
714
|
+
'resumed',
|
|
715
|
+
'stopped',
|
|
716
|
+
'archived',
|
|
717
|
+
'variantAdded',
|
|
718
|
+
'variantRemoved',
|
|
719
|
+
'trafficChanged',
|
|
720
|
+
'winnerDeclared',
|
|
721
|
+
'reachedSignificance',
|
|
722
|
+
],
|
|
723
|
+
};
|
|
724
|
+
/**
|
|
725
|
+
* Experiment result entity
|
|
726
|
+
*/
|
|
727
|
+
export const ExperimentResult = {
|
|
728
|
+
singular: 'experiment result',
|
|
729
|
+
plural: 'experiment results',
|
|
730
|
+
description: 'Results for an experiment variant',
|
|
731
|
+
properties: {
|
|
732
|
+
variantKey: {
|
|
733
|
+
type: 'string',
|
|
734
|
+
description: 'Variant key',
|
|
735
|
+
},
|
|
736
|
+
metricKey: {
|
|
737
|
+
type: 'string',
|
|
738
|
+
description: 'Metric key',
|
|
739
|
+
},
|
|
740
|
+
sampleSize: {
|
|
741
|
+
type: 'number',
|
|
742
|
+
description: 'Number of participants',
|
|
743
|
+
},
|
|
744
|
+
conversionRate: {
|
|
745
|
+
type: 'number',
|
|
746
|
+
optional: true,
|
|
747
|
+
description: 'Conversion rate',
|
|
748
|
+
},
|
|
749
|
+
meanValue: {
|
|
750
|
+
type: 'number',
|
|
751
|
+
optional: true,
|
|
752
|
+
description: 'Mean metric value',
|
|
753
|
+
},
|
|
754
|
+
standardDeviation: {
|
|
755
|
+
type: 'number',
|
|
756
|
+
optional: true,
|
|
757
|
+
description: 'Standard deviation',
|
|
758
|
+
},
|
|
759
|
+
lift: {
|
|
760
|
+
type: 'number',
|
|
761
|
+
optional: true,
|
|
762
|
+
description: 'Lift vs control',
|
|
763
|
+
},
|
|
764
|
+
pValue: {
|
|
765
|
+
type: 'number',
|
|
766
|
+
optional: true,
|
|
767
|
+
description: 'P-value vs control',
|
|
768
|
+
},
|
|
769
|
+
confidenceInterval: {
|
|
770
|
+
type: 'json',
|
|
771
|
+
optional: true,
|
|
772
|
+
description: 'Confidence interval',
|
|
773
|
+
},
|
|
774
|
+
isSignificant: {
|
|
775
|
+
type: 'boolean',
|
|
776
|
+
optional: true,
|
|
777
|
+
description: 'Whether result is statistically significant',
|
|
778
|
+
},
|
|
779
|
+
calculatedAt: {
|
|
780
|
+
type: 'datetime',
|
|
781
|
+
description: 'When results were calculated',
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
relationships: {
|
|
785
|
+
experiment: {
|
|
786
|
+
type: 'Experiment',
|
|
787
|
+
backref: 'results',
|
|
788
|
+
description: 'Parent experiment',
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
actions: ['calculate', 'refresh', 'export'],
|
|
792
|
+
events: ['calculated', 'refreshed'],
|
|
793
|
+
};
|
|
794
|
+
// =============================================================================
|
|
795
|
+
// Funnel
|
|
796
|
+
// =============================================================================
|
|
797
|
+
/**
|
|
798
|
+
* Funnel entity
|
|
799
|
+
*
|
|
800
|
+
* Represents a conversion funnel
|
|
801
|
+
*/
|
|
802
|
+
export const Funnel = {
|
|
803
|
+
singular: 'funnel',
|
|
804
|
+
plural: 'funnels',
|
|
805
|
+
description: 'A conversion funnel for tracking user journeys',
|
|
806
|
+
properties: {
|
|
807
|
+
// Identity
|
|
808
|
+
name: {
|
|
809
|
+
type: 'string',
|
|
810
|
+
description: 'Funnel name',
|
|
811
|
+
},
|
|
812
|
+
description: {
|
|
813
|
+
type: 'string',
|
|
814
|
+
optional: true,
|
|
815
|
+
description: 'Funnel description',
|
|
816
|
+
},
|
|
817
|
+
// Steps
|
|
818
|
+
steps: {
|
|
819
|
+
type: 'json',
|
|
820
|
+
description: 'Funnel steps (event definitions)',
|
|
821
|
+
},
|
|
822
|
+
stepCount: {
|
|
823
|
+
type: 'number',
|
|
824
|
+
optional: true,
|
|
825
|
+
description: 'Number of steps',
|
|
826
|
+
},
|
|
827
|
+
// Configuration
|
|
828
|
+
conversionWindow: {
|
|
829
|
+
type: 'number',
|
|
830
|
+
optional: true,
|
|
831
|
+
description: 'Conversion window in days',
|
|
832
|
+
},
|
|
833
|
+
strict: {
|
|
834
|
+
type: 'boolean',
|
|
835
|
+
optional: true,
|
|
836
|
+
description: 'Whether order must be strictly followed',
|
|
837
|
+
},
|
|
838
|
+
// Metrics
|
|
839
|
+
totalEntered: {
|
|
840
|
+
type: 'number',
|
|
841
|
+
optional: true,
|
|
842
|
+
description: 'Total users who entered funnel',
|
|
843
|
+
},
|
|
844
|
+
totalConverted: {
|
|
845
|
+
type: 'number',
|
|
846
|
+
optional: true,
|
|
847
|
+
description: 'Total users who completed funnel',
|
|
848
|
+
},
|
|
849
|
+
overallConversionRate: {
|
|
850
|
+
type: 'number',
|
|
851
|
+
optional: true,
|
|
852
|
+
description: 'Overall conversion rate',
|
|
853
|
+
},
|
|
854
|
+
avgTimeToConvert: {
|
|
855
|
+
type: 'number',
|
|
856
|
+
optional: true,
|
|
857
|
+
description: 'Average time to convert in hours',
|
|
858
|
+
},
|
|
859
|
+
},
|
|
860
|
+
relationships: {
|
|
861
|
+
stepResults: {
|
|
862
|
+
type: 'FunnelStep[]',
|
|
863
|
+
description: 'Step-by-step results',
|
|
864
|
+
},
|
|
865
|
+
},
|
|
866
|
+
actions: ['create', 'update', 'delete', 'calculate', 'compare', 'export'],
|
|
867
|
+
events: ['created', 'updated', 'deleted', 'calculated'],
|
|
868
|
+
};
|
|
869
|
+
/**
|
|
870
|
+
* Funnel step entity
|
|
871
|
+
*/
|
|
872
|
+
export const FunnelStep = {
|
|
873
|
+
singular: 'funnel step',
|
|
874
|
+
plural: 'funnel steps',
|
|
875
|
+
description: 'A step in a conversion funnel',
|
|
876
|
+
properties: {
|
|
877
|
+
stepNumber: {
|
|
878
|
+
type: 'number',
|
|
879
|
+
description: 'Step number (1-indexed)',
|
|
880
|
+
},
|
|
881
|
+
name: {
|
|
882
|
+
type: 'string',
|
|
883
|
+
description: 'Step name',
|
|
884
|
+
},
|
|
885
|
+
eventName: {
|
|
886
|
+
type: 'string',
|
|
887
|
+
description: 'Event that triggers this step',
|
|
888
|
+
},
|
|
889
|
+
entered: {
|
|
890
|
+
type: 'number',
|
|
891
|
+
optional: true,
|
|
892
|
+
description: 'Users who entered this step',
|
|
893
|
+
},
|
|
894
|
+
completed: {
|
|
895
|
+
type: 'number',
|
|
896
|
+
optional: true,
|
|
897
|
+
description: 'Users who completed this step',
|
|
898
|
+
},
|
|
899
|
+
droppedOff: {
|
|
900
|
+
type: 'number',
|
|
901
|
+
optional: true,
|
|
902
|
+
description: 'Users who dropped off',
|
|
903
|
+
},
|
|
904
|
+
conversionRate: {
|
|
905
|
+
type: 'number',
|
|
906
|
+
optional: true,
|
|
907
|
+
description: 'Conversion rate from previous step',
|
|
908
|
+
},
|
|
909
|
+
avgTimeInStep: {
|
|
910
|
+
type: 'number',
|
|
911
|
+
optional: true,
|
|
912
|
+
description: 'Average time in step in seconds',
|
|
913
|
+
},
|
|
914
|
+
},
|
|
915
|
+
relationships: {
|
|
916
|
+
funnel: {
|
|
917
|
+
type: 'Funnel',
|
|
918
|
+
backref: 'stepResults',
|
|
919
|
+
description: 'Parent funnel',
|
|
920
|
+
},
|
|
921
|
+
},
|
|
922
|
+
actions: ['view'],
|
|
923
|
+
events: ['entered', 'completed', 'droppedOff'],
|
|
924
|
+
};
|
|
925
|
+
// =============================================================================
|
|
926
|
+
// Cohort
|
|
927
|
+
// =============================================================================
|
|
928
|
+
/**
|
|
929
|
+
* Cohort entity
|
|
930
|
+
*
|
|
931
|
+
* Represents a user cohort for retention analysis
|
|
932
|
+
*/
|
|
933
|
+
export const Cohort = {
|
|
934
|
+
singular: 'cohort',
|
|
935
|
+
plural: 'cohorts',
|
|
936
|
+
description: 'A user cohort for retention analysis',
|
|
937
|
+
properties: {
|
|
938
|
+
// Identity
|
|
939
|
+
name: {
|
|
940
|
+
type: 'string',
|
|
941
|
+
description: 'Cohort name',
|
|
942
|
+
},
|
|
943
|
+
description: {
|
|
944
|
+
type: 'string',
|
|
945
|
+
optional: true,
|
|
946
|
+
description: 'Cohort description',
|
|
947
|
+
},
|
|
948
|
+
// Definition
|
|
949
|
+
cohortType: {
|
|
950
|
+
type: 'string',
|
|
951
|
+
description: 'Cohort type: acquisition, behavioral, custom',
|
|
952
|
+
examples: ['acquisition', 'behavioral', 'custom'],
|
|
953
|
+
},
|
|
954
|
+
startEvent: {
|
|
955
|
+
type: 'string',
|
|
956
|
+
description: 'Event that defines cohort entry',
|
|
957
|
+
},
|
|
958
|
+
returnEvent: {
|
|
959
|
+
type: 'string',
|
|
960
|
+
optional: true,
|
|
961
|
+
description: 'Event that defines retention',
|
|
962
|
+
},
|
|
963
|
+
// Time period
|
|
964
|
+
period: {
|
|
965
|
+
type: 'string',
|
|
966
|
+
description: 'Cohort period: day, week, month',
|
|
967
|
+
examples: ['day', 'week', 'month'],
|
|
968
|
+
},
|
|
969
|
+
startDate: {
|
|
970
|
+
type: 'datetime',
|
|
971
|
+
optional: true,
|
|
972
|
+
description: 'Cohort start date',
|
|
973
|
+
},
|
|
974
|
+
endDate: {
|
|
975
|
+
type: 'datetime',
|
|
976
|
+
optional: true,
|
|
977
|
+
description: 'Cohort end date',
|
|
978
|
+
},
|
|
979
|
+
// Size
|
|
980
|
+
userCount: {
|
|
981
|
+
type: 'number',
|
|
982
|
+
optional: true,
|
|
983
|
+
description: 'Number of users in cohort',
|
|
984
|
+
},
|
|
985
|
+
// Retention
|
|
986
|
+
retentionData: {
|
|
987
|
+
type: 'json',
|
|
988
|
+
optional: true,
|
|
989
|
+
description: 'Retention curve data',
|
|
990
|
+
},
|
|
991
|
+
avgRetention: {
|
|
992
|
+
type: 'number',
|
|
993
|
+
optional: true,
|
|
994
|
+
description: 'Average retention rate',
|
|
995
|
+
},
|
|
996
|
+
},
|
|
997
|
+
relationships: {
|
|
998
|
+
users: {
|
|
999
|
+
type: 'Contact[]',
|
|
1000
|
+
description: 'Users in this cohort',
|
|
1001
|
+
},
|
|
1002
|
+
},
|
|
1003
|
+
actions: ['create', 'update', 'delete', 'calculate', 'compare', 'export'],
|
|
1004
|
+
events: ['created', 'updated', 'deleted', 'calculated'],
|
|
1005
|
+
};
|
|
1006
|
+
// =============================================================================
|
|
1007
|
+
// Export all entities as a schema
|
|
1008
|
+
// =============================================================================
|
|
1009
|
+
/**
|
|
1010
|
+
* All experiment entity types
|
|
1011
|
+
*/
|
|
1012
|
+
export const ExperimentEntities = {
|
|
1013
|
+
// Sessions & Events
|
|
1014
|
+
Session,
|
|
1015
|
+
AnalyticsEvent,
|
|
1016
|
+
Pageview,
|
|
1017
|
+
// Segmentation
|
|
1018
|
+
Segment,
|
|
1019
|
+
// Feature Flags
|
|
1020
|
+
FeatureFlag,
|
|
1021
|
+
// Experimentation
|
|
1022
|
+
Experiment,
|
|
1023
|
+
ExperimentResult,
|
|
1024
|
+
// Funnels
|
|
1025
|
+
Funnel,
|
|
1026
|
+
FunnelStep,
|
|
1027
|
+
// Cohorts
|
|
1028
|
+
Cohort,
|
|
1029
|
+
};
|
|
1030
|
+
/**
|
|
1031
|
+
* Entity categories for organization
|
|
1032
|
+
*/
|
|
1033
|
+
export const ExperimentCategories = {
|
|
1034
|
+
tracking: ['Session', 'AnalyticsEvent', 'Pageview'],
|
|
1035
|
+
segmentation: ['Segment', 'Cohort'],
|
|
1036
|
+
featureFlags: ['FeatureFlag'],
|
|
1037
|
+
experimentation: ['Experiment', 'ExperimentResult'],
|
|
1038
|
+
funnels: ['Funnel', 'FunnelStep'],
|
|
1039
|
+
};
|