@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
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Next.js client-side analytics implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides client-side analytics functionality for Next.js applications.
|
|
5
|
+
* Includes consent management, event buffering, and PostHog bootstrap integration.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* This implementation is optimized for Next.js client components:
|
|
9
|
+
* - Supports consent-based initialization
|
|
10
|
+
* - Buffers events before initialization
|
|
11
|
+
* - Integrates with Next.js Script component
|
|
12
|
+
* - Handles PostHog bootstrap data for SSR
|
|
13
|
+
*
|
|
14
|
+
* @module @od-oneapp/analytics/next/client
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { type AnalyticsManager } from '../shared/utils/manager';
|
|
18
|
+
import { createPostHogConfig } from '../shared/utils/posthog-client-utils';
|
|
19
|
+
|
|
20
|
+
import type { BootstrapData } from '../shared/types/posthog-types';
|
|
21
|
+
import type { AnalyticsConfig, TrackingOptions } from '../shared/types/types';
|
|
22
|
+
|
|
23
|
+
export interface NextJSClientAnalyticsConfig extends AnalyticsConfig {
|
|
24
|
+
nextjs?: {
|
|
25
|
+
// Next.js Script loading strategy
|
|
26
|
+
strategy?: 'afterInteractive' | 'beforeInteractive' | 'lazyOnload' | 'worker' | undefined;
|
|
27
|
+
|
|
28
|
+
// Defer initialization until user consent
|
|
29
|
+
deferUntilConsent?: boolean | undefined;
|
|
30
|
+
|
|
31
|
+
// Buffer events before initialization
|
|
32
|
+
bufferEvents?: boolean | undefined;
|
|
33
|
+
|
|
34
|
+
// Maximum events to buffer
|
|
35
|
+
maxBufferSize?: number | undefined;
|
|
36
|
+
|
|
37
|
+
// Custom consent check function
|
|
38
|
+
checkConsent?: (() => boolean | Promise<boolean>) | undefined;
|
|
39
|
+
|
|
40
|
+
// Enable debug mode
|
|
41
|
+
debug?: boolean | undefined;
|
|
42
|
+
|
|
43
|
+
// PostHog specific options
|
|
44
|
+
posthog?: {
|
|
45
|
+
// Server-side bootstrap data
|
|
46
|
+
bootstrap?: BootstrapData | undefined;
|
|
47
|
+
|
|
48
|
+
// API key for client operations
|
|
49
|
+
apiKey?: string | undefined;
|
|
50
|
+
|
|
51
|
+
// Host override
|
|
52
|
+
host?: string | undefined;
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface BufferedEvent {
|
|
58
|
+
args: any[];
|
|
59
|
+
method: 'track' | 'identify' | 'page' | 'group' | 'alias';
|
|
60
|
+
timestamp: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export class NextJSClientAnalyticsManager {
|
|
64
|
+
private manager: AnalyticsManager | null = null;
|
|
65
|
+
private config: NextJSClientAnalyticsConfig;
|
|
66
|
+
private isInitialized = false;
|
|
67
|
+
private isLoading = false;
|
|
68
|
+
private eventBuffer: BufferedEvent[] = [];
|
|
69
|
+
private consentGiven = false;
|
|
70
|
+
|
|
71
|
+
constructor(config: NextJSClientAnalyticsConfig) {
|
|
72
|
+
this.config = config;
|
|
73
|
+
|
|
74
|
+
// Check if we should buffer events
|
|
75
|
+
if (config.nextjs?.bufferEvents !== false) {
|
|
76
|
+
this.setupEventBuffering();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Auto-initialize if no consent required
|
|
80
|
+
if (!config.nextjs?.deferUntilConsent) {
|
|
81
|
+
void this.initializeWhenReady();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Initialize analytics when DOM is ready
|
|
87
|
+
*/
|
|
88
|
+
private async initializeWhenReady(): Promise<void> {
|
|
89
|
+
if (typeof window === 'undefined') return;
|
|
90
|
+
|
|
91
|
+
// Wait for DOM to be ready
|
|
92
|
+
if (document.readyState === 'loading') {
|
|
93
|
+
await new Promise(resolve => {
|
|
94
|
+
document.addEventListener('DOMContentLoaded', resolve, { once: true });
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
await this.initialize();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Initialize analytics with consent check
|
|
103
|
+
*/
|
|
104
|
+
async initialize(): Promise<void> {
|
|
105
|
+
if (this.isInitialized || this.isLoading) return;
|
|
106
|
+
this.isLoading = true;
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
// Check consent if required
|
|
110
|
+
if (this.config.nextjs?.deferUntilConsent) {
|
|
111
|
+
const hasConsent = await this.checkConsent();
|
|
112
|
+
if (!hasConsent) {
|
|
113
|
+
// Analytics initialization deferred - no consent
|
|
114
|
+
this.isLoading = false;
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Import only what we need for Next.js environment
|
|
120
|
+
const { createAnalyticsManager } = await import('../shared/utils/manager');
|
|
121
|
+
const { ConsoleProvider } = await import('../shared/providers/console-provider');
|
|
122
|
+
|
|
123
|
+
const CLIENT_PROVIDERS: any = {
|
|
124
|
+
console: (config: any) => new ConsoleProvider(config),
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Only import providers that are configured
|
|
128
|
+
const configuredProviders = Object.keys(this.config.providers);
|
|
129
|
+
|
|
130
|
+
// Dynamically import only configured providers to avoid webpack bundling unused ones
|
|
131
|
+
for (const providerName of configuredProviders) {
|
|
132
|
+
if (providerName === 'console') continue; // Already loaded above
|
|
133
|
+
|
|
134
|
+
switch (providerName) {
|
|
135
|
+
case 'posthog': {
|
|
136
|
+
const { PostHogClientProvider } = await import('../providers/posthog/client');
|
|
137
|
+
CLIENT_PROVIDERS.posthog = (config: any) => new PostHogClientProvider(config);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case 'segment': {
|
|
141
|
+
const { SegmentClientProvider } = await import('../providers/segment/client');
|
|
142
|
+
CLIENT_PROVIDERS.segment = (config: any) => new SegmentClientProvider(config);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case 'vercel': {
|
|
146
|
+
const { VercelClientProvider } = await import('../providers/vercel/client');
|
|
147
|
+
CLIENT_PROVIDERS.vercel = (config: any) => new VercelClientProvider(config);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
default:
|
|
151
|
+
// Skip unknown providers
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
this.manager = createAnalyticsManager(this.config, CLIENT_PROVIDERS);
|
|
157
|
+
await this.manager.initialize();
|
|
158
|
+
this.isInitialized = true;
|
|
159
|
+
this.consentGiven = true;
|
|
160
|
+
|
|
161
|
+
// Flush buffered events
|
|
162
|
+
await this.flushBufferedEvents();
|
|
163
|
+
|
|
164
|
+
// Analytics initialized successfully
|
|
165
|
+
} catch {
|
|
166
|
+
// Failed to initialize analytics
|
|
167
|
+
} finally {
|
|
168
|
+
this.isLoading = false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Grant consent and initialize analytics
|
|
174
|
+
*/
|
|
175
|
+
async grantConsent(): Promise<void> {
|
|
176
|
+
this.consentGiven = true;
|
|
177
|
+
await this.initialize();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Revoke consent and clear data
|
|
182
|
+
*/
|
|
183
|
+
revokeConsent(): void {
|
|
184
|
+
this.consentGiven = false;
|
|
185
|
+
this.isInitialized = false;
|
|
186
|
+
this.manager = null;
|
|
187
|
+
this.eventBuffer = [];
|
|
188
|
+
|
|
189
|
+
// Analytics consent revoked
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Check consent status
|
|
194
|
+
*/
|
|
195
|
+
private async checkConsent(): Promise<boolean> {
|
|
196
|
+
if (this.consentGiven) return true;
|
|
197
|
+
|
|
198
|
+
if (this.config.nextjs?.checkConsent) {
|
|
199
|
+
return await this.config.nextjs.checkConsent();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return !this.config.nextjs?.deferUntilConsent;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Setup event buffering
|
|
207
|
+
*/
|
|
208
|
+
private setupEventBuffering(): void {
|
|
209
|
+
const maxSize = this.config.nextjs?.maxBufferSize ?? 50;
|
|
210
|
+
|
|
211
|
+
// Ensure buffer doesn't grow too large
|
|
212
|
+
const intervalId = setInterval(() => {
|
|
213
|
+
if (this.eventBuffer.length > maxSize) {
|
|
214
|
+
this.eventBuffer = this.eventBuffer.slice(-maxSize);
|
|
215
|
+
// Analytics buffer trimmed
|
|
216
|
+
}
|
|
217
|
+
}, 5000);
|
|
218
|
+
// Store interval ID for potential cleanup (not used currently)
|
|
219
|
+
void intervalId;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Buffer an event if not initialized
|
|
224
|
+
*/
|
|
225
|
+
private bufferEvent(method: BufferedEvent['method'], args: any[]): void {
|
|
226
|
+
if (!this.config.nextjs?.bufferEvents) return;
|
|
227
|
+
|
|
228
|
+
this.eventBuffer.push({
|
|
229
|
+
args,
|
|
230
|
+
method,
|
|
231
|
+
timestamp: Date.now(),
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
// Event buffered
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Flush all buffered events
|
|
239
|
+
*/
|
|
240
|
+
private async flushBufferedEvents(): Promise<void> {
|
|
241
|
+
if (!this.manager || this.eventBuffer.length === 0) return;
|
|
242
|
+
|
|
243
|
+
// Flushing buffered events
|
|
244
|
+
|
|
245
|
+
const events = [...this.eventBuffer];
|
|
246
|
+
this.eventBuffer = [];
|
|
247
|
+
|
|
248
|
+
for (const event of events) {
|
|
249
|
+
try {
|
|
250
|
+
switch (event.method) {
|
|
251
|
+
case 'track':
|
|
252
|
+
await this.manager.track(event.args[0], event.args[1], event.args[2]);
|
|
253
|
+
break;
|
|
254
|
+
case 'identify':
|
|
255
|
+
await this.manager.identify(event.args[0], event.args[1], event.args[2]);
|
|
256
|
+
break;
|
|
257
|
+
case 'page':
|
|
258
|
+
await this.manager.page(event.args[0], event.args[1], event.args[2]);
|
|
259
|
+
break;
|
|
260
|
+
case 'group':
|
|
261
|
+
await this.manager.group(event.args[0], event.args[1], event.args[2]);
|
|
262
|
+
break;
|
|
263
|
+
case 'alias':
|
|
264
|
+
await this.manager.alias(event.args[0], event.args[1], event.args[2]);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
} catch {
|
|
268
|
+
// Error flushing buffered event
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Track an event (with buffering support)
|
|
275
|
+
*/
|
|
276
|
+
async track(event: string, properties?: any, options?: TrackingOptions): Promise<void> {
|
|
277
|
+
if (this.isInitialized && this.manager) {
|
|
278
|
+
await this.manager.track(event, properties, options);
|
|
279
|
+
} else if (this.config.nextjs?.bufferEvents !== false) {
|
|
280
|
+
this.bufferEvent('track', [event, properties, options]);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Identify a user (with buffering support)
|
|
286
|
+
*/
|
|
287
|
+
async identify(userId: string, traits?: any, options?: TrackingOptions): Promise<void> {
|
|
288
|
+
if (this.isInitialized && this.manager) {
|
|
289
|
+
await this.manager.identify(userId, traits, options);
|
|
290
|
+
} else if (this.config.nextjs?.bufferEvents !== false) {
|
|
291
|
+
this.bufferEvent('identify', [userId, traits, options]);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Track a page view (with buffering support)
|
|
297
|
+
*/
|
|
298
|
+
async page(name?: string, properties?: any, options?: TrackingOptions): Promise<void> {
|
|
299
|
+
if (this.isInitialized && this.manager) {
|
|
300
|
+
await this.manager.page(name, properties, options);
|
|
301
|
+
} else if (this.config.nextjs?.bufferEvents !== false) {
|
|
302
|
+
this.bufferEvent('page', [name, properties, options]);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Track a group (with buffering support)
|
|
308
|
+
*/
|
|
309
|
+
async group(groupId: string, traits?: any, options?: TrackingOptions): Promise<void> {
|
|
310
|
+
if (this.isInitialized && this.manager) {
|
|
311
|
+
await this.manager.group(groupId, traits, options);
|
|
312
|
+
} else if (this.config.nextjs?.bufferEvents !== false) {
|
|
313
|
+
this.bufferEvent('group', [groupId, traits, options]);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Alias a user (with buffering support)
|
|
319
|
+
*/
|
|
320
|
+
async alias(userId: string, previousId: string, options?: TrackingOptions): Promise<void> {
|
|
321
|
+
if (this.isInitialized && this.manager) {
|
|
322
|
+
await this.manager.alias(userId, previousId, options);
|
|
323
|
+
} else if (this.config.nextjs?.bufferEvents !== false) {
|
|
324
|
+
this.bufferEvent('alias', [userId, previousId, options]);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Get initialization status
|
|
330
|
+
*/
|
|
331
|
+
getStatus() {
|
|
332
|
+
return {
|
|
333
|
+
activeProviders: this.manager?.getActiveProviders() ?? [],
|
|
334
|
+
bufferedEvents: this.eventBuffer.length,
|
|
335
|
+
consentGiven: this.consentGiven,
|
|
336
|
+
isInitialized: this.isInitialized,
|
|
337
|
+
isLoading: this.isLoading,
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Create a Next.js optimized analytics instance for client
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```typescript
|
|
347
|
+
* const analytics = createNextJSClientAnalytics({
|
|
348
|
+
* providers: { posthog: { apiKey: 'phc_xxx' } },
|
|
349
|
+
* nextjs: { deferUntilConsent: true },
|
|
350
|
+
* });
|
|
351
|
+
* await analytics.initialize();
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
354
|
+
export function createNextJSClientAnalytics(
|
|
355
|
+
config: NextJSClientAnalyticsConfig,
|
|
356
|
+
): NextJSClientAnalyticsManager {
|
|
357
|
+
return new NextJSClientAnalyticsManager(config);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Next.js Script component integration helper
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* ```tsx
|
|
365
|
+
* <Script {...getAnalyticsScriptProps('afterInteractive')} src="/analytics.js" />
|
|
366
|
+
* ```
|
|
367
|
+
*/
|
|
368
|
+
export function getAnalyticsScriptProps(
|
|
369
|
+
strategy: 'afterInteractive' | 'beforeInteractive' | 'lazyOnload' = 'afterInteractive',
|
|
370
|
+
) {
|
|
371
|
+
return {
|
|
372
|
+
onLoad: () => {
|
|
373
|
+
if (typeof window !== 'undefined') {
|
|
374
|
+
// Analytics scripts have loaded, can now initialize
|
|
375
|
+
window.dispatchEvent(new CustomEvent('analytics:scripts-loaded'));
|
|
376
|
+
}
|
|
377
|
+
},
|
|
378
|
+
strategy,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Create PostHog config with bootstrap data for client
|
|
384
|
+
*
|
|
385
|
+
* @example
|
|
386
|
+
* ```typescript
|
|
387
|
+
* const config = createPostHogConfigWithBootstrap(apiKey, bootstrapData);
|
|
388
|
+
* const analytics = createNextJSClientAnalytics(config);
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
export function createPostHogConfigWithBootstrap(
|
|
392
|
+
apiKey: string,
|
|
393
|
+
bootstrapData: BootstrapData,
|
|
394
|
+
options?: {
|
|
395
|
+
host?: string;
|
|
396
|
+
autocapture?: boolean;
|
|
397
|
+
capture_pageview?: boolean;
|
|
398
|
+
session_recording?: boolean;
|
|
399
|
+
debug?: boolean;
|
|
400
|
+
},
|
|
401
|
+
): NextJSClientAnalyticsConfig {
|
|
402
|
+
const posthogConfig = createPostHogConfig(apiKey, {
|
|
403
|
+
...options,
|
|
404
|
+
bootstrap: bootstrapData,
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
return {
|
|
408
|
+
providers: {
|
|
409
|
+
posthog: posthogConfig,
|
|
410
|
+
},
|
|
411
|
+
nextjs: {
|
|
412
|
+
posthog: {
|
|
413
|
+
apiKey,
|
|
414
|
+
bootstrap: bootstrapData,
|
|
415
|
+
...(options?.host !== undefined && { host: options.host }),
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
};
|
|
419
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Next.js Analytics Integration
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive analytics solution for Next.js 15 with App Router support.
|
|
5
|
+
* Provides client-side, server-side, React Server Component, middleware, and
|
|
6
|
+
* App Router integrations for analytics tracking.
|
|
7
|
+
*
|
|
8
|
+
* @module @od-oneapp/analytics/next
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
// Client-side exports
|
|
12
|
+
export {
|
|
13
|
+
NextJSClientAnalyticsManager,
|
|
14
|
+
createNextJSClientAnalytics,
|
|
15
|
+
createPostHogConfigWithBootstrap,
|
|
16
|
+
getAnalyticsScriptProps,
|
|
17
|
+
type NextJSClientAnalyticsConfig,
|
|
18
|
+
} from './client';
|
|
19
|
+
|
|
20
|
+
// Server-side exports
|
|
21
|
+
export {
|
|
22
|
+
NextJSServerAnalyticsManager,
|
|
23
|
+
createNextJSServerAnalytics,
|
|
24
|
+
createNextJSServerAnalyticsWithBootstrap,
|
|
25
|
+
getPostHogBootstrapDataOnServer,
|
|
26
|
+
type NextJSServerAnalyticsConfig,
|
|
27
|
+
} from './server';
|
|
28
|
+
|
|
29
|
+
// React Server Component exports
|
|
30
|
+
export {
|
|
31
|
+
ServerAnalyticsProvider,
|
|
32
|
+
getServerBootstrapData,
|
|
33
|
+
identifyServerUser,
|
|
34
|
+
identifyUserAction,
|
|
35
|
+
trackEventAction,
|
|
36
|
+
trackServerEvent,
|
|
37
|
+
trackServerPageView,
|
|
38
|
+
withServerPageTracking,
|
|
39
|
+
} from './rsc';
|
|
40
|
+
|
|
41
|
+
// App Router specific exports
|
|
42
|
+
export {
|
|
43
|
+
AnalyticsProvider as ClientAnalyticsProvider,
|
|
44
|
+
TrackedButton,
|
|
45
|
+
TrackedLink,
|
|
46
|
+
resetAnalytics,
|
|
47
|
+
useAnalytics,
|
|
48
|
+
useAnalyticsConsent,
|
|
49
|
+
useEcommerceTracking,
|
|
50
|
+
useFormTracking,
|
|
51
|
+
useIdentifyUser,
|
|
52
|
+
usePageTracking,
|
|
53
|
+
useTrackEvent,
|
|
54
|
+
withViewTracking,
|
|
55
|
+
} from './app-router';
|
|
56
|
+
|
|
57
|
+
// Middleware exports
|
|
58
|
+
export {
|
|
59
|
+
composeMiddleware,
|
|
60
|
+
conditionalAnalyticsMiddleware,
|
|
61
|
+
createAnalyticsMiddleware,
|
|
62
|
+
createAnalyticsMiddlewareConfig,
|
|
63
|
+
getAnalyticsContextFromHeaders,
|
|
64
|
+
getDistinctIdFromHeaders,
|
|
65
|
+
type AnalyticsMiddlewareConfig,
|
|
66
|
+
} from './middleware';
|
|
67
|
+
|
|
68
|
+
// Re-export types
|
|
69
|
+
export type {
|
|
70
|
+
AnalyticsConfig,
|
|
71
|
+
AnalyticsContext,
|
|
72
|
+
AnalyticsProvider,
|
|
73
|
+
ProviderConfig,
|
|
74
|
+
TrackingOptions,
|
|
75
|
+
} from '../shared/types/types';
|
|
76
|
+
|
|
77
|
+
export type { BootstrapData, PostHogConfig } from '../shared/types/posthog-types';
|
|
78
|
+
|
|
79
|
+
// Export utilities
|
|
80
|
+
export {
|
|
81
|
+
createBootstrapData,
|
|
82
|
+
generateDistinctId,
|
|
83
|
+
getDistinctIdFromCookies,
|
|
84
|
+
} from '../shared/utils/posthog-bootstrap';
|