@od-oneapp/analytics 2026.1.1301
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/README.md +509 -0
- package/dist/ai-YMnynb-t.mjs +3347 -0
- package/dist/ai-YMnynb-t.mjs.map +1 -0
- package/dist/chunk-DQk6qfdC.mjs +18 -0
- package/dist/client-CTzJVFU5.mjs +9 -0
- package/dist/client-CTzJVFU5.mjs.map +1 -0
- package/dist/client-CcFTauAh.mjs +54 -0
- package/dist/client-CcFTauAh.mjs.map +1 -0
- package/dist/client-CeOLjbac.mjs +281 -0
- package/dist/client-CeOLjbac.mjs.map +1 -0
- package/dist/client-D339NFJS.mjs +267 -0
- package/dist/client-D339NFJS.mjs.map +1 -0
- package/dist/client-next.d.mts +62 -0
- package/dist/client-next.d.mts.map +1 -0
- package/dist/client-next.mjs +525 -0
- package/dist/client-next.mjs.map +1 -0
- package/dist/client.d.mts +30 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +186 -0
- package/dist/client.mjs.map +1 -0
- package/dist/config-DPS6bSYo.d.mts +34 -0
- package/dist/config-DPS6bSYo.d.mts.map +1 -0
- package/dist/config-P6P5adJg.mjs +287 -0
- package/dist/config-P6P5adJg.mjs.map +1 -0
- package/dist/console-8bND3mMU.mjs +128 -0
- package/dist/console-8bND3mMU.mjs.map +1 -0
- package/dist/ecommerce-Cgu4wlux.mjs +993 -0
- package/dist/ecommerce-Cgu4wlux.mjs.map +1 -0
- package/dist/emitters-6-nKo8i-.mjs +208 -0
- package/dist/emitters-6-nKo8i-.mjs.map +1 -0
- package/dist/emitters-DldkVSPp.d.mts +12 -0
- package/dist/emitters-DldkVSPp.d.mts.map +1 -0
- package/dist/index-BfNWgfa5.d.mts +1494 -0
- package/dist/index-BfNWgfa5.d.mts.map +1 -0
- package/dist/index-BkIWe--N.d.mts +953 -0
- package/dist/index-BkIWe--N.d.mts.map +1 -0
- package/dist/index-jPzXRn52.d.mts +184 -0
- package/dist/index-jPzXRn52.d.mts.map +1 -0
- package/dist/manager-DvRRjza6.d.mts +76 -0
- package/dist/manager-DvRRjza6.d.mts.map +1 -0
- package/dist/posthog-bootstrap-CYfIy_WS.mjs +1769 -0
- package/dist/posthog-bootstrap-CYfIy_WS.mjs.map +1 -0
- package/dist/posthog-bootstrap-DWxFrxlt.d.mts +81 -0
- package/dist/posthog-bootstrap-DWxFrxlt.d.mts.map +1 -0
- package/dist/providers-http-client.d.mts +37 -0
- package/dist/providers-http-client.d.mts.map +1 -0
- package/dist/providers-http-client.mjs +320 -0
- package/dist/providers-http-client.mjs.map +1 -0
- package/dist/providers-http-server.d.mts +31 -0
- package/dist/providers-http-server.d.mts.map +1 -0
- package/dist/providers-http-server.mjs +297 -0
- package/dist/providers-http-server.mjs.map +1 -0
- package/dist/providers-http.d.mts +46 -0
- package/dist/providers-http.d.mts.map +1 -0
- package/dist/providers-http.mjs +4 -0
- package/dist/server-edge.d.mts +9 -0
- package/dist/server-edge.d.mts.map +1 -0
- package/dist/server-edge.mjs +373 -0
- package/dist/server-edge.mjs.map +1 -0
- package/dist/server-next.d.mts +67 -0
- package/dist/server-next.d.mts.map +1 -0
- package/dist/server-next.mjs +193 -0
- package/dist/server-next.mjs.map +1 -0
- package/dist/server.d.mts +10 -0
- package/dist/server.mjs +7 -0
- package/dist/service-cYtBBL8x.mjs +945 -0
- package/dist/service-cYtBBL8x.mjs.map +1 -0
- package/dist/shared.d.mts +16 -0
- package/dist/shared.d.mts.map +1 -0
- package/dist/shared.mjs +93 -0
- package/dist/shared.mjs.map +1 -0
- package/dist/types-BxBnNQ0V.d.mts +354 -0
- package/dist/types-BxBnNQ0V.d.mts.map +1 -0
- package/dist/types-CBvxUEaF.d.mts +216 -0
- package/dist/types-CBvxUEaF.d.mts.map +1 -0
- package/dist/types.d.mts +4 -0
- package/dist/types.mjs +0 -0
- package/dist/vercel-types-lwakUfoI.d.mts +102 -0
- package/dist/vercel-types-lwakUfoI.d.mts.map +1 -0
- package/package.json +129 -0
- package/src/client/index.ts +164 -0
- package/src/client/manager.ts +71 -0
- package/src/client/next/components.tsx +270 -0
- package/src/client/next/hooks.ts +217 -0
- package/src/client/next/manager.ts +141 -0
- package/src/client/next.ts +144 -0
- package/src/client-next.ts +101 -0
- package/src/client.ts +89 -0
- package/src/examples/ai-sdk-patterns.ts +583 -0
- package/src/examples/emitter-patterns.ts +476 -0
- package/src/examples/nextjs-emitter-patterns.tsx +403 -0
- package/src/next/app-router.tsx +564 -0
- package/src/next/client.ts +419 -0
- package/src/next/index.ts +84 -0
- package/src/next/middleware.ts +429 -0
- package/src/next/rsc.tsx +300 -0
- package/src/next/server.ts +253 -0
- package/src/next/types.d.ts +220 -0
- package/src/providers/base-provider.ts +419 -0
- package/src/providers/console/client.ts +10 -0
- package/src/providers/console/index.ts +152 -0
- package/src/providers/console/server.ts +6 -0
- package/src/providers/console/types.ts +15 -0
- package/src/providers/http/client.ts +464 -0
- package/src/providers/http/index.ts +30 -0
- package/src/providers/http/server.ts +396 -0
- package/src/providers/http/types.ts +135 -0
- package/src/providers/posthog/client.ts +518 -0
- package/src/providers/posthog/index.ts +11 -0
- package/src/providers/posthog/server.ts +329 -0
- package/src/providers/posthog/types.ts +104 -0
- package/src/providers/segment/client.ts +113 -0
- package/src/providers/segment/index.ts +11 -0
- package/src/providers/segment/server.ts +115 -0
- package/src/providers/segment/types.ts +51 -0
- package/src/providers/vercel/client.ts +102 -0
- package/src/providers/vercel/index.ts +11 -0
- package/src/providers/vercel/server.ts +89 -0
- package/src/providers/vercel/types.ts +27 -0
- package/src/server/index.ts +103 -0
- package/src/server/manager.ts +62 -0
- package/src/server/next.ts +210 -0
- package/src/server-edge.ts +442 -0
- package/src/server-next.ts +39 -0
- package/src/server.ts +106 -0
- package/src/shared/emitters/ai/README.md +981 -0
- package/src/shared/emitters/ai/events/agent.ts +130 -0
- package/src/shared/emitters/ai/events/artifacts.ts +167 -0
- package/src/shared/emitters/ai/events/chat.ts +126 -0
- package/src/shared/emitters/ai/events/chatbot-ecommerce.ts +133 -0
- package/src/shared/emitters/ai/events/completion.ts +103 -0
- package/src/shared/emitters/ai/events/content-generation.ts +347 -0
- package/src/shared/emitters/ai/events/conversation.ts +332 -0
- package/src/shared/emitters/ai/events/product-features.ts +1402 -0
- package/src/shared/emitters/ai/events/streaming.ts +114 -0
- package/src/shared/emitters/ai/events/tool.ts +93 -0
- package/src/shared/emitters/ai/index.ts +69 -0
- package/src/shared/emitters/ai/track-ai-sdk.ts +74 -0
- package/src/shared/emitters/ai/track-ai.ts +50 -0
- package/src/shared/emitters/ai/types.ts +1041 -0
- package/src/shared/emitters/ai/utils.ts +468 -0
- package/src/shared/emitters/ecommerce/events/cart-checkout.ts +106 -0
- package/src/shared/emitters/ecommerce/events/coupon.ts +49 -0
- package/src/shared/emitters/ecommerce/events/engagement.ts +61 -0
- package/src/shared/emitters/ecommerce/events/marketplace.ts +119 -0
- package/src/shared/emitters/ecommerce/events/order.ts +199 -0
- package/src/shared/emitters/ecommerce/events/product.ts +205 -0
- package/src/shared/emitters/ecommerce/events/registry.ts +123 -0
- package/src/shared/emitters/ecommerce/events/wishlist-sharing.ts +140 -0
- package/src/shared/emitters/ecommerce/index.ts +46 -0
- package/src/shared/emitters/ecommerce/track-ecommerce.ts +53 -0
- package/src/shared/emitters/ecommerce/types.ts +314 -0
- package/src/shared/emitters/ecommerce/utils.ts +216 -0
- package/src/shared/emitters/emitter-types.ts +974 -0
- package/src/shared/emitters/emitters.ts +292 -0
- package/src/shared/emitters/helpers.ts +419 -0
- package/src/shared/emitters/index.ts +66 -0
- package/src/shared/index.ts +142 -0
- package/src/shared/ingestion/index.ts +66 -0
- package/src/shared/ingestion/schemas.ts +386 -0
- package/src/shared/ingestion/service.ts +628 -0
- package/src/shared/node22-features.ts +848 -0
- package/src/shared/providers/console-provider.ts +160 -0
- package/src/shared/types/base-types.ts +54 -0
- package/src/shared/types/console-types.ts +19 -0
- package/src/shared/types/posthog-types.ts +131 -0
- package/src/shared/types/segment-types.ts +15 -0
- package/src/shared/types/types.ts +397 -0
- package/src/shared/types/vercel-types.ts +19 -0
- package/src/shared/utils/config-client.ts +19 -0
- package/src/shared/utils/config.ts +250 -0
- package/src/shared/utils/emitter-adapter.ts +212 -0
- package/src/shared/utils/manager.test.ts +36 -0
- package/src/shared/utils/manager.ts +1322 -0
- package/src/shared/utils/posthog-bootstrap.ts +136 -0
- package/src/shared/utils/posthog-client-utils.ts +48 -0
- package/src/shared/utils/posthog-next-utils.ts +282 -0
- package/src/shared/utils/posthog-server-utils.ts +210 -0
- package/src/shared/utils/rate-limit.ts +289 -0
- package/src/shared/utils/security.ts +545 -0
- package/src/shared/utils/validation-client.ts +161 -0
- package/src/shared/utils/validation.ts +399 -0
- package/src/shared.ts +155 -0
- package/src/types/index.ts +62 -0
package/README.md
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
# @repo/analytics
|
|
2
|
+
|
|
3
|
+
> **Multi-provider analytics package with type-safe event tracking, comprehensive ecommerce support, and AI product
|
|
4
|
+
> analytics**
|
|
5
|
+
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://nodejs.org/)
|
|
8
|
+
|
|
9
|
+
## Quick Reference
|
|
10
|
+
|
|
11
|
+
**Status:** Development (Tests passing: 634/655, TypeCheck: ✅)
|
|
12
|
+
|
|
13
|
+
**Requirements:**
|
|
14
|
+
|
|
15
|
+
- Node.js 22.0.0+ (uses Node 22+ features: `structuredClone`, `AbortSignal.timeout`, bigint timing)
|
|
16
|
+
- pnpm 10.0.0+
|
|
17
|
+
- Next.js 15.0.0+ (if using Next.js integration)
|
|
18
|
+
|
|
19
|
+
**Exports:**
|
|
20
|
+
|
|
21
|
+
- **Core**: `./client`, `./server`, `./shared`, `./types`
|
|
22
|
+
- **Next.js**: `./client/next`, `./server/next`, `./server/edge`
|
|
23
|
+
|
|
24
|
+
**Key Features:**
|
|
25
|
+
|
|
26
|
+
- ✅ Multi-Provider (PostHog, Vercel Analytics, Segment, Console)
|
|
27
|
+
- ✅ Type-Safe Emitters (Segment.io specification)
|
|
28
|
+
- ✅ Universal (client/server/edge environments)
|
|
29
|
+
- ✅ E-commerce (50+ standardized events)
|
|
30
|
+
- ✅ AI Product Tracking (90+ ChatGPT/Claude-style events)
|
|
31
|
+
- ✅ Feature Flags (PostHog integration)
|
|
32
|
+
- ✅ Next.js 15 (App Router, Server Components, hooks)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
### Prerequisites
|
|
39
|
+
|
|
40
|
+
⚠️ **Required:** Node.js 22+ (package uses `structuredClone`, `AbortSignal.timeout`, `process.hrtime.bigint`)
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Check Node version
|
|
44
|
+
node --version # Must be v22.0.0 or higher
|
|
45
|
+
|
|
46
|
+
# Install package
|
|
47
|
+
pnpm add @repo/analytics --filter=your-app
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Install Providers (Peer Dependencies)
|
|
51
|
+
|
|
52
|
+
Install only the providers you need:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# PostHog (recommended - analytics + feature flags)
|
|
56
|
+
pnpm add posthog-js posthog-node --filter=your-app
|
|
57
|
+
|
|
58
|
+
# Vercel Analytics
|
|
59
|
+
pnpm add @vercel/analytics --filter=your-app
|
|
60
|
+
|
|
61
|
+
# Segment
|
|
62
|
+
pnpm add @segment/analytics-next --filter=your-app
|
|
63
|
+
|
|
64
|
+
# Console (built-in, no installation needed)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
### Environment Variables
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# .env.local
|
|
75
|
+
|
|
76
|
+
# PostHog (Primary)
|
|
77
|
+
NEXT_PUBLIC_POSTHOG_KEY=phc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
78
|
+
NEXT_PUBLIC_POSTHOG_HOST=https://app.posthog.com
|
|
79
|
+
|
|
80
|
+
# Vercel Analytics (Optional)
|
|
81
|
+
VERCEL_ANALYTICS_ID=your-analytics-id
|
|
82
|
+
|
|
83
|
+
# Segment (Optional)
|
|
84
|
+
NEXT_PUBLIC_SEGMENT_WRITE_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
85
|
+
|
|
86
|
+
# Development
|
|
87
|
+
NEXT_PUBLIC_CONSOLE_ANALYTICS=true
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Next.js Setup
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
// app/providers.tsx
|
|
94
|
+
"use client";
|
|
95
|
+
|
|
96
|
+
import { AnalyticsProvider } from "@repo/analytics/client/next";
|
|
97
|
+
|
|
98
|
+
export function Providers({ children }: { children: React.ReactNode }) {
|
|
99
|
+
return (
|
|
100
|
+
<AnalyticsProvider
|
|
101
|
+
config={{
|
|
102
|
+
providers: {
|
|
103
|
+
posthog: {
|
|
104
|
+
apiKey: process.env.NEXT_PUBLIC_POSTHOG_KEY!,
|
|
105
|
+
options: {
|
|
106
|
+
debug: process.env.NODE_ENV === "development",
|
|
107
|
+
capture_pageview: false
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
console: {
|
|
111
|
+
enabled: process.env.NODE_ENV === "development"
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
debug: process.env.NODE_ENV === "development"
|
|
115
|
+
}}
|
|
116
|
+
>
|
|
117
|
+
{children}
|
|
118
|
+
</AnalyticsProvider>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Usage Examples
|
|
124
|
+
|
|
125
|
+
#### Client Component
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
"use client";
|
|
129
|
+
|
|
130
|
+
import { useAnalytics, track } from "@repo/analytics/client/next";
|
|
131
|
+
|
|
132
|
+
export function SignupButton() {
|
|
133
|
+
const analytics = useAnalytics();
|
|
134
|
+
|
|
135
|
+
const handleClick = async () => {
|
|
136
|
+
// Method 1: Direct tracking
|
|
137
|
+
await analytics.track("Button Clicked", { button_name: "signup" });
|
|
138
|
+
|
|
139
|
+
// Method 2: Emitter pattern (recommended)
|
|
140
|
+
const event = track("CTA Clicked", { cta_type: "signup" });
|
|
141
|
+
await analytics.emit(event);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
return <button onClick={handleClick}>Sign Up</button>;
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
#### Server Component / API Route
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
// app/api/checkout/route.ts
|
|
152
|
+
import { createServerAnalytics, ecommerce } from "@repo/analytics/server/next";
|
|
153
|
+
|
|
154
|
+
export async function POST(request: Request) {
|
|
155
|
+
const analytics = await createServerAnalytics({
|
|
156
|
+
providers: {
|
|
157
|
+
posthog: { apiKey: process.env.POSTHOG_API_KEY! }
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
await analytics.emit(
|
|
162
|
+
ecommerce.CHECKOUT_STARTED({
|
|
163
|
+
order_id: "order_123",
|
|
164
|
+
value: 299.99,
|
|
165
|
+
currency: "USD",
|
|
166
|
+
products: [{ product_id: "prod_abc", price: 299.99, quantity: 1 }]
|
|
167
|
+
})
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
return Response.json({ success: true });
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### E-commerce Events
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { ecommerce } from "@repo/analytics/client/next";
|
|
178
|
+
|
|
179
|
+
// Product viewed
|
|
180
|
+
ecommerce.PRODUCT_VIEWED({
|
|
181
|
+
product_id: "prod_123",
|
|
182
|
+
name: "Premium Plan",
|
|
183
|
+
price: 299.99,
|
|
184
|
+
currency: "USD"
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Product added to cart
|
|
188
|
+
ecommerce.PRODUCT_ADDED({
|
|
189
|
+
cart_id: "cart_abc",
|
|
190
|
+
product_id: "prod_123",
|
|
191
|
+
quantity: 1,
|
|
192
|
+
price: 299.99
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// Order completed
|
|
196
|
+
ecommerce.ORDER_COMPLETED({
|
|
197
|
+
order_id: "order_789",
|
|
198
|
+
revenue: 499.97,
|
|
199
|
+
currency: "USD",
|
|
200
|
+
products: [
|
|
201
|
+
/* ... */
|
|
202
|
+
],
|
|
203
|
+
payment_method: "card"
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### AI Product Events
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { ai } from "@repo/analytics/client/next";
|
|
211
|
+
|
|
212
|
+
// Chat message sent
|
|
213
|
+
ai.CHAT_MESSAGE_SENT({
|
|
214
|
+
conversation_id: "conv_123",
|
|
215
|
+
message_id: "msg_456",
|
|
216
|
+
model_id: "gpt-4",
|
|
217
|
+
message_length: 150
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Message regenerated
|
|
221
|
+
ai.MESSAGE_REGENERATED({
|
|
222
|
+
conversation_id: "conv_123",
|
|
223
|
+
model_id: "gpt-4",
|
|
224
|
+
original_message_id: "msg_456",
|
|
225
|
+
attempt_number: 2,
|
|
226
|
+
reason: "user-requested"
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Conversation branched
|
|
230
|
+
ai.CONVERSATION_BRANCHED({
|
|
231
|
+
conversation_id: "conv_123",
|
|
232
|
+
parent_conversation_id: "conv_122",
|
|
233
|
+
branch_point_message_id: "msg_450",
|
|
234
|
+
reason: "explore-alternative"
|
|
235
|
+
});
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Architecture
|
|
241
|
+
|
|
242
|
+
### Four-File Export Pattern
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
@repo/analytics
|
|
246
|
+
├── /client → Browser-only (posthog-js, @vercel/analytics client)
|
|
247
|
+
├── /server → Node.js server (posthog-node, segment server)
|
|
248
|
+
├── /client/next → Next.js client (hooks, provider, components)
|
|
249
|
+
├── /server/next → Next.js server (API routes, server components)
|
|
250
|
+
├── /server/edge → Edge runtime (middleware, edge API routes)
|
|
251
|
+
└── /shared → Environment-agnostic (emitters, types, utils)
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Import Rules:**
|
|
255
|
+
|
|
256
|
+
- ✅ Client components: `@repo/analytics/client/next`
|
|
257
|
+
- ✅ Server components/API routes: `@repo/analytics/server/next`
|
|
258
|
+
- ✅ Edge runtime: `@repo/analytics/server/edge`
|
|
259
|
+
- ❌ Never mix: Client + server imports cause build errors
|
|
260
|
+
|
|
261
|
+
**Edge Runtime Limitations:**
|
|
262
|
+
|
|
263
|
+
The `/server/edge` export provides a simplified implementation compatible with edge runtime:
|
|
264
|
+
|
|
265
|
+
- ✅ Basic tracking (track, identify, page, group, alias)
|
|
266
|
+
- ✅ Console provider (console API)
|
|
267
|
+
- ✅ PostHog provider (HTTP API, no SDK dependency)
|
|
268
|
+
- ✅ Emitter pattern support (`emit()`)
|
|
269
|
+
- ❌ No event deduplication (no LRU cache)
|
|
270
|
+
- ❌ No rate limiting enforcement
|
|
271
|
+
- ❌ No feature flags (requires Node.js SDK)
|
|
272
|
+
- ❌ No batch processing optimization
|
|
273
|
+
|
|
274
|
+
For full features, use `/server` or `/server/next` in Node.js environments.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Core API
|
|
279
|
+
|
|
280
|
+
### Analytics Manager
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// Create analytics instance
|
|
284
|
+
const analytics = await createClientAnalytics(config);
|
|
285
|
+
|
|
286
|
+
// Track events
|
|
287
|
+
await analytics.track("Event Name", { property: "value" });
|
|
288
|
+
|
|
289
|
+
// Identify users
|
|
290
|
+
await analytics.identify("user_123", { email: "user@example.com" });
|
|
291
|
+
|
|
292
|
+
// Track page views
|
|
293
|
+
await analytics.page("/pricing", { title: "Pricing Page" });
|
|
294
|
+
|
|
295
|
+
// Group/organization
|
|
296
|
+
await analytics.group("org_456", { name: "Acme Corp" });
|
|
297
|
+
|
|
298
|
+
// Emit emitter payloads
|
|
299
|
+
const event = track("Event", { data: "value" });
|
|
300
|
+
await analytics.emit(event);
|
|
301
|
+
|
|
302
|
+
// Batch processing
|
|
303
|
+
await analytics.emitBatch([event1, event2, event3], {
|
|
304
|
+
concurrency: 5,
|
|
305
|
+
failFast: false
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### React Hooks
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// Access analytics manager
|
|
313
|
+
const analytics = useAnalytics();
|
|
314
|
+
|
|
315
|
+
// Track on mount
|
|
316
|
+
useTrackEvent("Page Viewed", { page: "/dashboard" });
|
|
317
|
+
|
|
318
|
+
// Identify user on mount
|
|
319
|
+
useIdentifyUser(user.id, { email: user.email });
|
|
320
|
+
|
|
321
|
+
// Auto page tracking
|
|
322
|
+
usePageTracking();
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## Feature Flags (PostHog)
|
|
328
|
+
|
|
329
|
+
### Client-Side
|
|
330
|
+
|
|
331
|
+
```typescript
|
|
332
|
+
import { useAnalytics } from '@repo/analytics/client/next';
|
|
333
|
+
|
|
334
|
+
function FeatureFlag() {
|
|
335
|
+
const analytics = useAnalytics();
|
|
336
|
+
const provider = analytics.getProvider('posthog');
|
|
337
|
+
const [enabled, setEnabled] = useState(false);
|
|
338
|
+
|
|
339
|
+
useEffect(() => {
|
|
340
|
+
provider?.isFeatureEnabled('new-feature').then(setEnabled);
|
|
341
|
+
}, [provider]);
|
|
342
|
+
|
|
343
|
+
return enabled ? <NewFeature /> : <OldFeature />;
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Server-Side
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
// app/page.tsx
|
|
351
|
+
import { createServerAnalytics } from "@repo/analytics/server/next";
|
|
352
|
+
|
|
353
|
+
export default async function Page() {
|
|
354
|
+
const analytics = await createServerAnalytics({
|
|
355
|
+
providers: { posthog: { apiKey: process.env.POSTHOG_API_KEY! } }
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
const provider = analytics.getProvider("posthog");
|
|
359
|
+
const showFeature = await provider?.getFeatureFlag("new-feature", "user_123");
|
|
360
|
+
|
|
361
|
+
return <div>{showFeature ? <New /> : <Old />}</div>;
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
---
|
|
366
|
+
|
|
367
|
+
## Troubleshooting
|
|
368
|
+
|
|
369
|
+
### Common Issues
|
|
370
|
+
|
|
371
|
+
**"Analytics not initialized"**
|
|
372
|
+
|
|
373
|
+
- Ensure you await `createClientAnalytics()` or `createServerAnalytics()`
|
|
374
|
+
|
|
375
|
+
**"Provider not available in this environment"**
|
|
376
|
+
|
|
377
|
+
- Check you're using correct import path (client vs server vs edge)
|
|
378
|
+
|
|
379
|
+
**Events not showing in PostHog**
|
|
380
|
+
|
|
381
|
+
- Verify API key is correct
|
|
382
|
+
- Enable debug mode: `options: { debug: true }`
|
|
383
|
+
- Check network tab for failed requests
|
|
384
|
+
|
|
385
|
+
**"structuredClone is not defined"**
|
|
386
|
+
|
|
387
|
+
- Upgrade to Node.js 22+ (required)
|
|
388
|
+
|
|
389
|
+
### Debug Mode
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
const analytics = await createClientAnalytics({
|
|
393
|
+
providers: {
|
|
394
|
+
posthog: {
|
|
395
|
+
apiKey: "...",
|
|
396
|
+
options: { debug: true }
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
debug: true,
|
|
400
|
+
onInfo: (msg) => console.log("[Analytics]", msg),
|
|
401
|
+
onError: (err, ctx) => console.error("[Analytics Error]", err, ctx)
|
|
402
|
+
});
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Health Check
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
const health = await analytics.healthCheck(5000);
|
|
409
|
+
console.log("Healthy:", health.healthy);
|
|
410
|
+
console.log("Providers:", health.providers);
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
---
|
|
414
|
+
|
|
415
|
+
## Security
|
|
416
|
+
|
|
417
|
+
⚠️ **Important Security Notes:**
|
|
418
|
+
|
|
419
|
+
1. **Never track PII** - Avoid email, phone, SSN, credit cards
|
|
420
|
+
2. **Sanitize input** - Validate all properties before tracking
|
|
421
|
+
3. **Use env variables** - Never hardcode API keys
|
|
422
|
+
4. **Rotate keys** - Update API keys periodically
|
|
423
|
+
|
|
424
|
+
**Security Features (Implemented):**
|
|
425
|
+
|
|
426
|
+
- ✅ Input sanitization (`sanitizeProperties()`)
|
|
427
|
+
- ✅ PII detection and redaction (`containsPII()`, `redactPII()`)
|
|
428
|
+
- ✅ XSS protection (`stripHTML()`)
|
|
429
|
+
- ✅ Payload size limits (default: 100KB max)
|
|
430
|
+
- ✅ Dangerous key blocking (prevents `__proto__`, `constructor`)
|
|
431
|
+
- ✅ Rate limiting (token bucket algorithm, 100 calls/second default)
|
|
432
|
+
|
|
433
|
+
**Usage:**
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
import { sanitizeProperties, containsPII } from "@repo/analytics/server";
|
|
437
|
+
|
|
438
|
+
// Sanitize before tracking
|
|
439
|
+
const sanitized = sanitizeProperties(userInput, {
|
|
440
|
+
stripPII: true,
|
|
441
|
+
stripHTML: true,
|
|
442
|
+
maxPayloadSize: 50_000 // 50KB
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
// Check for PII
|
|
446
|
+
if (containsPII(JSON.stringify(properties))) {
|
|
447
|
+
console.warn("PII detected in analytics payload");
|
|
448
|
+
}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
453
|
+
## Documentation
|
|
454
|
+
|
|
455
|
+
- **Full Documentation**: [Analytics Package Docs](../../apps/docs/packages/analytics.mdx)
|
|
456
|
+
- **Audit Findings**: [AUDIT_FINDINGS.md](./AUDIT_FINDINGS.md)
|
|
457
|
+
- **API Reference**: See source code JSDoc comments
|
|
458
|
+
- **Examples**: [`src/examples/`](./src/examples/)
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## Development
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
# Install dependencies
|
|
466
|
+
pnpm install
|
|
467
|
+
|
|
468
|
+
# Run tests
|
|
469
|
+
pnpm --filter=@repo/analytics test
|
|
470
|
+
|
|
471
|
+
# Type check
|
|
472
|
+
pnpm --filter=@repo/analytics typecheck
|
|
473
|
+
|
|
474
|
+
# Lint
|
|
475
|
+
pnpm --filter=@repo/analytics lint
|
|
476
|
+
|
|
477
|
+
# Coverage
|
|
478
|
+
pnpm --filter=@repo/analytics test:coverage
|
|
479
|
+
|
|
480
|
+
# Check circular deps
|
|
481
|
+
pnpm --filter=@repo/analytics circular
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
---
|
|
485
|
+
|
|
486
|
+
## Support
|
|
487
|
+
|
|
488
|
+
- **Issues**: [GitHub Issues](https://github.com/your-org/monorepo/issues)
|
|
489
|
+
- **Discussions**: [GitHub Discussions](https://github.com/your-org/monorepo/discussions)
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## License
|
|
494
|
+
|
|
495
|
+
MIT License
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
**Built with ❤️ by the Platform Team**
|
|
500
|
+
|
|
501
|
+
## 📚 Comprehensive Documentation
|
|
502
|
+
|
|
503
|
+
For detailed documentation, see:
|
|
504
|
+
|
|
505
|
+
- **[Audit Reports](../../apps/docs/content/docs/audits/analytics/)** - Comprehensive audits, fixes, and security
|
|
506
|
+
reviews
|
|
507
|
+
- **[Technical Guides](../../apps/docs/content/docs/packages/analytics/)** - Implementation guides and best practices
|
|
508
|
+
|
|
509
|
+
All comprehensive documentation has been centralized in the docs app.
|